yFiles for JavaFX Release Notes

yFiles for JavaFX version 2.0 is the newest major release available.
(See also the entire yFiles for JavaFX change log.) The latest release is version 2.0.0.1.

Technical Requirements

  • Oracle JDK 1.8 (8u40) or higher is needed for software development with yFiles for JavaFX.
  • Oracle JRE 1.8 (8u40) or higher is needed to execute programs using yFiles for JavaFX.
  • A browser to view the HTML documentation.

yFiles for JavaFX 2.0 - Changes Since 1.0.0.1

Full Java 8 support
New radial layout algorithm

Major Features Added

Viewer

  • Added support for Java 8.
    • Added support for streams in yFiles collection class Enumerable.

      This means that it is now possible to use the stream API with most of the data structures in the yFiles library. For example, it is now possible to write

      graph.getNodes().stream().filter(node -> node.getLabels().size() > 0);

      to retrieve all labeled nodes in an IGraph.
    • Convenience methods for many yFiles classes defined in utility classes (so-called extension classes) were added as default methods to yFiles interfaces and are thus easier to find and to use. For example, to remove all entities in proper order from a graph, instead of calling

      GraphExtensions.clear(graph)

      you can simply call the same method defined as a default method on IGraph on the graph instance:

      graph.clear()

  • GraphClipboard now supports copying independent items. This allows the user to copy labels, ports, bends, or edges to other elements without having to copy their owners. Also this technique allows for copying an item (for example a label) to multiple target elements at once.
  • The GraphClipboard now supports an optional target location for pasting and the new method GraphEditorInputMode#pasteAtLocation can be used for this end, too. In addition, ApplicationCommands#PASTE_COMMAND now supports an optional parameter of type IPoint to provide a target location.
  • GraphEditorInputMode now provides default action for duplicating single graph items or whole subgraphs. This also works with incomplete subgraphs, for example in a tree, it is possible to duplicate a subtree and the tree will never be disconnected.
    In addition, the new command GraphCommands#DUPLICATE_SELECTION_COMMAND (shortcut: Ctrl-D) and the new method GraphClipboard#duplicate can be used to duplicate selected items without altering the clipboard contents.
  • GraphEditorInputMode now provides a default action for reversing edges. To this end, the methods #reverseEdge and #reverseEdges have been added to GraphEditorInputMode. Also, the new command GraphCommands#REVERSE_EDGES_COMMAND (shortcut: Ctrl-R) has been added.
  • Node and edge labels can now snap to particular locations while moving them interactively. Both types of labels can be aligned horizontally or vertically to their original location. In addition, a node label can be aligned with the borders or the center of its owner, and during resizing of that owner, smartly keeps its relative location to the snapped position. An edge label can be snapped on the path of its owner, or at particular distances of it.
    This feature can be enabled and configured with an LabelSnapContext and is available for labels with one of these label models: SmartEdgeLabelModel, FreeEdgeLabelModel, FreeNodeLabelModel, and FreeLabelModel.
  • Interactive label editing and creation has the following new features:
    • The current label visual can be hidden while the text editor is shown to reduce visual clutter. This feature is enabled by default and can be controlled through the property GraphEditorInputMode#HidingLabelDuringEditingEnabled.
    • GraphEditorInputMode and TableEditorInputMode provide new events LabelTextEditingStarted and LabelTextEditingCanceled that are raised directly before the label text editor is shown and after the label editing has been canceled, respectively.
    • Double clicking nodes and edges now opens the label editor. An existing label can be double clicked to edit the label text. This feature can be disabled with the property GraphEditorInputMode#LabelEditingOnDoubleClickEnabled.
    • IEditLabelHelper implementations provided by the ILabel's lookup can now be used to forbid or customize the editing of individual labels. Class LabelDecorator provides a new property #EditLabelHelperDecorator to customize this feature.
    • GraphEditorInputMode#editLabel and TableEditorInputMode#editLabel can now be used with SimpleLabel instances. This provides editing capabilities for dummy elements such as legends, page headers or other textual elements.
    In addition, label editing has been reworked for a more consistent user experience. Especially, label editing now:
    • Uses the various callback methods on GraphEditorInputMode, TableEditorInputMode and IEditLabelHelper implementations in a consistent way, regardless of how many labels or labeled items are edited or added, and independent from how the editing/label creation process has been started (e.g. through a command or programmatically through the input mode convenience methods).
    • Determines the actual labeled item that is modified when multiple elements are selected in a consistent way.

Layout

  • Added new layout algorithm RadialLayouter that places nodes on concentric circles. Edges are routed in a radial fashion using one of several routing strategies.
  • Added support for terminating (layout) algorithms prematurely. To this end, new class AbortHandler provides methods for requesting early but graceful termination (see #stop) and immediate termination (see #cancel). The following layout algorithms have at least rudimentary support for immediate termination:

    Layout Algorithms
    • BalloonLayouter
    • CircularLayouter
    • CompactOrthogonalLayouter
    • DirectedOrthogonalLayouter
    • GenericTreeLayouter
    • GRIP
    • HierarchicGroupLayouter
    • HierarchicLayouter
    • IncrementalHierarchicLayouter
    • OrganicLayouter
    • OrthogonalGroupLayouter
    • OrthogonalLayouter
    • PartialLayouter
    • RadialLayouter
    • RecursiveGroupLayouter
    • SmartOrganicLayouter

    Routing Algorithms
    • BusRouter
    • EdgeRouter
    • OrganicEdgeRouter
    • OrthogonalEdgeRouter

    Other Algorithms
    • GreedyMISLabeling
    • SALabeling

    The following layout algorithms also support graceful early termination:

    Layout Algorithms
    • HierarchicGroupLayouter
    • HierarchicLayouter
    • IncrementalHierarchicLayouter
    • OrganicLayouter
    • SmartOrganicLayouter

    Routing Algorithms
    • EdgeRouter

    Other Algorithms
    • SALabeling
  • Added support for parallel execution of computationally intensive tasks.
    Layout algorithms SmartOrganicLayouter and OrganicLayouter may take advantage of multiple threads for layout calculations. Parallel execution is enabled using the algorithms' setMultiThreadingAllowed(boolean) method.
    Interface ITaskExecutor and factory classes TaskExecutorFactory make up the programmatic interface for the new concurrency support.
  • Introduced concept of node halos. Halos are reserved space around a node in which layout algorithms will not place other graph elements. Node halos are modelled using class NodeHalo. The following layout algorithms support node halos:

    Layout Algorithms
    • BalloonLayouter
    • CircularLayouter
    • CompactOrthogonalLayouter
    • ComponentLayouter
    • DirectedOrthogonalLayouter
    • GenericTreeLayouter
    • IncrementalHierarchicLayouter
    • OrthogonalGroupLayouter
    • OrthogonalLayouter
    • RadialLayouter
    • RecursiveGroupLayouter
    • SmartOrganicLayouter
    • TreeLayouter

    Routing Algorithms
    • EdgeRouter
    • SelfLoopLayouter

    Other Algorithms
    • GreedyMISLabeling
    • SALabeling
    • InsetsGroupBoundsCalculator
    • MinimumSizeGroupBoundsCalculator

  • SmartOrganicLayouter: Added support for partition grid layout. See PartitionGrid.

Minor Features Added

Viewer

  • Added class CanvasPrinter that leverages the new printing API of JavaFX 8
  • ContextMenuInputMode has now an abstract subclass to handle non-JavaFX context menu as shown in the interoperability demos.
  • LayoutExecutor can now safely handle concurrent layout requests. By default an already running layout will be short-cut and the next layout request will be processed. Property #SequentialExecution can be set to false to revert to the old (unsafe) behavior. The new #stop method and the #Running property can also be used in this context.
  • GraphEditorInputMode got support for cyclic click selection. This helps in conveniently selecting items that are hidden behind other items. By default, this features is bound to the Alt-Key being pressed. It can be disabled by setting the #CyclicSelectionRecognizer property to EventRecognizers#NEVER.
  • ItemDropInputMode is a new DropInputMode that facilitates subclasses that support preview and snapping of the dragged item as well as highlighting potential drop targets.
    NodeDropInputMode and StripeDropInputMode have been refactored to use ItemDropInputMode as base class.
  • ItemHoverInputMode is a new IInputMode that fires events when the mouse enters or leaves the visualization of a graph item.
  • GraphEditorInputMode and GraphViewerInputMode provide a new CanvasClicked event to detect clicks on an empty canvas location.
  • Node ports can now be moved by dragging their IHandle.
  • When zooming while editing a label, the label text editor now stays at its minimum (maximum) size when the zoom level becomes smaller (larger) than the specified threshold. Previously, the label text editor jumped back to the size of zoom level 1.0 for such values.
  • GraphClipboard has new properties CopyItems, IndependentCopyItems, and DependentCopyItems that allow for restricting the types of items that can be copied at all, independently from their owners, or implicitly through their owners, respectively.
  • GraphViewerInputMode and GraphEditorInputMode: Their ClickInputMode now delivers both left and right clicks.
  • GraphViewerInputMode: The click hit test order can now be configured by property #ClickHitTestOrder.
  • GraphEditorInputMode provides an explicit hit test order for double clicks that can be changed through the #DoubleClickHitTestOrder property. By default, this hit test order prefers labels over other graph elements.
  • Added new methods ClickInputMode#preventNextDoubleClick and TapInputMode#preventNextDoubleTap that can be used in event handlers for single clicks/taps to prevent that this click can become part of a double click event.
  • NodeDropInputMode can now optionally drop nodes onto leaf nodes and thus convert the leaves into group nodes. Also it is possible to drop nodes into collapsed folder nodes. For both use-cases, an opt-in property has been added and a predicate property allows for fine-grained control over this feature.
  • Similarly, leaf nodes can now be the target of a reparenting gesture if the property GraphEditorInputMode#ReparentingToLeavesEnabled is enabled. In this case, leaves are converted into group nodes.
  • Added support for deleting bends in a way that an orthogonal edge remains orthogonal after removing the bends. The new property GraphEditorInputMode#OrthogonalBendRemovalEnabled enables/disables this feature.
  • GraphViewerInputMode now supports multi-selection via Ctrl+Click and marquee selection. The latter is disabled by default.
  • OverviewInputMode and the GraphOverviewControl have been optimized to improve the user experience when used on touch devices.
  • OverviewInputMode can be customized more easily. Minor modes can be replaced and adjusted, as well as the list of available default command bindings can be modified.
  • Improved GraphModelManager to allow for easier customizations. Property #HierarchicNestingEnabled was added to allow for adding custom logic that uses a different approach to hierarchic nesting. Also the return types of some of the factory methods where made less restrictive to allow for further modifications.
  • FoldingManager now offers two convenience methods, #updateViewStates(INode) and #updateViewStates(IEdge), that will trigger update calls on IDummyNodeConverter and IDummyEdgeConverter for elements that are currently being displayed in a view. This makes it easier to synchronize states between the master graph and the folded graph views in case this is not automatically performed by the default implementation.

Layout

  • BalloonLayouter: Added support for integrated node and edge labeling. See new properties #IntegratedEdgeLabelingEnabled, #IntegratedNodeLabelingEnabled, and #NodeLabelingPolicy.
  • BalloonLayouter: Added support for different policies to align nodes having the same root node. See new property #ChildAlignmentPolicy.
  • BalloonLayouter: Added support for interleaved child node placement. With interleaved placement, child nodes are placed at different distances to their parent node to achieve a more compact layout. See new property #InterleavedMode.
  • IncrementalHierarchicLayouter: Improved partition grid support. Nodes can now be mapped to a multi-lane partition cell identifier, i.e., a cell spanning multiple columns and rows. See PartitionGrid.
  • IncrementalHierarchicLayouter: Improved edge label placement. Edge labels with preferred placement at source/target are placed closer to the corresponding node. Additionally, SimplexNodePlacer offers the option to place adjacent edge labels in a compact, stacked style. See new property #LabelCompactionEnabled.
  • EdgeRouter: Added a fine-granular configuration option to weigh the crossing costs for each label using the data provider look-up key #LABEL_CROSSING_COST_FACTOR_DPKEY.
  • EdgeRouter: Added property #IgnoreInnerNodeLabelsEnabled for ignoring node labels that are inside the bounds of their owner node. Node labels that are ignored because of this setting may be crossed by edges. This is especially useful if inner labels of group nodes may be crossed but outer labels of normal nodes may not.
  • EdgeRouter: Added support for customizing the order in which edges are routed. See new property #EdgeOrderComparator.
  • GenericTreeLayouter: When enabling the new properties #IntegratedNodeLabeling and/or #IntegratedEdgeLabeling, the respective labels will be taken into account during the calculation of group bounds.
  • PartialLayouter: Now supports handling of directed and undirected edges; see data provider key #DIRECTED_EDGES_DPKEY.
  • LabelLayoutTranslator: Added properties #WriteBackRelativeEdgeLabelLocationEnabled and #WriteBackRelativeNodeLabelLocationEnabled that allow a core layouter to specify new node or edge label locations relative to the label's owner.
  • LabelLayoutKeys: Added key #IGNORE_LABEL_KEY that allows specifying which edge and node labels should be ignored during layout calculations.
  • Added new class OrganicRemoveOverlapsStage that removes node overlaps while respecting a specified minimal node distance. Unlike the approach implemented in class RemoveOverlapsLayoutStage, this approach tries to keep the original layout structure, i.e., it tries to keep the geometric distance between the nodes.

Demos

  • Added a demo to show how to print the contents of a yFiles CanvasControl using the JavaFX 8 printing API.
  • Added a demo to show how to use yFiles for JavaFX in an Eclipe RCP application.
  • Added a demo to show how to use the JavaFX 8 rich text API together with yFiles labels.
  • Interoperability demos show how to wire up Commands of the GraphControl with buttons in the toolbar.
  • Interoperability demos show how to implement a ContextMenuInputMode that handle non-JavaFX context menu controls.
  • Interoperability demos show how to implement drag and drop of nodes from a Swing or SWT palette to the GraphControl.
  • Removed Shrinker from obfuscation demo since it is not Java 8 compliant yet.

Tutorials

  • Vastly improved the Getting Started tutorial in regards to documentation and content.

Improvements

Viewer

  • To support proper serialization and deserialization of URLs, we have added the ability to specify the base URI when loading GraphML files via methods that use java.io.InputStream or java.io.Reader. The added methods in particular are:
    • GraphControl#importFromGraphML(InputStream, URI)
    • GraphControl#importFromGraphML(Reader, URI)
    • GraphMLIOHandler#read(IGraph, InputStream, URI)
    • GraphMLIOHandler#read(IGraph, Reader, URI)
    • GraphMLParser#parse(InputStream, URI, IGraph, IGraphElementFactory)
    • GraphMLParser#parse(Reader, URI, IGraph, IGraphElementFactory)
    This e.g. enables the usage of relative paths in the GraphML.
  • Added class RenderContext as a default implementation of the IRenderContext interface for use in custom calls to rendering related methods like IVisualCreator#createVisual(IRenderContext) or CanvasControl#createContentVisual(IRenderContext). An instance of this class can be obtained by calling CanvasControl#createRenderContext.
  • Added class ContextConfigurator which can be used to create IRenderContexts that are configured to render certain regions of a CanvasControl with a certain scale and margins. This class is used for image export and printing.
  • ResizeStripeInputMode uses now the proper cursors for resizing stripes.
  • Zooming with the mouse wheel now works with the Shift key pressed.
  • The performance of parsing GraphML files has been improved. The speed-up is especially notable for large graphs with several thousands of nodes.
  • Optionally, LayoutExecutor uses WaitInputMode while waiting during the calculation of a layout.
  • LayoutGraphAdapter provides now the original Tag data for temporary graph objects.
  • ContextMenuInputMode added support for Menu-Key.
  • Added serialization and deserialization for javafx.scene.paint.LinearGradient, javafx.scene.paint.RadialGradient and javafx.scene.paint.ImagePattern.
  • Added proper serialization and deserialization for URLs. This means that it is now possible to use relative paths for external resources in GraphML, for example for images in ImageNodeStyle.
  • GraphControl: Added the method #importFromGraphML(URL) to conveniently load GraphML files from URLs.
  • Various performance improvements for the rendering and the selection handling. This affects, amongst others, styles that use a GeneralPath.
  • Property GraphEditorInputMode#DetailSelectionRecognizer is now also applied for double clicks to determine the clicked item.
  • GraphEditorInputMode and GraphViewerInputMode don't select or focus graph items styled with a void style (VoidNodeStyle, VoidEdgeStyle, VoidLabelStyle, and VoidPortStyle). The new property #IgnoringVoidStylesEnabled specifies whether this feature is enabled.
  • GraphEditorInputMode and GraphViewerInputMode: the new protected method #shouldSelect can be overridden to determine whether an item can be selected in general.
  • DropInputMode: Added property #LastDragEvent.
  • OverviewInputMode: The new property #Margins specifies margins for the visible area of the bound GraphOverviewControl. The new protected method #updateVisibleArea provides further means for customizing the visible area.
  • CompositePositionHandler: Added methods #getPositionHandler and #getHandle to retrieve an earlier added IPositionHandler or IHandle.
  • PortRelocationHandles now triggers the EdgePortsChanged event of the GraphEditorInputMode.
  • EdgeStyleDecorationInstaller can now be used with self loops without bends, too.
  • TableLayoutConfigurator: Improved support for routing algorithms.
  • IGraph: The collection models of graph items returned by the methods #getNodes, getEdges, etc. now support the methods #remove and #clear to remove graph items from the graph. Note that calling the method #add is still not allowed.
  • GraphModelManager: New callback method #onGraphChanged.
  • LayoutExecutor: The new property #ConsideringViewportLimiterEnabled can be used to let the target viewport after a layout respect the ViewportLimiter of the GraphControl.
    The ViewportAnimation has a new property #ConsideringViewportLimiterEnabled for the same purpose.
  • LayoutGraphAdapter now adds data providers that map each node, edge and label of a LayoutGraph to their corresponding IModelItem in the original IGraph. Especially, these data providers are available if a layout is run with a LayoutExecutor or the convenience methods LayoutExtensions.MorphLayout and LayoutExtensions.ApplyLayout.
  • GeomSupport: The new method #createSmoothedPath creates a new path as copy of a given one but with smoothed bends.
  • IconLabelStyle: The icon is added to the hit test area for mouse clicks and marquee selection. This can be switched off by overriding IconLabelStyleRenderer#shouldHitTestIcon.
  • CanvasControl: Method #fitContent now respects the #ViewportLimiter property. This might result in zoom levels greater than 1.0.
  • DefaultDummyEdgeConverter now synchronizes the #Tag property of the first label if label synchronization is enabled.
  • GraphCopier has been improved to facilitate manipulation of the copied items:
    • The new events NodeCopied, EdgeCopied, LabelCopied, and PortCopied are dispatched after a model item has been copied.
    • The method #getOrCreateCopy<T> is now public to facilitate copying of, for example, node tags.
  • GraphClipboard: In hierarchically organized graphs, nodes are now pasted into their previous parent group, the group at their target position, or the root, depending on the new property #ParentNodeDetection.

Algorithms

  • Dfs: Added method #cancel that can be used by subclasses to cancel the search.
  • Cycles: Improved method #findCycle to stop the search as soon as the first cycle has been found.

Layout

  • IncrementalHierarchicLayouter: The default sequencing phase has been improved to produce less crossings and run faster.
  • IncrementalHierarchicLayouter: Now prevents overlaps among same layer edges attached to group nodes.
  • IncrementalHierarchicLayouter: During layering, edges connected to group nodes may be redirected and replaced by dummy edges connected to the children of the group node. For these dummy edges ILayoutDataProvider#getEdgeData now returns an IEdgeData of the new type EdgeDataType#REDIRECTED_GROUP_EDGE.
  • PCListOptimizer: Improved port candidate assignment calculated by method #optimizeAfterSequencing.
  • SmartOrganicLayouter: Now uses a more sophisticated approach to remove node overlaps if the scope is set to #SCOPE_ALL and the quality to time ratio (see #setQualityTimeRatio) is greater than or equal to 0.7.
  • InteractiveOrganicLayouter: Method #startLayout now takes advantage of multiple threads for layout calculation which may reduce the required runtime.
  • PartitionLayouter: Added nested class PolylineInterEdgeRouter that routes inter-edges using class EdgeRouter.
  • PartialLayouter: Now considers port constraints independent of the specified layout orientation. Note that port constraints are considered only if the core layout algorithm (see #setCoreLayouter) supports port constraints as well.
  • PartialLayouter$StraightLineEdgeRouter: Added support for port constraints.
  • RecursiveGroupLayouter: Added property #ReplacingPortConstraintsEnabled that replaces port constraints by port candidates and, thus, may improve the layout result.
  • EdgeRouter: Memory usage has been reduced.
  • EdgeRouter: Added penalty setting for edge length. See property #EdgeLengthPenalty.
  • EdgeRouter: Now avoids very small octilinear segments.
  • EdgeRouter: Added four predefined optimization strategies. See PenaltySettings#OPTIMIZATION_BALANCED, PenaltySettings#OPTIMIZATION_EDGE_BENDS, PenaltySettings#OPTIMIZATION_EDGE_CROSSINGS, and PenaltySettings#OPTIMIZATION_EDGE_LENGTHS.
  • DirectedOrthogonalLayouter and OrthogonalGroupLayouter: Added optimization step that reduces the number of perceived bends. See new property #PerceivedBendsOptimizationEnabled.
  • OrthogonalLayouter, OrthogonalGroupLayouter and DirectedOrthogonalLayouter: Added optimization step that aligns degree one nodes (i.e. nodes with one incident edge) that have the same neighbor. See new property #AlignDegreeOneNodesEnabled.
  • OrthogonalGroupLayouter: Improved routing and edge labeling for self-loops of normal (non-group) nodes.
  • LayoutTool: Added new rectangle arrangement method #arrangeRectangleMultiRows(java.awt.geom.Rectangle2D[], java.awt.geom.Rectangle2D, double, double, boolean, byte, int) suitable for arranging rows of rectangles with highly different sizes.
  • ComponentLayouter: Added new component arrangement strategies #STYLE_MULTI_ROWS, #STYLE_MULTI_ROWS_COMPACT, #STYLE_MULTI_ROWS_HEIGHT_CONSTRAINED, #STYLE_MULTI_ROWS_HEIGHT_CONSTRAINED_COMPACT, #STYLE_MULTI_ROWS_WIDTH_CONSTRAINED, and #STYLE_MULTI_ROWS_WIDTH_CONSTRAINED_COMPACT suitable for components with highly different sizes.

Bugfixes

Viewer

  • Fixed static method FlagsEnum#xor that called non-static method #and by mistake.
  • Fixed unfunctional PointSelectionIndicatorInstaller.
  • GraphML:
    • Fixed a possible NullPointException when deserializing properties of obfuscated enums.
    • Folding: Source port tags in view states were not parsed correctly.
    • Properties with a text value containing nested CDATA sections were not parsed correctly.
    • Primitive types like floats and doubles could not be read when used in element syntax.
    • Write events were not always raised.
    • Fixed a bug were incorrect values for bend tags were written.
    • The #Name property of the @GraphML annotation was not considered during deserialization.
    • GraphMLIOHandler: Method #addNamespace had no effect, and adding a custom schema with #addSchemaLocation triggered an exception.
  • TableEditorInputMode by default also handled right clicks, which prevented the context menu for stripes from appearing and erroneously toggled the stripe selection state.
  • Creating a new node as a child of an existing node which was not a group node did not cause the state change to be recorded by the undo engine. After undoing the node creation, the parent node still behaved like a group node. Such an implicit change is now recorded properly and can be reverted through undo as expected.
  • Fixed too large dirty regions when using certain kinds of SnapLines.
  • Fixed memory leak that occurred when CreateEdgeInputMode was uninstalled.
  • CanvasControl: Fixed incorrect event propagation.
  • CreateEdgeInputMode now removes event handlers when it is uninstalled.
  • It is now possible to set the line spacing and wrapping width for the JavaFX Text nodes that the SimpleLabelStyle is producing to render labels via its #TextFormat property.
  • SimpleLabelStyle: #ClippingText property is now useful.
  • ShinyPlateNodeStyleRenderer now uses its getters to access the properties of its style. This means that overriding them now has an effect.
  • SimpleLabelStyleRenderer: Prevented NullPointerException for labels with negative width or height.
  • Pen:
    • Changed default values for #LineCap and #LineJoin properties.
    • Fixed incorrect application of the #DashStyle property.
  • TextEditorInputMode: The internal positioning/scaling calculation now respects the values returned by the methods #getMaximumZoom and #getMinimumZoom properly.
  • FilteredGraphWrapper: #dispose did not clean up all event listeners.
  • Undoing a reparent grouping gesture might have resulted in inconsistent group node sizes. Note: The fix results in a slightly incompatible behavior when nodes are reparented programmatically and multiple folding views are used. In that case, you need now to subscribe to hierarchy events and manually adjust the group node bounds.
  • IUndoSupport: Manually bracketing undo edits with beginEdit might have led to exceptions when folding was active.
  • ClickInputMode: The property #FocusClickSwallowingEnabled had only an effect for the very first click.
  • Copying table stripes did not work correctly.
  • GraphOverviewControl: Moving the viewport by clicking into the control did not honor the #ViewPortLimiter property restrictions of CanvasControl.
  • RotatedSliderEdgeLabelModel can now deal with edge paths that are null, e.g. when using VoidEdgeStyle.
  • FoldedGraph detects more carefully what has changed before invoking the methods #createDummyEdgeAppearance and #changeDummyEdgeAppearance of IDummyEdgeConverter. Previously, in some cases, these methods were called too often or not at all.
  • When both a group node and its child node were resized together the group node bounds shrunk to its original bounds once the child had reached the original bounds.
  • Fixed problem in LayoutGraphAdapter where label candidates for edge labels were not always determined correctly.
  • Fixed LayoutGraphAdapter producing threading issues when PortCalculator was used during a multi-threaded layout.
  • When snapping was disabled temporarily (using Ctrl) during a move gesture the moved item snapped after finishing the gesture, anyway.
  • FoldedGraphUndoSupport didn't add the correct bend information to its internal data structures.
  • CreateEdgeInputMode: Fixed some problems with mixed mouse and touch input.
  • When using an IEditLabelHelper and adding a label interactively, the helper's #editLabel callback was called instead of #addLabel.
  • Newly added labels could have had an empty size when an IEditLabelHelper instance was registered.
  • When a highlighted item was removed from the graph, the highlight was not cleaned up.
  • Reparenting an empty group node displayed the target node highlight around the reparented node.
  • The modified MoveInputMode created by MainInputMode#createMoveUnselectedInputMode changed the cursor to indicate a movable object even when the modifierRecognizer disabled moving.
  • When both a group node and its child node were resized together the group node bounds shrunk to its original bounds once the child had reached the original bounds.
  • ClickInputMode: Cancelling the mode during clicks didn't work correctly and as a result, the location reported for the next click might have been wrong.
  • CreateEdgeInputMode now copies the dummy edge's tag to the created edge. This could have caused issues when the EdgeCreationStarted event was used to set a custom tag on the dummy edge.
  • When the pressed status of the Shift key changed during a reparenting gesture of a node, the bounds of its containing group node were not immediately updated.
  • The secondary multi-tap gesture was not recognized correctly.
  • Labels whose positions were determined by NinePositionsEdgeLabelModel, SliderEdgeLabelModel, and SideSliderEdgeLabelModel might have disappeared when one or more edge segments were hidden under the source or target node.
  • SnapContext: Snap results with a null tag were erroneously always discarded.
  • GeneralPath: Method #transform, amongst others using Matrix2D, applied the transformation matrix incorrectly in the case of a rotation.
  • IconLabelStyle: Method #getBounds in IconLabelStyleRenderer returned a valid rectangle even if the label layout was invalid. As a consequence, IsVisible erroneously returned true for labels with invalid bounds.
  • The lookup of CollapsibleNodeStyleRenderer was missing the correct results for IGroupBoundsCalculator, ISizeConstraintProvider, and IShapeGeometry.
  • CanvasControl#ensureVisible hasn't worked for bounds larger than the current viewport.
  • Setting the view point on a CanvasControl with a width or height of 0.0 could cause an exception if a #ViewportLimiter was set.
  • GraphCopier threw an ConcurrentModificationException if the source and the target graph are identical.
  • GraphEditorInputMode and GraphViewerInputMode now respect the MultiSelectionRecognizer for extending an existing selection via marquee.
  • Fixed TableEditorInputMode exhibiting problematic behavior under certain circumstances when the GraphControl's graph is replaced.
  • RotatedSideSliderEdgeLabelModel: Label model parameters of this model were serialized as the respective parameters of RotatedSliderEdgeLabelModel. Thus, after loading, the positions of the labels are the expected ones but the label models changed.
  • RotatedSliderEdgeLabelModel: Parameters with ratio 0.5 were not correctly deserialized from GraphML.
  • FilteredGraphWrapper: The #edgesAt methods erroneously returned edges that were marked as hidden by the #EdgePredicate. The methods #degree, #inDegree and #outDegree are based on these methods and were affected, too.
  • GraphSnapContext: Snapping nodes to vertical edge segments was not working if property #NodeToEdgeDistance was set to 0.
  • The EdgeStyleDecorationInstaller did not copy the tags of dummy ports and edges used when displayed in view coordinates (#ZoomMode = DecorationZoomMode#VIEW_COORDINATES).
  • GraphEditorInputMode#findItems: Only the first element in the test array parameter was actually checked.

Layout

  • MultiPageLayouter: Fixed bug that caused that an AbortHandler attached to the input graph to be ignored.
  • IncrementalHierarchicLayouter: Fixed routing style violations in octilinear grouped edges.
  • MultiPageLayouter: Fixed NullPointerException that may occur if the edge-id DataProvider (see MultiPageLayouter#EDGE_ID_DPKEY) is an instance of EdgeMap.
  • IncrementalHierarchicLayouter: Fixed NullPointerException that could occur when octilinear edges are attached to group nodes.
  • HVTreeLayouter: Fixed bug that may cause edges with reversed direction if the layout isn't run in buffered mode.
  • PortCandidateSet: Fixed bug that caused method PortCandidateSet.ICandidateMatcher#findMatchingCandidate() to return the entry with the highest cost instead of the lowest cost if the candidate matcher is created with method PortCandidateSet#createMatcher().
  • DirectedOrthogonalLayouter: Fixed bug that caused an ArgumentException if DataProvider-Key PortConstraintKeys#SOURCE_GROUP_ID_DPKEY is registered to the input graph but DataProvider-Key PortConstraintKeys#TARGET_GROUP_ID_DPKEY is not registered.
  • ComponentLayouter: Fixed bug that caused an ArrayIndexOutOfBoundsException if the style is set to ComponentArrangementStyle#MULTI_ROWS_HEIGHT_CONSTRAINT or ComponentArrangementStyle#MULTI_ROWS_HEIGHT_CONSTRAINT_COMPACT (see ComponentLayouter#Style) and all components exceed the preferred height (see ComponentLayouter#PreferredLayoutSize).
  • IncrementalHierarchicLayouter: Fixed bug that caused first or last segments of edges to be too short to span all associated labels.
  • MultiPageLayouter: Fixed bug that may cause non-orthogonal edge routes.
  • TreeReductionStage: Fixed bug that may cause a InvalidGraphStructureException if the input graph contains group nodes with incident edges.
  • TreeLayouter: Fixed bug that may cause a ClassCastException if the input graph is a CopiedLayoutGraph that consists of multiple connected components and the layouter uses the LayeredNodePlacer (e.g., if option TreeLayouter#setChildPlacementPolicy is set to ChildPlacementPolicy#ALL_LEAVES_ON_SAME_LAYER).
  • IncrementalHierarchicLayouter and RankAssignments: Fixed possible NullPointerException that may occur if the maximal duration of the algorithm is limited.
  • IncrementalHierarchicLayouter: Fixed bug that may cause overlaps of edge labels with preferred placement at source/target.
  • Polyline.EdgeRouter: Fixed rare NullPointerException that mainly appears if there are overlapping nodes.
  • PartialLayouter: Fixed bug that may cause broken edge routes for edges incident to incremental group nodes if option ImmediateInterEdgeRoutingEnabled is true.
  • CompactOrthogonalLayouter: Fixed possible IllegalArgumentException caused by nodes without node-ids. This problem may only appear if the inter edge router is set to PartitionLayouter.ChannelInterEdgeRouter.
  • Running any label placement algorithm had no effect for node/edge labels if the properties #NodeOverlapsRemovalEnabled/#EdgeOverlapsRemovalEnabled were enabled because all potential candidates were erroneously rejected.
  • IncrementalHierarchicLayouter: Fixed bug that may cause edges with zig-zag paths if there are swimlanes and integrated edge labeling is enabled.
  • IncrementalHierarchicLayouter and TopologicalIncrementalLayerer: Fixed bug that may cause unwanted same-layer edges between incremental nodes.
  • GenericTreeLayouter: Fixed issue that caused too large group nodes when label consideration is enabled and the layout is not oriented top-to-bottom.
  • GenericTreeLayouter: Fixed issue that causes group nodes to be too small to include all edge labels when the edge connects to a child of an inner group node.
  • GenericTreeLayouter: Fixed issue that causes group nodes to be too small to node halos.
  • IncrementalHierarchicLayouter: Fixed minimum edge length for orthogonal edges. It is now also taken into consideration for edges that connect to a node's side and for backloop edges (see property #BackloopRoutingEnabled).
  • IncrementalHierarchicLayouter: Fixed possible ArrayIndexOutOfBoundsException in PCListOptimizer that may appear if there are port constraints which have no matching port candidate or port candidate set entry.
  • IncrementalHierarchicLayouter: Fixed possible IndexOutOfBoundsException if PortConstraints are used together with PortCandidateSets.
  • EdgeRouter: Minimum first and last segment length and minimum node to edge distance were sometimes ignored when used together with octilinear routing style.
  • GraphGrouping: Fixed bug in method #getNearestCommonAncestor that sometimes caused wrong results if one of the specified nodes is the ancestor of the other node.
  • InsetsGroupBoundsCalculator: Fixed method #calculateBounds to consider only the given child nodes and all edges between those child nodes instead of all nodes and all edges in the graph.
  • GenericTreeLayouter: Fixed NullPointerException that occurred when using LayeredNodePlacer as default node placer.
  • LayoutTool: Fixed calculation of lower width bound in method #arrangeRectangleRows(java.awt.geom.Rectangle2D[], java.awt.geom.Rectangle2D, double, int). Due to the better bound, the optimization procedure now needs less steps, especially for graphs with very wide components. Note, that the results may also slightly differ, because the optimization may now stop with slightly different values.
  • SALabeling and GreedyMISLabeling: Fixed possible NullPointerException caused by labels with zero width/height and a "free" edge label model.

Incompatible Changes

Viewer

  • CanvasControl: Removed obsolete #PrintCommandsEnabled property.
  • PixelImageExporter: instead of using the JavaFX SnapshotParameters class directly, the exporter now holds an instance of ContextConfigurator which is designed to make the exporting of a certain region or scale of the contents of a CanvasControl to an image a lot easier. Clients can still overwrite the new protected method #getSnapshotParameters to return an instance of SnapshotParameters that will be used to make the actual snapshot of the JavaFX node.
  • IRenderContext: removed obsolete methods #getWorldTransform and #getTransform since all calculations related to rendering and transformation of elements can be achieved by the transform returned by #getViewTransform.
  • To support proper resize cursors the properties
    • CanvasCursor#SizeNS
    • CanvasCursor#SizeWE
    • CanvasCursor#SizeNWSE
    • CanvasCursor#SizeNESW
    • CanvasCursor#SizeSizeAll
    were replaced by
    • CanvasCursor#SizeN
    • CanvasCursor#SizeS
    • CanvasCursor#SizeE
    • CanvasCursor#SizeW
    • CanvasCursor#SizeSE
    • CanvasCursor#SizeNE
    • CanvasCursor#SizeSW
    • CanvasCursor#SizeNW
    • CanvasCursor#Move
  • To handle non-JavaFX context menu controls ContextMenuInputMode has now a super class AbstractContextMenuInputMode that is used in the MainInputMode and GraphEditorInputMode. The contextMenu property of class PopulateContextMenuEventArgs has now type Object and must be cast to the type of the context menu control of the used toolkit.
  • Obsolete classes InputGesture and KeyGesture were replaced by the JavaFX class javafx.scene.input.KeyCodeCombination.
  • CanvasControl: removed erroneous and obsolete #invalidateWorld method.
  • Pen: removed unused #DashCap property.
  • Class DateTime was replaced by the Java 8 class Instant.
  • Class javafx.util.Duration was replaced by the more common Java 8 class java.time.Duration.
  • Property URL of class ImageNodeStyle is now of type java.net.URL instead of string. GraphML files that use this property might not load anymore because of this change. In this case, the specified paths in the file need to be adjusted to URLs.
  • TextEditorInputMode: The resource key #TEXT_BOX_STYLE_KEY was removed due to insufficient compatibility with the JavaFX css styling mechanism. Clients that want to change the visual appearence of the text box should instead retrieve the instance of the control via #getTextBox and use the JavaFX framework methods to change the style.

API Changes

  • Changed SnapLine to support non-orthogonal snap lines as well: its properties #From and #To have been changed from type double to PointD, its property #Orientation was removed, and its constructors have been changed accordingly.

    Orthogonal snap lines are now modeled by class OrthogonalSnapLine. It extends SnapLine and provides the property #Orientation. Existing API uses either SnapLine or OrthogonalSnapLine, depending on whether it works only with orthogonal snap lines or not.

    As a consequence, in class SnapLineSnapResult, the method #getSnapLine returns a non-orthogonal SnapLine and #getDelta returns a PointD instead of a double. API related to GraphSnapContext still works only with orthogonal snap lines and uses OrthogonalSnapLine.

  • The #Key property on SingleLineSnapLineContainer, FixedDistanceSnapLineContainer and InBetweenSnapLineContainer, has been made read only.
  • GraphModelManager's factory methods for creating the installers now have a less restrictive return type. The default implementation still returns the same types as before, though.
  • GraphClipboard's factory methods for creating the predicates for the various cut and copy operations now require a second argument that is the graph that the predicate is working on. Usages typically use the graph in the graph control where the selection is also being used. If the default graph selection implementation is used. The graph instance can be obtained from its corresponding property.
  • GraphModelManager's installer related properties now use a weaker return type to simplify subclassing with new functionality. The instances used are the same and can be down-casted accordingly to the more specific types as documented.
  • AlgorithmAbortedException: Removed overloaded methods #check. Client code that needs to terminate layout calculations prematurely must use new class AbortHandler instead.
  • Moved classes PartitionGrid, PartitionCellId, RowDescriptor, and ColumnDescriptor from package com.yworks.yfiles.layout.incremental to package com.yworks.yfiles.layout.grid.
  • IItemFactory: Added method #createRedirectedGroupEdge.
  • LayeredNodePlacer: Removed data provider key #DISTANCE_TO_PARENT_MAP_DPKEY from public API, since it is for internal use only.
  • EdgeRouter: Penalty settings have been changed to double precision. See class PenaltySettings.
  • PathSearch: Signature of method #calculateCosts has changed. It now takes an additional double array as parameter that is populated with the calculated costs instead of returning a new array.
  • GraphClipboard's protected method #copy(IGraph, Predicate<IModelItem>, IGraph, ElementCopiedDelegate) which was called by #cut, #copy, and #paste to invoke the GraphCopier has been split: #copy(IGraph, Predicate<IModelItem>, IGraph, ElementCopiedDelegate) now is called only by #cut and #copy. #paste now invokes the new method #paste(IGraph, Predicate<IModelItem>, IGraph, ElementCopiedDelegate, Predicate<IModelItem>).
  • The type of GraphMLAttribute's #Serializable property has been changed from boolean to the enum GraphMLSerializationMode.
  • GraphEditorInputMode and TableEditorInputMode: return value of callback methods #onAddLabel and #onEditLabel has been changed from void to boolean. The return value should specify whether the operation in question was successful.
  • The ContextMenuInputMode's protected method onPopulateContextMenu(ContextMenu, PointD, boolean) and the constructors of PopulateContextMenuEventArgs and PopulateItemContextMenuEventArgs now require an additional argument that indicates whether the request to display a context menu was caused by the keyboard.

Behavior Changes

  • The default constructor of TextFormat and SimpleLabelStyle uses now the default font of the current UI environment instead of "Arial".
  • TableEditorInputMode now only handles left mouse clicks by default, which is consistent with the rest of the library.
  • EdgeRouter: Labels of table nodes are no longer ignored by the router if TableLayoutConfigurator is used to prepare the graph for layout calculations. If you want to ignore such labels you can use a IDataProvider registered with key LabelLayoutKeys#IGNORE_LABEL_KEY.
  • EdgeRouter: Method #doLayout now throws an IllegalArgumentException if there is a node with zero width or height in the given graph.
  • FixedGroupLayoutStage: Method #getOrthogonalEdgeRouter now returns an instance of class EdgeRouter instead of class OrthogonalEdgeRouter.
  • ComponentLayouter: Method #setPreferredLayoutSize now throws an IllegalArgumentException when setting the preferred size to negative values or zero.
  • Changed default behavior of edge label placement in OrthogonalLayouter and LabelLayoutDataRefinement when using PreferredPlacementDescriptor#PLACE_ANYWHERE Now edge labels are placed on the edge and in the center between source and target node.
  • GraphEditorInputMode now by default supports the new GraphCommands.DUPLICATE_COMMAND that is bound to keyboard shortcut Ctrl-D. If this behavior is undesired new behavior, the #DuplicationEnabled property can be set to false.
  • The clipboard now supports copying and pasting of items independently from their owning elements. E.g. single selected labels can be copied to other elements, as well as edges without their source and target nodes. This behavior can be reverted to the old behavior by setting GraphClipboard's #IndependentCopyItems to GraphItemTypes#NONE.
  • GraphEditorInputMode now by default allows for reversing selected edges using the Ctrl-R keyboard shortcut and the new GraphCommands.REVERSE_EDGE_COMMAND. This new behavior can be turned off by setting the #EdgeReversalEnabled property to false.
  • ClickInputMode: If #ActiveButtons includes MouseButtons#RIGHT, the original right click event is marked as handled if ClickInputMode's event handlers mark the higher level click event as handled. Especially, no context menu will be shown if the right click is handled by ClickInputMode itself.
  • GraphEditorInputMode and GraphViewerInputMode: The default click actions that change the selection and create new nodes are only triggered on left mouse clicks now.
  • Previously, ports at nodes and edges that were copied and pasted to and from the clipboard were all copied, even if there where no edges attached to them after the operation. Now those empty ports are not copied/pasted anymore unless the PortDefaults' #AutoCleanupEnabled property is set to false or they were unoccupied before the operation already. In order to restore the old behavior, where all ports were copied, regardless of edges where adjacent to them, make sure to include them in the core predicate, since this behavior change just affects ports that had previously not been accepted by the core predicate function.
  • GraphEditorInputMode's NodeCreated event may now report nodes that are not part of the graph, when the user has dropped a node via NodeDropInputMode and the new NodeDropInputMode#FolderAsParentEnabled property is enabled. By default this feature is disabled, though.
  • IReparentNodeHandler's #isValidParent method may now also be queried if the new GraphEditorInputMode#ReparentingToLeavesEnabled property is enabled. By default this property is disabled, though. Note that the method will also be queried if the reparent handler is used outside the context of GraphEditorInputMode.
  • GraphMLValueSerializerContext: The property #Instance now provides the object that should be converted, not the parent object. If you need to access the actual parent object, you can use the #Owner property.
  • GraphMLIOHandler: The event QueryReferenceId is now never fired for MarkupExtensions and other proxy objects for serialization, only for the original object references.
  • EdgeRouter: Method #doLayout now throws an IllegalArgumentException if there is a node with zero width or height in the given graph.
  • FixedGroupLayoutStage: Property #OrthogonalEdgeRouter now yields an instance of class EdgeRouter instead of class OrthogonalEdgeRouter per default.
  • ComponentLayouter: Method #setPreferredLayoutSize now throws an IllegalArgumentException when setting the preferred size to negative values or zero.
  • Changed default behavior of edge label placement in layouters with integrated edge labeling when using LabelPlacements#ANYWHERE. Now edge labels are placed on the edge and in the center between source and target node. This change affects the following layout algorithms: IncrementalHierarchicLayouter, OrthogonalLayouter, OrthogonalGroupLayouter, DirectedOrthogonalLayouter, GenericTreeLayouter, and LabelLayoutDataRefinement.
  • LabelCandidateDescriptor: The default values of the properties #EdgeOverlapPenalty and #NodeOverlapPenalty have been changed to 0.0. Values greater than 0.0 trigger a known issue in all generic label placement algorithms that erroneously rejects all potential candidates. As a result, no suitable placement is calculated in this case.
  • MoveInputMode accepts mouse hovers with the Shift key held down again.
  • GraphEditorInputMode and GraphViewerInputMode: By default, graph items styled with a void style (VoidNodeStyle, VoidEdgeStyle, VoidLabelStyle, VoidPortStyle) won't be selected or get the focus.
  • GraphEditorInputMode's #ClickHitTestOrder property default value has changed. Now it does not contain the redundant GraphItemTypes#ALL as the last element in the array anymore.
  • GraphViewerInputMode: By default, clipboard commands are now disabled. This can be controlled with the new property #ClipboardCommandsEnabled.
  • The default keyboard shortcut for deselecting elements (GraphCommand#DESELECT_ALL_COMMAND) has been changed to Ctrl+Shift+A. Ctrl+D is now the default shortcut for duplicating selected elements (GraphCommand#DUPLICATE_SELECTION_COMMAND). Duplicating elements can be disabled via the GraphEditorInputMode#DuplicationEnabled property.
  • GraphEditorInputMode: Method #shouldBeMarqueeSelectable is no longer queried by the Paste command to determine the items which should be selected after paste. Instead, the new method #shouldBeSelectedAfterPaste is queried. Note that #shouldBeMarqueeSelectable still is queried to determine the items which should be selected by marquee selection.
  • Now, all pasted items are selected after a Paste (was: only nodes, edges, and bends). This can be configured via the new #PasteSelectableItems property in GraphEditorInputMode and the corresponding #shouldBeSelectedAfterPaste method.
  • If ClickInputMode is configured to deliver both single and double clicks, double clicks are not reported if the first click has created a new node or if cyclic selection is currently active. The same holds for TapInputMode and single/double taps.
  • The segment index for label model parameters of SliderEdgeLabelModel and SideSliderEdgeLabelModel now is related to the visible segments for edges styled with PolylineEdgeStyle.
  • If an IEditLabelHelper implementation is present in an ILabel's lookup, its #editLabel method is now called in addition to an eventual owner's edit helper when the label text is edited. If implementations are present for both the label and the owner, editing is only allowed if both helpers return true. Additionally, the predicate method GraphEditorInputMode#shouldLabelBeEdited always has to return true, whether edit helpers are present or not.
  • The label that is edited is now determined in the following order:
    1. If a label is explicitly provided as a command parameter or through a convenience method or is the only selected element, it is edited if the previous condition is satisfied. No other candidates are tried in that case.
    2. If a label owner is explicitly provided as a command parameter or through a convenience method, or is the only selected element, the first label that satisfies the condition above is edited if the previous condition is satisfied. If no such label exists, a new label is be added, provided that the owner allows adding. In either case, no other candidates are tried.
    3. The first selected label for which the previous condition is satisfied.
    4. If multiple label owners are selected, the first owner that has a label for which the previous condition is satisfied (in which case that label is edited).
    5. If IEditLabelHelper#editLabel for either an editable label or its owner provides a different label instance, this instance is edited instead.
    6. Otherwise, a label is added if an eligible owner can be found (see below).
  • If an IEditLabelHelper implementation is present in an ILabeledItem's lookup, its #addLabel method is called to determine whether a label may be added and provide a suitable label instance. Additionally, the predicate method GraphEditorInputMode#shouldLabelBeAdded always has to return true, whether edit helpers are present or not. If the new label should be edited interactively after it's creation (the default behavior), it also must be editable, following the rules above. Therefore an IEditLabelHelper implementation usually should allow editing of label instances that it has created itself in #addLabel.
  • The label owner for which a label is added is now determined in the following order:
    1. If a label owner is explicitly provided as a command parameter or through a convenience method, or is the only selected element, a label is added if the previous condition is satisfied. No other candidates are tried in that case.
    2. If multiple label owners are selected, the first one for which the previous condition is satisfied.