Skip to content

Commit

Permalink
forward toolbox creation over to the observation window, #20
Browse files Browse the repository at this point in the history
  • Loading branch information
zepumph committed Feb 24, 2025
1 parent 9889269 commit 792452d
Show file tree
Hide file tree
Showing 5 changed files with 18 additions and 73 deletions.
1 change: 1 addition & 0 deletions js/common/model/MembraneChannelsModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ export default class MembraneChannelsModel extends PhetioObject {
public getSlotPosition( slot: Slot ): number {
return SLOT_POSITIONS[ slots.indexOf( slot ) ];
}

public readonly slots = slots;

public readonly timeSpeedProperty: EnumerationProperty<TimeSpeed>;
Expand Down
67 changes: 1 addition & 66 deletions js/common/view/ChannelDragNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,10 @@
import DerivedProperty from '../../../../axon/js/DerivedProperty.js';
import TReadOnlyProperty from '../../../../axon/js/TReadOnlyProperty.js';
import Bounds2 from '../../../../dot/js/Bounds2.js';
import Utils from '../../../../dot/js/Utils.js';
import Vector2 from '../../../../dot/js/Vector2.js';
import Vector2Property from '../../../../dot/js/Vector2Property.js';
import ModelViewTransform2 from '../../../../phetcommon/js/view/ModelViewTransform2.js';
import DragListener from '../../../../scenery/js/listeners/DragListener.js';
import KeyboardListener from '../../../../scenery/js/listeners/KeyboardListener.js';
import { PressListenerEvent } from '../../../../scenery/js/listeners/PressListener.js';
import Node from '../../../../scenery/js/nodes/Node.js';
import Tandem from '../../../../tandem/js/Tandem.js';
Expand Down Expand Up @@ -69,10 +67,9 @@ export default class ChannelDragNode extends Node {
return slotDragIndicatorNode.globalBounds.intersectsBounds( this.globalBounds ) && !model.isSlotFilled( slotDragIndicatorNode.slot );
} );

const closest = _.sortBy( overlappingSlotDragIndicatorNodes, slotDragIndicatorNode => {
return _.sortBy( overlappingSlotDragIndicatorNodes, slotDragIndicatorNode => {
return slotDragIndicatorNode.globalBounds.center.distance( this.globalBounds.center );
} )[ 0 ];
return closest;
};

// eslint-disable-next-line consistent-this,@typescript-eslint/no-this-alias
Expand Down Expand Up @@ -148,68 +145,6 @@ export default class ChannelDragNode extends Node {
} );
this.addInputListener( this.dragListener );

let currentSlotIndex = initSlot === null ? 0 : model.getSlotIndex( initSlot );

// TODO: Move on hold
const keyboardInputListener = new KeyboardListener( {

// TODO: esc goes back to the toolbox
// TODO: on blur also go back to the toolbox
keys: [ 'arrowRight', 'arrowLeft', 'home', 'end', 'space', 'enter' ],
fire: ( event, keysPressed ) => {

if ( keysPressed.includes( 'arrowRight' ) ) {
console.log( 'right' );

// move to the next slot in the model.
currentSlotIndex++;
currentSlotIndex = Utils.clamp( currentSlotIndex, 0, model.slots.length );
if ( currentSlotIndex >= model.slots.length ) {
this.positionProperty.value = new Vector2( 100, 50 );
}
else {
const x = model.getSlotPosition( model.getSlotForIndex( currentSlotIndex ) );
this.positionProperty.value = new Vector2( x, 10 );
}
}
if ( keysPressed.includes( 'arrowLeft' ) ) {
// move to the next slot in the model.
currentSlotIndex--;
currentSlotIndex = Utils.clamp( currentSlotIndex, 0, model.slots.length - 1 );

const x = model.getSlotPosition( model.getSlotForIndex( currentSlotIndex ) );
this.positionProperty.value = new Vector2( x, 10 );
}

if ( keysPressed.includes( 'home' ) ) {
//TODO:
}
if ( keysPressed.includes( 'end' ) ) {
//TODO:
}
if ( keysPressed.includes( 'space' ) || keysPressed.includes( 'enter' ) ) {

if ( currentSlotIndex >= model.slots.length ) {
this.dispose();
homes[ 0 ].focus();
}
else {
// if over an empty slot, fill it and delete the node
// const contents = model.getSlotContents( model.getSlotForIndex( currentSlotIndex ) );

// TODO: When dropping with mouse, it should also replace.
model.setSlotContents( model.getSlotForIndex( currentSlotIndex ), this.type );
this.dispose();

homes[ 0 ].focus();

// // TODO: Same as above, but we may want to animate the old one back to the toolbox. Is animation valuable here, or would be a distraction?
}
}
}
} );
this.addInputListener( keyboardInputListener );

// TODO: Interactive highlight?
// this.setInteractiveHighlight( new HighlightFromNode( this ) );
}
Expand Down
2 changes: 1 addition & 1 deletion js/common/view/ChannelToolNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export default class ChannelToolNode extends VBox {
return {
click: () => {

view.createFromKeyboard( type, [ this, channelNode ], true ); // TODO: swapped with the mouse one, watch out!!!!
view.forwardFromKeyboard( type );
}
};
};
Expand Down
19 changes: 14 additions & 5 deletions js/common/view/MembraneChannelsScreenView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -248,13 +248,26 @@ export default class MembraneChannelsScreenView extends ScreenView {
membraneChannelNode.press( event );
}

public forwardFromKeyboard( type: ChannelType ): void {
const slot = this.model.getLeftmostEmptySlot() || this.model.getMiddleSlot();

this.model.setSlotContents( slot, type );

// TODO: There must be a better way to do this internally, https://github.com/phetsims/membrane-channels/issues/20
this.observationWindow.focus();
this.observationWindow.membraneGroupSortInteractionView.model.selectedGroupItemProperty.value = this.model.getSlotIndex( slot );
this.observationWindow.membraneGroupSortInteractionView.model.isGroupItemKeyboardGrabbedProperty.value = true;
this.observationWindow.membraneGroupSortInteractionView.model.hasKeyboardGrabbedGroupItemProperty.value = true;
this.observationWindow.membraneGroupSortInteractionView.model.isKeyboardFocusedProperty.value = true;
}

/**
* Called when the user presses a membrane protein in the accordion box to create one.
*
* @param type
* @param homes - the nodes that the membrane protein can be returned to, in sequential order (1st visible one takes precedence)
*/
public createFromKeyboard( type: ChannelType, homes: Node[], focus: boolean ): ChannelDragNode {
public createFromKeyboard( type: ChannelType, homes: Node[] ): ChannelDragNode {

// TODO: duplicated with create from mouse
// Move over the first available slot
Expand All @@ -270,10 +283,6 @@ export default class MembraneChannelsScreenView extends ScreenView {
);
this.addChild( channelDragNode );

if ( focus ) {
channelDragNode.focus();
}

// TODO: once keyboarded, prevent mouse+touch, or do this on init
// channelDragNode.pickable = false; // keyboard only

Expand Down
2 changes: 1 addition & 1 deletion js/common/view/ObservationWindow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export default class ObservationWindow extends InteractiveHighlightingNode {
private readonly stepEmitter = new Emitter<[ number ]>( {
parameters: [ { valueType: 'number' } ]
} );
private readonly membraneGroupSortInteractionView: MembraneGroupSortInteractionView;
public readonly membraneGroupSortInteractionView: MembraneGroupSortInteractionView;

public constructor( private readonly model: MembraneChannelsModel, view: MembraneChannelsScreenView,
public readonly modelViewTransform: ModelViewTransform2, canvasBounds: Bounds2, tandem: Tandem ) {
Expand Down

0 comments on commit 792452d

Please sign in to comment.