documentationfor yFiles for HTML 2.6

Selection

General

The selection state of items is maintained by the IGraphSelection instance found in GraphComponent’s selection property. The IGraphSelection provides ISelectionModel<T> instances for each type of graph items. It also allows querying and changing the selection state for each model item.

Selection models available on IGraphSelection
selectedNodes
selectedLabels
selectedEdges
selectedPorts
selectedBends
ISelectionModel<T>s for the different types of graph items.
Methods for querying and setting the selection state on
isSelected(item: T): boolean
Whether the given model item is selected.
setSelected(item: T, selected: boolean): void
Setting the selection state of the given item to selected (true) or unselected (false).
clear(): void
Set all model items maintained by the selection model to unselected.

Interactive selection of graph items is supported by both GraphEditorInputMode and GraphViewerInputMode. Both provide access to the selection they manage through property graphSelection. This is the same instance found in the selection property of the GraphComponent these input modes manage.

Both modes provide convenience methods to directly select or deselect a single item as well as all marquee-selectable items in a given area: setSelected(IModelItem, boolean) and marqueeSelect(Rect).

GraphEditorInputMode and GraphViewerInputMode support three ways of selecting elements interactively: selection by mouse click or tap, marquee selection, and the select all command. The items which are handled by these kinds of selection can be defined using the …​SelectableItems properties. These properties define the item types which can be selected using a combination of the values defined in GraphItemTypes.

Finer control can be achieved by overriding the should…​Select methods:

Member Interaction Description
selectableItemsclick, marquee, lasso, select allDetermines which types of graph items are selectable.
selectablePredicateclick, marquee, lasso, select allA predicate function which determines whether the given item should be selected.
shouldSelectItem(item: IModelItem): booleanclick, marquee, lasso, select allWhether the given item should be selected. Can be overridden for customization.
clickSelectableItemsclickDetermines which types of graph items are selectable by mouse click or tap. Note that this is treated as a subset of selectableItems.
shouldClickSelect(item: IModelItem): booleanclickWhether the given item should be selected by mouse click or tap. Can be overridden for customization.
marqueeSelectableItemsmarquee, lassoDetermines which types of graph items are marquee selectable.
shouldMarqueeSelect(item: IModelItem): booleanmarquee, lassoWhether the given item should be selected by marquee selection. Can be overridden for customization.

Instead of overriding the shouldSelectItem method you can set a predicate function using the selectablePredicate property.

Note that an item is only selected if all conditions are met. For example, an item is only considered for click selection if its type is set in both selectableItems and clickSelectableItems. More, click selection is only handled for items which are clickable, see section Customizing Mouse Clicks.

IGraphSelection dispatches an event for each item whose selection state changes, the ItemSelectionChanged event. On a higher level, both GraphEditorInputMode and GraphViewerInputMode dispatch events at the beginning and the end of a user interaction which changes the selection state of one or more graph items: MultiSelectionStarted and MultiSelectionFinished. Despite their name these events are also dispatched when the state of only one item changes.

Related events
Event Occurs when …​
GraphEditorInputMode.MultiSelectionStarted…​ the selection state of one or more items is about to be changed as a result of a user interaction.
ISelectionModel<T>.ItemSelectionChanged…​ the selection state of a graph item has changed.
GraphEditorInputMode.MultiSelectionFinished…​ the selection state of one or more items has been changed as a result of a user interaction.

  • The ItemSelectionChanged event is also dispatched upon programmatic selection changes.
  • For each affected item one ItemSelectionChanged event is dispatched, even if the changes happen in one method call or upon one single interaction.
  • For user interaction driven changes, all ItemSelectionChanged events are dispatched in between a MultiSelectionStarted and a MultiSelectionFinished event.

You can make further click selection customizations by modifying the click or touch handling as discussed in sections Customizing Mouse Clicks and Customizing Touch Gestures.

The highlighting visualization of selected elements themselves can be customized as described in section Styling Selection, Focus, and Highlight.

Marquee selection

For marquee selection GraphEditorInputMode and GraphViewerInputMode let their child input mode MarqueeSelectionInputMode handle the marquee rectangle. MarqueeSelectionInputMode allows customization by changing the recognizers for some gestures. This might be of importance to avoid conflicts with input modes which share the same gesture (i.e. dragging on an empty canvas), e.g. MoveViewportInputMode.

pressedRecognizer
An event recognizer which returns true if the given event should be recognized as a mouse down gesture that might start a marquee selection.
draggedRecognizer
An event recognizer which returns true if the given event should be recognized as a drag gesture. This is only queried if the MarqueeSelectionInputMode is already activated by a previous gesture.
releasedRecognizer
An event recognizer which returns true if the given event should be recognized as a valid gesture to successfully finish the marquee selection.

GraphViewerInputMode has different recognizers than GraphEditorInputMode for marquee selection and its MarqueeSelectionInputMode is disabled by default.

During the drag gesture MarqueeSelectionInputMode dispatches a sequence of events:

Related events
Event Occurs when …​
DragStarting…​ a drag gesture is recognized, before the input mode is initialized for dragging.
DragStarted…​ a drag gesture is recognized, after the input mode is initialized for dragging.
Dragging…​ the mouse moves during drag operations and before the actual drag is performed.
Dragged…​ the mouse moves during drag operations and after the actual drag is performed.
DragCanceling…​ the drag gesture is canceled before the input mode has been cleaned up.
DragCanceled…​ the drag gesture is canceled after the input mode has been cleaned up.
DragFinishing…​ a drag gesture has ended successfully before the actual drag operations have been finished.
DragFinished…​ a drag gesture has ended successfully after the actual drag operations have been finished.

The visualization of the marquee rectangle can be customized by setting a custom IVisualTemplate to MarqueeSelectionInputMode’s template property or by registering a custom IVisualTemplate with the resource keyMARQUEE_RECTANGLE_TEMPLATE_KEY.

// Create a new RectangleTemplate
const rectangleTemplate = new (class extends BaseClass(IVisualTemplate) {
  /**
   * @param {!IRenderContext} context
   * @param {!Rect} bounds
   * @param {*} dataObject
   * @returns {?SvgVisual}
   */
  createVisual(context, bounds, dataObject) {
    const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect')
    rect.setAttribute('stroke-width', '1')
    rect.setAttribute('stroke', 'red')
    rect.setAttribute('stroke-dasharray', '1.5, 1.5')
    rect.setAttribute('fill', 'red')
    rect.setAttribute('fill-opacity', '0.25')
    rect.x.baseVal.value = bounds.x
    rect.y.baseVal.value = bounds.y
    rect.width.baseVal.value = bounds.width
    rect.height.baseVal.value = bounds.height
    return new SvgVisual(rect)
  }

  /**
   * @param {!IRenderContext} context
   * @param {!SvgVisual} oldVisual
   * @param {!Rect} bounds
   * @param {*} dataObject
   * @returns {?SvgVisual}
   */
  updateVisual(context, oldVisual, bounds, dataObject) {
    const rect = oldVisual.svgElement
    rect.x.baseVal.value = bounds.x
    rect.y.baseVal.value = bounds.y
    rect.width.baseVal.value = bounds.width
    rect.height.baseVal.value = bounds.height
    return oldVisual
  }
})()

// Set this template as the one to use for drawing the marquee selection rectangle
graphEditorInputMode.marqueeSelectionInputMode.template = rectangleTemplate

// Create a new RectangleTemplate
const rectangleTemplate = new (class extends BaseClass(IVisualTemplate) {
  createVisual(context: IRenderContext, bounds: Rect, dataObject: any): SvgVisual | null {
    const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect')
    rect.setAttribute('stroke-width', '1')
    rect.setAttribute('stroke', 'red')
    rect.setAttribute('stroke-dasharray', '1.5, 1.5')
    rect.setAttribute('fill', 'red')
    rect.setAttribute('fill-opacity', '0.25')
    rect.x.baseVal.value = bounds.x
    rect.y.baseVal.value = bounds.y
    rect.width.baseVal.value = bounds.width
    rect.height.baseVal.value = bounds.height
    return new SvgVisual(rect)
  }

  updateVisual(context: IRenderContext, oldVisual: SvgVisual, bounds: Rect, dataObject: any): SvgVisual | null {
    const rect = oldVisual.svgElement as SVGRectElement
    rect.x.baseVal.value = bounds.x
    rect.y.baseVal.value = bounds.y
    rect.width.baseVal.value = bounds.width
    rect.height.baseVal.value = bounds.height
    return oldVisual
  }
})()

// Set this template as the one to use for drawing the marquee selection rectangle
graphEditorInputMode.marqueeSelectionInputMode.template = rectangleTemplate

Above example results in the following marquee selection rectangle:

Custom marquee selection rectangle
customizing interaction marquee rectangle painter

You can set the cursor shown during dragging using the marqueeCursor property.

Lasso selection

Lasso selection in GraphEditorInputMode and GraphViewerInputMode is performed by their child input mode LassoSelectionInputMode, which handles drawing a path within which to select items. This child input mode is disabled by default, to avoid conflicting with marquee selection. LassoSelectionInputMode allows customization by changing the recognizers for some gestures. This might be of importance to avoid conflicts with input modes which share the same gesture (i.e. dragging on an empty canvas), e.g. MoveViewportInputMode.

By default, LassoSelectionInputMode is configured to draw the path around the selection area in a freehand gesture while dragging the mouse with the left mouse button held down. The gesture is finished after releasing the mouse button and the path is closed with a straight line from the current location to its start.

By changing one or more of its various event recognizers LassoSelectionInputMode can be configured to support a polyline path or a mixture of both freehand and straight segments. Also, it is possible to configure the input mode to finish only when the gesture is ended in an area around the start point of the path.

prepareRecognizer
prepareRecognizerTouch
event recognizers that determine when to start the gesture.
dragFreeRecognizer
event recognizer which determines when to perform a freehand drag.
finishRecognizer
finishRecognizerTouch
event recognizers which determine when to end the gesture.
startSegmentRecognizer
endSegmentRecognizer
event recognizers that determine when and how to switch from free drawing mode to segment mode.
dragSegmentRecognizer
event recognizer which determines when to draw a segment.
finishRegionRecognizer
finishRegionRecognizerTouch
finishRadius
event recognizers which determine when to end the gesture within a defined radius from the starting point and the radius itself.

GraphViewerInputMode has different recognizers than GraphEditorInputMode for lasso selection and its LassoSelectionInputMode is disabled by default.

The following settings configure LassoSelectionInputMode to support a polyline lasso, i.e. a path consisting of straight segments:

const lassoSelectionInputMode = graphEditorInputMode.lassoSelectionInputMode
lassoSelectionInputMode.dragFreeRecognizer = MouseEventRecognizers.DRAG
// start a segment immediately at the beginning of the gesture or after the last segment is ended
lassoSelectionInputMode.startSegmentRecognizer = EventRecognizers.ALWAYS
// end a segment when the mouse button is pressed or released
lassoSelectionInputMode.endSegmentRecognizer = EventRecognizers.createOrRecognizer(
  MouseEventRecognizers.LEFT_CLICK,
  MouseEventRecognizers.LEFT_UP
)
lassoSelectionInputMode.dragSegmentRecognizer = MouseEventRecognizers.MOVE_OR_DRAG
// outside the finish radius finish only with double click
lassoSelectionInputMode.finishRecognizer = MouseEventRecognizers.LEFT_DOUBLE_CLICK
// or finish within the finish radius around the start point
lassoSelectionInputMode.finishRadius = 10

Note that the gesture now can only be ended by either a double click where the path is closed automatically by drawing a straight segment between the current location and the start of the path or by ending a segment with in the finishRadius around its start point.

It is also possible to mix the freehand and the polyline gestures. The following settings configure LassoSelectionInputMode to draw a freehand path while dragging the mouse with the left button down and straight segments when the button is released. Similar to the freehand configuration the gesture now can only be finished with a double click or by pressing or releasing the mouse button within the finishRadius around its start point.

const lassoSelectionInputMode = graphEditorInputMode.lassoSelectionInputMode
// start a segment when the mouse button is released
lassoSelectionInputMode.startSegmentRecognizer = MouseEventRecognizers.LEFT_UP
// outside the finish radius finish only with double click
lassoSelectionInputMode.finishRecognizer = MouseEventRecognizers.LEFT_DOUBLE_CLICK
// or finish within the finish radius around the start point
lassoSelectionInputMode.finishRadius = 10

During the drag gesture LassoSelectionInputMode dispatches a sequence of events:

Related events
Event Occurs when …​
DragStarting…​ a drag gesture is recognized, before the input mode is initialized for dragging.
DragStarted…​ a drag gesture is recognized, after the input mode is initialized for dragging.
Dragging…​ the mouse moves during drag operations and before the actual drag is performed.
Dragged…​ the mouse moves during drag operations and after the actual drag is performed.
DragCanceling…​ the drag gesture is canceled before the input mode has been cleaned up.
DragCanceled…​ the drag gesture is canceled after the input mode has been cleaned up.
DragFinishing…​ a drag gesture has ended successfully before the actual drag operations have been finished.
DragFinished…​ a drag gesture has ended successfully after the actual drag operations have been finished.

The visualization of the path can be customized by setting the stroke and fill properties or by registering a custom Stroke or Fill with the resource keysLASSO_STROKE_KEY and LASSO_FILL_KEY.

During the gesture LassoSelectionInputMode can display an indicator for the region around the start location where the lasso gesture can be finished. Per default this indicator isn’t used but can be set via finishRegionTemplate or FINISH_REGION_TEMPLATE_KEY. When entering this region a highlight indicator is used to indicate that the gesture can now be finished. The visualization for this can be changed via finishRegionHighlightTemplate or FINISH_REGION_HIGHLIGHT_TEMPLATE_KEY.

// Set a custom stroke and fill
lassoSelectionInputMode.stroke = new Stroke({
  fill: Fill.RED,
  dashStyle: new DashStyle([2, 4], 1)
})
lassoSelectionInputMode.fill = new SolidColorFill(255, 0, 0, 65)
// Set a custom finish region visualization
lassoSelectionInputMode.finishRegionTemplate = new (class extends BaseClass(IVisualTemplate) {
  /**
   * @param {!IRenderContext} context
   * @param {!Rect} bounds
   * @param {*} dataObject
   * @returns {?SvgVisual}
   */
  createVisual(context, bounds, dataObject) {
    const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect')
    rect.setAttribute('stroke-width', '3')
    rect.setAttribute('stroke', 'darkred')
    rect.setAttribute('fill', 'none')
    rect.x.baseVal.value = bounds.x
    rect.y.baseVal.value = bounds.y
    rect.width.baseVal.value = bounds.width
    rect.height.baseVal.value = bounds.height
    return new SvgVisual(rect)
  }

  /**
   * @param {!IRenderContext} context
   * @param {!SvgVisual} oldVisual
   * @param {!Rect} bounds
   * @param {*} dataObject
   * @returns {?SvgVisual}
   */
  updateVisual(context, oldVisual, bounds, dataObject) {
    const rect = oldVisual.svgElement
    rect.x.baseVal.value = bounds.x
    rect.y.baseVal.value = bounds.y
    rect.width.baseVal.value = bounds.width
    rect.height.baseVal.value = bounds.height
    return oldVisual
  }
})()

// Set a custom finish region highlight visualization
lassoSelectionInputMode.finishRegionHighlightTemplate = new (class extends BaseClass(IVisualTemplate) {
  /**
   * @param {!IRenderContext} context
   * @param {!Rect} bounds
   * @param {*} dataObject
   * @returns {?SvgVisual}
   */
  createVisual(context, bounds, dataObject) {
    const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect')
    rect.setAttribute('stroke', 'darkred')
    rect.setAttribute('fill', 'none')
    rect.x.baseVal.value = bounds.x
    rect.y.baseVal.value = bounds.y
    rect.width.baseVal.value = bounds.width
    rect.height.baseVal.value = bounds.height
    return new SvgVisual(rect)
  }

  /**
   * @param {!IRenderContext} context
   * @param {!SvgVisual} oldVisual
   * @param {!Rect} bounds
   * @param {*} dataObject
   * @returns {?SvgVisual}
   */
  updateVisual(context, oldVisual, bounds, dataObject) {
    const rect = oldVisual.svgElement
    rect.x.baseVal.value = bounds.x
    rect.y.baseVal.value = bounds.y
    rect.width.baseVal.value = bounds.width
    rect.height.baseVal.value = bounds.height
    return oldVisual
  }
})()
// Set a custom stroke and fill
lassoSelectionInputMode.stroke = new Stroke({
  fill: Fill.RED,
  dashStyle: new DashStyle([2, 4], 1)
})
lassoSelectionInputMode.fill = new SolidColorFill(255, 0, 0, 65)
// Set a custom finish region visualization
lassoSelectionInputMode.finishRegionTemplate = new (class extends BaseClass(IVisualTemplate) {
  createVisual(context: IRenderContext, bounds: Rect, dataObject: any): SvgVisual | null {
    const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect')
    rect.setAttribute('stroke-width', '3')
    rect.setAttribute('stroke', 'darkred')
    rect.setAttribute('fill', 'none')
    rect.x.baseVal.value = bounds.x
    rect.y.baseVal.value = bounds.y
    rect.width.baseVal.value = bounds.width
    rect.height.baseVal.value = bounds.height
    return new SvgVisual(rect)
  }

  updateVisual(context: IRenderContext, oldVisual: SvgVisual, bounds: Rect, dataObject: any): SvgVisual | null {
    const rect = oldVisual.svgElement as SVGRectElement
    rect.x.baseVal.value = bounds.x
    rect.y.baseVal.value = bounds.y
    rect.width.baseVal.value = bounds.width
    rect.height.baseVal.value = bounds.height
    return oldVisual
  }
})()

// Set a custom finish region highlight visualization
lassoSelectionInputMode.finishRegionHighlightTemplate = new (class extends BaseClass(IVisualTemplate) {
  createVisual(context: IRenderContext, bounds: Rect, dataObject: any): SvgVisual | null {
    const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect')
    rect.setAttribute('stroke', 'darkred')
    rect.setAttribute('fill', 'none')
    rect.x.baseVal.value = bounds.x
    rect.y.baseVal.value = bounds.y
    rect.width.baseVal.value = bounds.width
    rect.height.baseVal.value = bounds.height
    return new SvgVisual(rect)
  }

  updateVisual(context: IRenderContext, oldVisual: SvgVisual, bounds: Rect, dataObject: any): SvgVisual | null {
    const rect = oldVisual.svgElement as SVGRectElement
    rect.x.baseVal.value = bounds.x
    rect.y.baseVal.value = bounds.y
    rect.width.baseVal.value = bounds.width
    rect.height.baseVal.value = bounds.height
    return oldVisual
  }
})()

Above example results in the following lasso selection visualization:

Custom lasso visualization
customizing interaction lasso visualization

You can set the cursor shown during dragging using the lassoCursor property.

Single Item Selection

All interactive selection gestures support selecting multiple items at the same time. Sometimes, one wants only one or no item to be selected at once. In order to enable this “single selection mode” disable MarqueeSelectionInputMode and the multiSelectionRecognizer to NEVER. Then remove SELECT_ALL and TOGGLE_ITEM_SELECTION from availableCommands and EXTEND_SELECTION_LEFT, EXTEND_SELECTION_RIGHT, EXTEND_SELECTION_UP, EXTEND_SELECTION_DOWN, SELECT_TO_PAGE_UP, and SELECT_TO_PAGE_DOWN from navigationInputMode.availableCommands. An example can be found in Single Selection.

// disable marquee selection
geim.marqueeSelectionInputMode.enabled = false
// disable multi selection with Ctrl-Click
geim.multiSelectionRecognizer = EventRecognizers.NEVER

// deactivate commands which can lead to multi selection
geim.availableCommands.remove(ICommand.TOGGLE_ITEM_SELECTION)
geim.availableCommands.remove(ICommand.SELECT_ALL)

geim.navigationInputMode.availableCommands.remove(ICommand.EXTEND_SELECTION_LEFT)
geim.navigationInputMode.availableCommands.remove(ICommand.EXTEND_SELECTION_UP)
geim.navigationInputMode.availableCommands.remove(ICommand.EXTEND_SELECTION_DOWN)
geim.navigationInputMode.availableCommands.remove(ICommand.EXTEND_SELECTION_RIGHT)

// Disable selection of (possibly multiple) items
geim.pasteSelectableItems = GraphItemTypes.NONE