/// <summary> /// Displaye <see cref="DiagramItem"/> objects according to given diagram definition /// </summary> /// <param name="diagramDefinition">Definition of diagram with items to display</param> /// <param name="context">Context available for diagram definition</param> private void displayItems(DiagramDefinition diagramDefinition, DiagramContext context) { foreach (var definition in context.RootItemDefinitions) { var item = new DiagramItem(definition, context); InitializeItemDrawing(item); } if (!diagramDefinition.ShowJoinLines) { return; } //show join lines foreach (var joinDefinition in diagramDefinition.JoinDefinitions) { foreach (var from in Engine.DefiningItems(joinDefinition.From)) { foreach (var to in Engine.DefiningItems(joinDefinition.To)) { var join = _diagramFactory.CreateJoin(joinDefinition, context); Engine.AddJoin(join, from, to); } } } }
/// <summary> /// Set initial position for given item. /// Accordingly old positions, default positions,.. /// </summary> /// <param name="item">Item which position will be set</param> /// <param name="cursor">Cursor used for position initialization.</param> private void setInitialPosition(PositionCursor cursor, DiagramItem item) { Point oldPosition; if (item.HasPosition) { //keep preset position oldPosition = item.GlobalPosition; } else { if (!_oldPositions.ContainsKey(item.ParentID)) { //there is no old position for item cursor.SetDefault(item); return; } var parentPositions = _oldPositions[item.ParentID]; if (!parentPositions.ContainsKey(item.ID)) { //there is no old position for item cursor.SetDefault(item); return; } //keep position from previous display oldPosition = parentPositions[item.ID]; } cursor.RegisterPosition(item, oldPosition); }
/// <summary> /// Report drag start of given item. /// </summary> /// <param name="item">The item.</param> internal void DragStart(DiagramItem item) { if (OnDragStart != null) { OnDragStart(item.Definition); } }
/// <summary> /// Initializes a new instance of the <see cref="DiagramItem" /> class. /// </summary> /// <param name="definition">The definition.</param> /// <param name="parentItem">The parent item.</param> /// <param name="slot">The slot.</param> internal DiagramItem(DiagramItemDefinition definition, DiagramItem parentItem, SlotCanvas slot) { ContainingDiagramCanvas = slot; Definition = definition; ParentItem = parentItem; ParentItem._children.Add(this); DiagramContext = parentItem.DiagramContext; initialize(); }
/// <summary> /// Sets the highlight status. /// </summary> /// <param name="item">The item.</param> /// <param name="status">if set to <c>true</c> [status].</param> private void setHighlightStatus(DiagramItem item, bool status) { foreach (var join in Provider.Engine.Joins) { if (join.From.OwningItem == item || join.To.OwningItem == item) { join.IsHighlighted = status; } } }
/// <summary> /// Save position of given item to be hold for another display /// </summary> /// <param name="contextItem">Context item, where saved position is valid</param> /// <param name="item">Item which position is saved</param> /// <param name="position">Saved position</param> private void saveOldPosition(DiagramItem contextItem, DiagramItem item, Point position) { var isRootItem = contextItem == null; var contextID = isRootItem ? "" : contextItem.ID; Dictionary <string, Point> positions; if (!_oldPositions.TryGetValue(contextID, out positions)) { positions = new Dictionary <string, Point>(); _oldPositions[contextID] = positions; } positions[item.ID] = position; }
/// <summary> /// Register item to be displayed after next <see cref="Display"/> call /// </summary> /// <param name="item">Registered item</param> internal void RegisterItem(DiagramItem item) { //attach items behaviours ItemHighlighting.Attach(item); ZOrdering.Attach(item, _orderingGroup); DragAndDrop.Attach(item, GetPosition, SetPosition); UpdateGlobalPosition.Attach(item); _items.Add(item.Definition.ID, item); if (item.IsRootItem) { _rootItems.Add(item); } }
/// <summary> /// Set initial positions of given children /// </summary> /// <param name="parent">Parent of children</param> /// <param name="container">Container where children are displayed</param> /// <param name="children">Children which positions will be initialized</param> private void setInitialPositions(DiagramItem parent, DiagramCanvasBase container, IEnumerable <DiagramItem> children) { var isRoot = parent == null; var lastCursor = isRoot ? _rootCursor : parent.PositionCursor; var needsInitialPositions = lastCursor == null; if (needsInitialPositions) { var cursor = new PositionCursor(); Size lastLayoutSize; if (isRoot) { //root has no owner, because of that has special cursor _rootCursor = cursor; //we dont want to limit size of root canvas lastLayoutSize = new Size(); } else { //owner should keep their cursors parent.PositionCursor = cursor; lastLayoutSize = container.DesiredSize; } //inform cursor about items foreach (var child in children) { setInitialPosition(cursor, child); } //update positions of children cursor.UpdatePositions(lastLayoutSize); } foreach (var child in children) { child.GlobalPosition = checkBounds(child, child.GlobalPosition); } }
/// <summary> /// Add join into <see cref="Output"/> /// </summary> /// <param name="join">Added join</param> /// <param name="fromItem">Owner of join start connector</param> /// <param name="toItem">Owner of join end connector</param> internal void AddJoin(JoinDrawing join, DiagramItem fromItem, DiagramItem toItem) { var from = fromItem.GetConnector(join.Definition.From); var to = toItem.GetConnector(join.Definition.To); join.From = from; join.To = to; FollowConnectorPosition.Attach(from, this, (p) => { refreshJoinPath(join); }); FollowConnectorPosition.Attach(to, this, (p) => { refreshJoinPath(join); }); _joins.Add(join); Output.AddJoin(join); }
/// <summary> /// Initializes a new instance of the <see cref="ConnectorDrawing" /> class. /// </summary> /// <param name="definition">The definition.</param> /// <param name="align">The align.</param> /// <param name="owningItem">The owning item.</param> public ConnectorDrawing(ConnectorDefinition definition, ConnectorAlign align, DiagramItem owningItem) { Align = align; Definition = definition; OwningItem = owningItem; var halfMargin = 10; switch (Align) { case ConnectorAlign.Top: case ConnectorAlign.Bottom: Margin = new Thickness(halfMargin, 0, halfMargin, 0); break; case ConnectorAlign.Left: case ConnectorAlign.Right: Margin = new Thickness(0, halfMargin, 0, halfMargin); break; } }
/// <summary> /// Arrange children of given owner according to Arrange algorithm /// </summary> /// <param name="owner">Owner which children will be arranged</param> /// <param name="container">Container where children are arranged</param> internal Size ArrangeChildren(DiagramItem owner, DiagramCanvasBase container) { var isRoot = owner == null; var children = isRoot ? _rootItems : owner.Children; setInitialPositions(owner, container, children); if (Output.DiagramContext.Diagram.UseItemAvoidance) { var collisionRepairer = new ItemCollisionRepairer(); collisionRepairer.Arrange(children); } //create navigator after items are positioned Navigator = new SceneNavigator(Items); var borders = getChildrenBorders(children); refreshJoinPaths(); return(borders); }
/// <summary> /// Check bounds of given items. /// </summary> /// <param name="globalPosition">Position to repair.</param> /// <param name="item">Checked item</param> /// <returns>Repaired position.</returns> private Point checkBounds(DiagramItem item, Point globalPosition) { if (item.IsRootItem) { return(globalPosition); } var localPosition = item.AsLocalPosition(globalPosition); var left = globalPosition.X; var top = globalPosition.Y; if (localPosition.X < 0) { left -= localPosition.X; } if (localPosition.Y < 0) { top -= localPosition.Y; } return(new Point(left, top)); }
/// <summary> /// Initialize drawing of given item according to its definition /// </summary> /// <param name="item">Item to be initialized</param> internal void InitializeItemDrawing(DiagramItem item) { foreach (var connectorDefinition in item.ConnectorDefinitions) { var connector = _diagramFactory.CreateConnector(connectorDefinition, item); item.Attach(connector); } ContentDrawing content; if (item.IsRecursive) { content = _diagramFactory.CreateRecursiveContent(item); } else { content = _diagramFactory.CreateContent(item); } item.SetContent(content); Engine.RegisterItem(item); }
/// <summary> /// Fills the slot canvas with instances according to given slot definition. /// </summary> /// <param name="slotCanvas">The slot canvas that will be filled.</param> /// <param name="slot">The slot definition.</param> public void FillSlot(SlotCanvas slotCanvas, SlotDefinition slot) { //recursive check is required only for diagram items //filling some slots - only some of its children can be recursive slotCanvas.SetOwner(this); var ancestors = new HashSet<DiagramItemDefinition>(); var current = this; while (current != null) { ancestors.Add(current.Definition); current = current.ParentItem; } foreach (var itemReference in slot.References) { var itemDefinition = DiagramContext.Diagram.GetItemDefinition(itemReference.DefinitionID); var item = new DiagramItem(itemDefinition, this, slotCanvas); item.IsRecursive = ancestors.Contains(itemDefinition); DiagramContext.Provider.InitializeItemDrawing(item); slotCanvas.Children.Add(item); } }
/// <summary> /// Hints the position of given item in context of hintContext. /// </summary> /// <param name="hintContext">The hint context where position hint is valid.</param> /// <param name="hintedItem">The hinted item.</param> /// <param name="position">The hinted position.</param> internal void HintPosition(DiagramItem hintContext, DiagramItem hintedItem, Point position) { Provider.Engine.HintPosition(hintContext, hintedItem, position); }
/// <summary> /// Creates the connector according to given definition. /// </summary> /// <param name="definition">The connector definition.</param> /// <param name="owningItem">The owning item.</param> /// <returns>Created drawing.</returns> public abstract ConnectorDrawing CreateConnector(ConnectorDefinition definition, DiagramItem owningItem);
/// <summary> /// Hint position of <see cref="DiagramItem"/> so it can be displayed /// on hinted position in next redraw. /// </summary> /// <param name="hintContext">Context item of hint</param> /// <param name="hintedItem">Item that's position is hinted</param> /// <param name="point">Hinted position</param> internal void HintPosition(DiagramItem hintContext, DiagramItem hintedItem, Point point) { saveOldPosition(hintContext, hintedItem, point); }
/// <summary> /// Sets the item that owns current canvas. /// </summary> /// <param name="owner">The owner.</param> internal void SetOwner(DiagramItem owner) { OwnerItem = owner; SetContext(owner.DiagramContext); Children.Clear(); }
/// <summary> /// Initializes a new instance of the <see cref="ContentDrawing" /> class. /// </summary> /// <param name="item">The item where content is displayed.</param> public ContentDrawing(DiagramItem item) { Item = item; }
/// <summary> /// Creates the content that will be own by given diagram item. /// </summary> /// <param name="owningItem">The owning item.</param> /// <returns>Created content drawing.</returns> public abstract ContentDrawing CreateContent(DiagramItem owningItem);
/// <summary> /// Creates content of the recursive item that will be shown at <see cref="DiagramDefinition"/> instead. /// </summary> /// <param name="item">The item which will be replaced by recursive content.</param> /// <returns>Created recursive content.</returns> public abstract ContentDrawing CreateRecursiveContent(DiagramItem item);