public RelationshipCreationCommand(CompositionEngine TargetEngine, RelationshipDefinition RelationshipDef) : base("Create Relationship '" + RelationshipDef.Name + "'.") { this.ContextEngine = TargetEngine; this.RelationshipDef = RelationshipDef; this.PointingConnectorFormat = RelationshipDef.DefaultConnectorsFormat; this.Initialize(); this.Assistance = "Press [Left-ALT] to link the pointed Idea as origin."; }
public override void Initialize() { OriginRepresentation = null; OriginLocation = Display.NULL_POINT; TargetRepresentation = null; TargetLocation = Display.NULL_POINT; WasKeyShiftPressed = false; WasKeyCtrlPressed = false; IsConnecting = false; // Very important to clear prior to restart PointingConnectorFormat = null; base.Initialize(); var Loader = Display.GetResource <TextBlock>("CursorLoaderArrowIdea"); // Trick for assign custom cursors. Display.GetCurrentWindow().Cursor = Loader.Cursor; PointingAssistant.Start(this.ContextEngine.CurrentView, this.RelationshipDef.GetSampleDrawing(true), true, Cursors.Cross); }
// --------------------------------------------------------------------------------------------------------------------------------------------------------- /// <summary> /// Creates and returns a new draw implementing this visual connector for an optional presentation context. /// </summary> public override DrawingGroup CreateDraw(UIElement PresentationContext, bool ShowManipulationAdorners) { // Calculate the Edge Positions if (this.OriginSymbol.Graphic == null) { this.OriginSymbol.GenerateGraphic(PresentationContext, ShowManipulationAdorners); } if (this.TargetSymbol.Graphic == null) { this.TargetSymbol.GenerateGraphic(PresentationContext, ShowManipulationAdorners); } // IMPORTANT: This validation allows to calculate edge-positions ONLY when not present. // The last calculated edge-positions are used for when presentation-context is not supplied, // which is used for generating the graphics of a composite-content view inside a symbol's details poster. if (PresentationContext == null && (this.OriginEdgePosition == Display.NULL_POINT || this.TargetEdgePosition == Display.NULL_POINT)) { PresentationContext = this.OwnerRepresentation.DisplayingView.Presenter; } DrawingGroup Result = null; if (this.IntermediatePosition == Display.NULL_POINT) { if (PresentationContext != null) { /*T Console.WriteLine("OriSym={0}=>{1}, TarSym={2}=>{3}.", * this.OriginSymbol, this.OriginSymbol.Graphic.GetHashCode(), * this.TargetSymbol, this.TargetSymbol.Graphic.GetHashCode()); */ if (this.OriginSymbol.IsRelatedVisible) { this.OriginEdgePosition = (this.OriginSymbol.IsHidden ? this.OriginPosition : this.OriginPosition.DetermineNearestIntersectingPoint(this.TargetPosition, PresentationContext, this.OriginSymbol.Graphic, this.OwnerRepresentation.DisplayingView.VisualHitTestFilter)); } if (this.TargetSymbol.IsRelatedVisible) { this.TargetEdgePosition = (this.TargetSymbol.IsHidden ? this.TargetPosition : this.TargetPosition.DetermineNearestIntersectingPoint(this.OriginPosition, PresentationContext, this.TargetSymbol.Graphic, this.OwnerRepresentation.DisplayingView.VisualHitTestFilter)); } // Nasty trick to compensate miscalculation of border position (or after undoing a relationship-central-symbol move) if (this.OriginEdgePosition == this.TargetSymbol.BaseCenter) { this.OriginPosition = this.OriginSymbol.BaseCenter.FindBoundary(this.OriginPosition, PresentationContext, this.OriginSymbol.Graphic, true) .SubstituteFor(default(Point), this.OriginSymbol.BaseCenter); this.OriginEdgePosition = this.OriginPosition; } if (this.TargetEdgePosition == this.OriginSymbol.BaseCenter) { this.TargetPosition = this.TargetSymbol.BaseCenter.FindBoundary(this.TargetPosition, PresentationContext, this.TargetSymbol.Graphic, true) .SubstituteFor(default(Point), this.TargetSymbol.BaseCenter); this.TargetEdgePosition = this.TargetPosition; } } /*T Console.WriteLine("OriginEdgePoint X={0}, Y={1}. TargetEdgePoint X={2}, Y={3}", * Math.Truncate(this.OriginEdgePosition.X), Math.Truncate(this.OriginEdgePosition.Y), * Math.Truncate(this.TargetEdgePosition.X), Math.Truncate(this.TargetEdgePosition.Y)); */ // Draw the Connector line Result = MasterDrawer.CreateDrawingConnector(this.OriginPlug, this.TargetPlug, VisualConnectorsFormat.GetLineBrush(this), VisualConnectorsFormat.GetLineThickness(this), VisualConnectorsFormat.GetLineDash(this), VisualConnectorsFormat.GetLineJoin(this), VisualConnectorsFormat.GetLineCap(this), VisualConnectorsFormat.GetPathStyle(this), VisualConnectorsFormat.GetPathCorner(this), VisualConnectorsFormat.GetMainBackground(this), VisualConnectorsFormat.GetOpacity(this), this.TargetEdgePosition, this.OriginEdgePosition, null, VISUAL_MAGNITUDE_ADJUSTMENT); /*T visual cue for detecting miscalculations... * Result.Children.Add(new GeometryDrawing(Brushes.Green, new Pen(Brushes.Red, 1.0), * new EllipseGeometry(new Point(this.OriginEdgePosition.X + 100, this.OriginEdgePosition.Y), 3, 3))); * Result.Children.Add(new GeometryDrawing(Brushes.Blue, new Pen(Brushes.Red, 1.0), * new EllipseGeometry(new Point(this.TargetEdgePosition.X + 100, this.TargetEdgePosition.Y), 3, 3))); */ } else { if (PresentationContext != null) { var EdgePos = (this.OriginSymbol.IsHidden ? this.OriginPosition : this.OriginPosition.DetermineNearestIntersectingPoint(this.IntermediatePosition, PresentationContext, this.OriginSymbol.Graphic, this.OwnerRepresentation.DisplayingView.VisualHitTestFilter)); if (EdgePos != this.IntermediatePosition) { this.OriginEdgePosition = EdgePos; } EdgePos = (this.TargetSymbol.IsHidden ? this.TargetPosition : this.TargetPosition.DetermineNearestIntersectingPoint(this.IntermediatePosition, PresentationContext, this.TargetSymbol.Graphic, this.OwnerRepresentation.DisplayingView.VisualHitTestFilter)); if (EdgePos != this.IntermediatePosition) { this.TargetEdgePosition = EdgePos; } } //T Console.WriteLine("OriginEdgePoint X={0}, Y={1}. TargetEdgePoint X={2}, Y={3}. IP={4}", OriginEdgePoint.X, OriginEdgePoint.Y, TargetEdgePoint.X, TargetEdgePoint.Y, this.IntermediatePosition); // Draw the Connector origin line Result = MasterDrawer.CreateDrawingConnector(this.OriginPlug, Plugs.None, VisualConnectorsFormat.GetLineBrush(this), VisualConnectorsFormat.GetLineThickness(this), VisualConnectorsFormat.GetLineDash(this), VisualConnectorsFormat.GetLineJoin(this), VisualConnectorsFormat.GetLineCap(this), VisualConnectorsFormat.GetPathStyle(this), VisualConnectorsFormat.GetPathCorner(this), VisualConnectorsFormat.GetMainBackground(this), VisualConnectorsFormat.GetOpacity(this), this.IntermediatePosition, this.OriginEdgePosition, null, VISUAL_MAGNITUDE_ADJUSTMENT); // Draw the Connector target line Result.Children.Add( MasterDrawer.CreateDrawingConnector(Plugs.None, this.TargetPlug, VisualConnectorsFormat.GetLineBrush(this), VisualConnectorsFormat.GetLineThickness(this), VisualConnectorsFormat.GetLineDash(this), VisualConnectorsFormat.GetLineJoin(this), VisualConnectorsFormat.GetLineCap(this), VisualConnectorsFormat.GetPathStyle(this), VisualConnectorsFormat.GetPathCorner(this), VisualConnectorsFormat.GetMainBackground(this), VisualConnectorsFormat.GetOpacity(this), this.TargetEdgePosition, this.IntermediatePosition, null, VISUAL_MAGNITUDE_ADJUSTMENT)); } /*T Console.WriteLine("OriginEdgePosition X={0}, Y={1}. TargetEdgePosition X={2}, Y={3}. IP={4}", * OriginEdgePosition.X, OriginEdgePosition.Y, TargetEdgePosition.X, TargetEdgePosition.Y, this.IntermediatePosition); */ // PENDING: Register periferic decorators for drawing (such as callouts, notes, etc. Not to be confused with Text decorations) // Show main-symbol name if required var RelDef = this.RepresentedLink.OwnerRelationship.RelationshipDefinitor.Value; /* ? * if (RelDef.IsSimple && RelDef.HideCentralSymbolWhenSimple && RelDef.ShowNameIfHidingCentralSymbol) * { * var LabelingBrushes = this.OwnerRelationshipRepresentation.MainSymbol.PutNameOnTop(Result); * this.OwnerRelationshipRepresentation.MainSymbol.PutDefinitionOnTop(Result, LabelingBrushes.Item2, LabelingBrushes.Item1, 4); * } * else * if (this.OwnerRelationshipRepresentation.MainSymbol.IsHidden) * { * var LabelingBrushes = this.OwnerRelationshipRepresentation.MainSymbol.GetDefaultLabelBrushes(); * this.OwnerRelationshipRepresentation.MainSymbol.PutDefinitionOnTop(Result, LabelingBrushes.Item2, LabelingBrushes.Item1); * } */ this.LabelArea = null; // Show link-role name decorator if required if (RelDef.DefaultConnectorsFormat.LabelLinkVariant || RelDef.DefaultConnectorsFormat.LabelLinkDefinitor || RelDef.DefaultConnectorsFormat.LabelLinkDescriptor || this.OwnerRepresentation.DisplayingView.ShowLinkRoleVariantLabels || this.OwnerRepresentation.DisplayingView.ShowLinkRoleDefNameLabels || this.OwnerRepresentation.DisplayingView.ShowLinkRoleDescNameLabels) { using (var Context = Result.Append()) { var DecoratorCenter = this.IntermediatePosition; if (DecoratorCenter == Display.NULL_POINT) { DecoratorCenter = new Point((this.OriginEdgePosition.X + this.TargetEdgePosition.X) / 2.0, (this.OriginEdgePosition.Y + this.TargetEdgePosition.Y) / 2.0); } /*T else * Console.WriteLine("DecoratorCenter = IntermediatePoint"); */ //T Console.WriteLine("DecoratorCenter: X={0}, Y={1}", DecoratorCenter.X, DecoratorCenter.Y); var LinkDescriptorLabel = (((RelDef.DefaultConnectorsFormat.LabelLinkDescriptor || this.OwnerRepresentation.DisplayingView.ShowLinkRoleDescNameLabels) && this.RepresentedLink.Descriptor != null) ? this.RepresentedLink.Descriptor.Name : null); var LinkDefinitorLabel = (RelDef.DefaultConnectorsFormat.LabelLinkDefinitor || this.OwnerRepresentation.DisplayingView.ShowLinkRoleDefNameLabels ? this.RepresentedLink.RoleDefinitor.Name : null); var LinkRoleVariantLabel = (RelDef.DefaultConnectorsFormat.LabelLinkVariant || this.OwnerRepresentation.DisplayingView.ShowLinkRoleVariantLabels ? this.RepresentedLink.RoleVariant.ToString() : null); this.LabelArea = MasterDrawer.PutConnectorLabeling(Context, RelDef, DecoratorCenter, VisualSymbolFormat.GetTextFormat(this.OwnerRelationshipRepresentation.MainSymbol, ETextPurpose.Extra), VisualConnectorsFormat.GetMainBackground(this), VisualConnectorsFormat.GetLineBrush(this), LinkDescriptorLabel, LinkDefinitorLabel, LinkRoleVariantLabel); } } // Register Selection Indicators for drawing // NOTE: (selection indicators at the symbol's center interfere with in-place editing) if (ShowManipulationAdorners) { if (this.OwnerRepresentation.IsSelected) { var SizeFactor = (this.GetDisplayingView().SelectedObjects.Contains(this) ? 1.5 : 0.5); this.OwnerRepresentation.DisplayingView.AttachAdorner(this, GenerateSelectionIndicators(INDICATOR_SIZE * SizeFactor, SelectionIndicatorBackground, SelectionIndicatorForeground).Select(tup => tup.Item1)); } else { this.OwnerRepresentation.DisplayingView.DetachAdorner(this); } } if (this.OwnerRepresentation.IsVanished) { Result.Opacity = VisualRepresentation.SELECTION_VANISHING_OPACITY; } return(Result); }
public override bool Continue(MouseEventArgs Parameter, bool IsDefinitive = true) { var Go = base.Continue(Parameter, IsDefinitive); if (!Go) { return(false); } if (this.WorkingView == null) { this.WorkingView = this.ContextEngine.CurrentView; } if (this.WorkingView != this.ContextEngine.CurrentView) { this.Terminate(); return(false); } this.TargetLocation = Parameter.GetPosition(this.WorkingView.PresenterControl); this.TargetRepresentation = this.ContextEngine.GetPointedRepresentation(this.TargetLocation, true); var TargetObject = this.ContextEngine.GetPointedVisualObject(this.TargetLocation, 2.0); // IMPORTANT: Get the snapped position AFTER obtain the pointed representation if (this.WorkingView.SnapToGrid) { this.TargetLocation = this.WorkingView.GetGridSnappedPosition(TargetLocation, false); } this.WasKeyShiftPressed = (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift)); this.WasKeyCtrlPressed = (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl)); if (this.TargetRepresentation != null && !(this.TargetRepresentation.RepresentedIdea.IdeaDefinitor.PreciseConnectByDefault || this.WasKeyCtrlPressed)) { this.TargetLocation = this.TargetRepresentation.MainSymbol.BaseCenter; } if (IsDefinitive) // If selecting a target representation... { //T Console.WriteLine("Pointed VisObj={0}", TargetObject.ToStringAlways("<NULL>")); PointingAssistant.ClearConnector(); if (!this.IsConnecting) { /* Better at definitive target (?) * this.WasKeyCtrlPressed = (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl)); * this.WasKeyShiftPressed = (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift)); */ this.OriginLocation = Parameter.GetPosition(this.WorkingView.PresenterControl); this.OriginRepresentation = this.ContextEngine.GetPointedRepresentation(this.OriginLocation, true); // IMPORTANT: Get the snapped position AFTER obtain the pointed representation if (this.WorkingView.SnapToGrid) { this.OriginLocation = this.WorkingView.GetGridSnappedPosition(this.OriginLocation, false); } if (this.OriginRepresentation == null) // Exit if nothing pointed at the beginning { return(true); } if (!this.OriginRepresentation.RepresentedIdea.IdeaDefinitor.PreciseConnectByDefault && !this.WasKeyCtrlPressed) { this.OriginLocation = this.OriginRepresentation.MainSymbol.BaseCenter; } this.IsConnecting = true; return(true); } if (this.OriginRepresentation == this.TargetRepresentation) { return(true); } // Needed to discard cancellation from a previous mouse-right-button click. this.RestartAfterTermination = true; if (this.TargetRepresentation == null && TargetObject != null && TargetObject is VisualComplement) { var Complement = (VisualComplement)TargetObject; // NOTE: This don't work if pointing to a complement with null background (it is not seen). if (Complement.CanGroup && (!Complement.Target.IsGlobal && Complement.Target.OwnerLocal.OwnerRepresentation.RepresentedIdea.IdeaDefinitor.CanAutomaticallyCreateGroupedConcepts && Complement.Target.OwnerLocal.OwnerRepresentation.RepresentedIdea.IdeaDefinitor.AutomaticGroupedConceptDef != null)) { // PENDING: Create grouped Concept and use it as target-representation. var ConceptDef = Complement.Target.OwnerLocal.OwnerRepresentation.RepresentedIdea.IdeaDefinitor.AutomaticGroupedConceptDef; var Position = this.TargetLocation; if (Complement.IsComplementGroupLine) { var Direction = Complement.GetPropertyField <Orientation>(VisualComplement.PROP_FIELD_ORIENTATION); if (Direction == Orientation.Vertical) { Position = new Point(Complement.BaseCenter.X, this.TargetLocation.Y + ((ConceptDef.DefaultSymbolFormat.InitialHeight / 2.0) * (this.TargetLocation.Y >= Complement.Target.OwnerLocal.BaseCenter.Y ? 1.0 : -1.0))); } else { Position = new Point(this.TargetLocation.X + ((ConceptDef.DefaultSymbolFormat.InitialWidth / 2.0) * (this.TargetLocation.X >= Complement.Target.OwnerLocal.BaseCenter.X ? 1.0 : -1.0)), Complement.BaseCenter.Y); } } var Creation = ConceptCreationCommand.CreateConcept(this.WorkingView.VisualizedCompositeIdea, ConceptDef, this.WorkingView, Position); if (Creation.WasSuccessful) { this.TargetRepresentation = Creation.Result.VisualRepresentators.First(); } } } var OrigRep = this.OriginRepresentation; var TargRep = this.TargetRepresentation; var OrigLoc = this.OriginLocation; var TargLoc = this.TargetLocation; // Allows extend Relationship from alternate origin. // Notice that the target (later used as origin) must be not-null. if ((Keyboard.IsKeyDown(Key.LeftAlt)) && !this.WasKeyShiftPressed && TargRep != null) { var TmpRep = OrigRep; OrigRep = TargRep; TargRep = TmpRep; var TmpLoc = OrigLoc; OrigLoc = TargLoc; TargLoc = TmpLoc; } // NOTE: TargetRepresentation can be null, so the intermediate MainSymbol can be created with no targets yet. var CreationResult = CreateRelationship(this.WorkingView.VisualizedCompositeIdea, this.RelationshipDef, this.WorkingView, OrigRep, OrigLoc, TargRep, TargLoc, !this.WasKeyShiftPressed, // Extend from origin. !(Keyboard.IsKeyDown(Key.RightAlt) && // IMPORTANT: This crashes if applied to a Simple-and-hiding-central-symbol Relationship !(this.RelationshipDef.IsSimple && this.RelationshipDef.HideCentralSymbolWhenSimple))); // Extend Relationship, else create Rel. from Rel. this.WasKeyShiftPressed = false; this.WasKeyCtrlPressed = false; if (CreationResult.WasSuccessful) { bool CanSelect = !this.RelationshipDef.HideCentralSymbolWhenSimple; // If a True boolean was passed, indicating to edit-in-place and can select... bool CanEditInPlace = (CreationResult.Parameters.InterpretItem <bool>() && CanSelect); this.OriginRepresentation = CreationResult.Result.VisualRepresentators[0]; // Re-start linking from Relationship Central/Main-Symbol center. this.OriginLocation = this.OriginRepresentation.MainSymbol.BaseCenter; this.WorkingView.Presenter .PostCall(pres => // Post-called in order to be executed after the symbol heading-content area is established (on first draw). { var Symbol = CreationResult.Result.VisualRepresentators[0].MainSymbol; if (CanSelect) { pres.OwnerView.Manipulator.ApplySelection(Symbol); } if (CanEditInPlace) { pres.OwnerView.EditInPlace(Symbol); } }); // PENDING: Also quit if role is non multi-connectable if (this.RelationshipDef.IsSimple) { var RelationshipRep = CreationResult.Context as RelationshipVisualRepresentation; if (RelationshipRep != null) { if (RelationshipRep.VisualConnectorsCount > 1) { return(false); } else if (!RelationshipDef.HideCentralSymbolWhenSimple) { RelationshipRep.MainSymbol.IsAutoPositionable = false; } } else { return(false); } } } else { this.IsConnecting = false; Console.WriteLine("Cannot create/change Relationship: " + CreationResult.Message.AbsentDefault("?")); this.Terminate(); return(false); } } else // Else, if just pointing... { if (this.IsConnecting && this.OriginRepresentation != null) { if (this.PointingConnectorFormat == null) { this.PointingConnectorFormat = new VisualConnectorsFormat(this.RelationshipDef.OwnerDomain.LinkRoleVariants.First(), Plugs.None, this.RelationshipDef.OwnerDomain.LinkRoleVariants.First(), Plugs.SimpleArrow, DefaultPointingConnectorBrush); } var OrigPlug = Plugs.None; var TargPlug = Plugs.SimpleArrow; if ((Keyboard.IsKeyDown(Key.LeftAlt)) && !this.WasKeyShiftPressed) { var TmpPlug = OrigPlug; OrigPlug = TargPlug; TargPlug = TmpPlug; } var GraphicPointer = MasterDrawer.CreateDrawingConnector(OrigPlug, TargPlug, this.PointingConnectorFormat.LineBrush, this.PointingConnectorFormat.LineThickness, this.PointingConnectorFormat.LineDash, this.PointingConnectorFormat.LineJoin, this.PointingConnectorFormat.LineCap, this.PointingConnectorFormat.PathStyle, this.PointingConnectorFormat.PathCorner, this.PointingConnectorFormat.MainBackground, this.PointingConnectorFormat.Opacity, this.TargetLocation, this.OriginLocation); PointingAssistant.PutConnector(GraphicPointer); this.RestartAfterTermination = true; } } // Continue the command... return(true); }
public VisualConnectorsFormatSubform(string ChildPropertyName, VisualConnectorsFormat TargetFormat) : this() { this.ChildPropertyName = ChildPropertyName; this.TargetFormat = TargetFormat; }