/// <summary>
 /// Test for a double click if a commit is expected to signal the
 /// OnClicked to forward the click to the base ConnectAction and
 /// complete the operation.
 /// </summary>
 /// <param name="e">DiagramMouseEventArgs</param>
 protected override void OnMouseDown(DiagramMouseEventArgs e)
 {
     if (myPendingOnClickedAction == OnClickedAction.CheckForCommit && e.Clicks == 2 && e.Button == MouseButtons.Left)
     {
         myPendingOnClickedAction = OnClickedAction.Commit;
     }
     base.OnMouseDown(e);
 }
 private void Reset()
 {
     mySelectedRoles          = null;
     mySourceShape            = null;
     myIUC                    = null;
     myLastMouseMoveItem      = null;
     myPendingOnClickedAction = OnClickedAction.Normal;
     FactTypeShape.ActiveInternalUniquenessConstraintConnectAction = null;
 }
 /// <summary>
 /// Cancel if the last hit shape is the Diagram by not forwarding
 /// to the base class. Otherwise, complete the action.
 /// </summary>
 /// <param name="e">DiagramEventArgs</param>
 protected override void OnMouseActionCompleted(DiagramEventArgs e)
 {
     base.OnMouseActionCompleted(e);
     myPendingOnClickedAction = OnClickedAction.Complete;
 }
        /// <summary>
        /// Add a source shape or commit/cancel the action by forwarding the
        /// click to the base class, or modify the current role sequence by handling
        /// the click locally.
        /// </summary>
        /// <param name="e">MouseActionEventArgs</param>
        protected override void OnClicked(MouseActionEventArgs e)
        {
            switch (myPendingOnClickedAction)
            {
            case OnClickedAction.Commit:
                myPendingOnClickedAction = OnClickedAction.Normal;
                // Letting the click through to the base ConnectAction
                // at this point (a constraint is selected and a role has been
                // double-clicked) will force the connect action to finish.
                base.OnClicked(e);
                return;

            case OnClickedAction.CheckForCommit:
                myPendingOnClickedAction = OnClickedAction.Normal;
                break;
            }
            DiagramMouseEventArgs args = CurrentDiagramArgs as DiagramMouseEventArgs;

            if (args != null)
            {
                DiagramItem  item           = args.DiagramHitTestInfo.HitDiagramItem;
                ModelElement currentElement = null;
                foreach (ModelElement elem in item.RepresentedElements)
                {
                    currentElement = elem;
                    break;
                }
                UniquenessConstraint internalUniquenessConstraint;
                RoleBase             roleBase;
                if (null != (internalUniquenessConstraint = currentElement as UniquenessConstraint) &&
                    internalUniquenessConstraint.IsInternal)
                {
                    if (mySourceShape == null)
                    {
                        // Let the click through to the base to officially begin the drag action
                        base.OnClicked(e);
                        mySourceShape = item.Shape as FactTypeShape;
                        myIUC         = internalUniquenessConstraint;
                    }
                }
                else if (mySourceShape != null)
                {
                    if (null != (roleBase = currentElement as RoleBase))
                    {
                        Role role = roleBase.Role;
                        if (role.FactType == mySourceShape.AssociatedFactType)
                        {
                            // Add or remove the role
                            IList <Role> roles       = SelectedRoleCollection;
                            int          roleIndex   = roles.IndexOf(role);
                            bool         forceRedraw = false;
                            if (roleIndex >= 0)
                            {
                                // Only remove a role when the control key is down. Otherwise,
                                // there is no way to double-click on a previously selected
                                // role without turning it off, and this is a natural gesture.
                                // Add shift key as well for discoverability.
                                if (0 != (0xff00 & GetKeyState(Keys.ControlKey)) ||
                                    0 != (0xff00 & GetKeyState(Keys.ShiftKey)))
                                {
                                    forceRedraw = true;
                                    roles.RemoveAt(roleIndex);
                                }
                            }
                            else
                            {
                                forceRedraw = true;
                                roles.Add(role);
                            }
                            if (mySourceShape != null)
                            {
                                myPendingOnClickedAction = OnClickedAction.CheckForCommit;
                            }

                            if (forceRedraw)
                            {
                                // Force the shape to redraw
                                Debug.Assert(mySourceShape != null);                                 //source shape should have been set
                                mySourceShape.Invalidate(true);
                            }
                        }
                    }
                    else if (currentElement is ORMDiagram)
                    {
                        base.OnClicked(e);                         // Let through to allow a cancel
                    }
                }
            }
        }
		private void Reset()
		{
			mySelectedRoles = null;
			mySourceShape = null;
			myIUC = null;
			myLastMouseMoveItem = null;
			myPendingOnClickedAction = OnClickedAction.Normal;
			FactTypeShape.ActiveInternalUniquenessConstraintConnectAction = null;
		}
		/// <summary>
		/// Cancel if the last hit shape is the Diagram by not forwarding
		/// to the base class. Otherwise, complete the action.
		/// </summary>
		/// <param name="e">DiagramEventArgs</param>
		protected override void OnMouseActionCompleted(DiagramEventArgs e)
		{
			base.OnMouseActionCompleted(e);
			myPendingOnClickedAction = OnClickedAction.Complete;
		}
		/// <summary>
		/// Add a source shape or commit/cancel the action by forwarding the
		/// click to the base class, or modify the current role sequence by handling
		/// the click locally.
		/// </summary>
		/// <param name="e">MouseActionEventArgs</param>
		protected override void OnClicked(MouseActionEventArgs e)
		{
			switch (myPendingOnClickedAction)
			{
				case OnClickedAction.Commit:
					myPendingOnClickedAction = OnClickedAction.Normal;
					// Letting the click through to the base ConnectAction
					// at this point (a constraint is selected and a role has been
					// double-clicked) will force the connect action to finish.
					base.OnClicked(e);
					return;
				case OnClickedAction.CheckForCommit:
					myPendingOnClickedAction = OnClickedAction.Normal;
					break;
			}
			DiagramMouseEventArgs args = CurrentDiagramArgs as DiagramMouseEventArgs;
			if (args != null)
			{
				DiagramItem item = args.DiagramHitTestInfo.HitDiagramItem;
				ModelElement currentElement = null;
				foreach (ModelElement elem in item.RepresentedElements)
				{
					currentElement = elem;
					break;
				}
				UniquenessConstraint internalUniquenessConstraint;
				RoleBase roleBase;
				if (null != (internalUniquenessConstraint = currentElement as UniquenessConstraint) &&
					internalUniquenessConstraint.IsInternal)
				{
					if (mySourceShape == null)
					{
						// Let the click through to the base to officially begin the drag action
						base.OnClicked(e);
						mySourceShape = item.Shape as FactTypeShape;
						myIUC = internalUniquenessConstraint;
					}
				}
				else if (mySourceShape != null)
				{
					if (null != (roleBase = currentElement as RoleBase))
					{
						Role role = roleBase.Role;
						if (role.FactType == mySourceShape.AssociatedFactType)
						{
							// Add or remove the role
							IList<Role> roles = SelectedRoleCollection;
							int roleIndex = roles.IndexOf(role);
							bool forceRedraw = false;
							if (roleIndex >= 0)
							{
								// Only remove a role when the control key is down. Otherwise,
								// there is no way to double-click on a previously selected
								// role without turning it off, and this is a natural gesture.
								// Add shift key as well for discoverability.
								if (0 != (0xff00 & GetKeyState(Keys.ControlKey)) ||
									0 != (0xff00 & GetKeyState(Keys.ShiftKey)))
								{
									forceRedraw = true;
									roles.RemoveAt(roleIndex);
								}
							}
							else
							{
								forceRedraw = true;
								roles.Add(role);
							}
							if (mySourceShape != null)
							{
								myPendingOnClickedAction = OnClickedAction.CheckForCommit;
							}

							if (forceRedraw)
							{
								// Force the shape to redraw
								Debug.Assert(mySourceShape != null); //source shape should have been set
								mySourceShape.Invalidate(true);
							}
						}
					}
					else if (currentElement is ORMDiagram)
					{
						base.OnClicked(e); // Let through to allow a cancel
					}
				}
			}
		}
		/// <summary>
		/// Test for a double click if a commit is expected to signal the
		/// OnClicked to forward the click to the base ConnectAction and
		/// complete the operation.
		/// </summary>
		/// <param name="e">DiagramMouseEventArgs</param>
		protected override void OnMouseDown(DiagramMouseEventArgs e)
		{
			if (myPendingOnClickedAction == OnClickedAction.CheckForCommit && e.Clicks == 2 && e.Button == MouseButtons.Left)
			{
				myPendingOnClickedAction = OnClickedAction.Commit;
			}
			base.OnMouseDown(e);
		}
		private void Reset()
		{
			myConstraintRoleSequence = null;
			myInitialSelectedRoles = null;
			mySelectedRoles = null;
			mySourceShape = null;
			myActiveConstraint = null;
			myPendingOnClickedAction = OnClickedAction.Normal;
			mySubtypeConnection = false;
			myAllowSubtypeConnection = false;
			FactTypeShape.ActiveExternalConstraintConnectAction = null;
		}
		/// <summary>
		/// Add a source shape or commit/cancel the action by forwarding the
		/// click to the base class, or modify the current role sequence by handling
		/// the click locally.
		/// </summary>
		/// <param name="e">MouseActionEventArgs</param>
		protected override void OnClicked(MouseActionEventArgs e)
		{
			switch (myPendingOnClickedAction)
			{
				case OnClickedAction.Commit:
					myPendingOnClickedAction = OnClickedAction.Normal;
					// Letting the click through to the base ConnectAction
					// at this point (a constraint is selected and a role has been
					// double-clicked) will force the connect action to finish.
					base.OnClicked(e);
					return;
				case OnClickedAction.CheckForCommit:
					myPendingOnClickedAction = OnClickedAction.Normal;
					break;
			}
			DiagramMouseEventArgs args = CurrentDiagramArgs as DiagramMouseEventArgs;
			if (args != null)
			{
				DiagramItem item = args.DiagramHitTestInfo.HitDiagramItem;
				ModelElement currentElement = null;
				bool isSupertypeRole = false;
				ORMDiagram ormDiagram;
				foreach (ModelElement elem in item.RepresentedElements)
				{
					currentElement = elem;
					SubtypeLink subtypeLink = currentElement as SubtypeLink;
					if (subtypeLink != null)
					{
						isSupertypeRole = true;
						currentElement = subtypeLink.AssociatedSubtypeFact.SupertypeRole;
					}
					break;
				}
				ExternalConstraintShape constraintShape;
				Role role;
				if (null != (constraintShape = currentElement as ExternalConstraintShape))
				{
					if (mySourceShape == null)
					{
						// Let the click through to the base to officially begin the drag action
						base.OnClicked(e);
						mySourceShape = constraintShape;
						IConstraint activeConstraint = constraintShape.AssociatedConstraint;
						myActiveConstraint = activeConstraint;
						switch (activeConstraint.ConstraintType)
						{
							case ConstraintType.DisjunctiveMandatory:
								// This setting is refined later
								myAllowSubtypeConnection = true;
								break;
							case ConstraintType.Exclusion:
								ExclusionConstraint exclusion = (ExclusionConstraint)activeConstraint;
								// If the exclusion constraint is currently attached to any fact types
								// that are not subtype facts, then we cannot allow a subtype connection.
								LinkedElementCollection<FactType> exclusionFactTypes = exclusion.FactTypeCollection;
								myAllowSubtypeConnection = (exclusionFactTypes.Count == 0) ? true : exclusionFactTypes[0] is SubtypeFact;
								break;
							default:
								myAllowSubtypeConnection = false;
								break;
						}
						if (null != (ormDiagram = mySourceShape.Diagram as ORMDiagram))
						{
							ormDiagram.StickyObject = constraintShape;
						}
					}
				}
				else if (null != (role = currentElement as Role))
				{
					// Add or remove the role
					IList<Role> roles = SelectedRoleCollection;
					int roleIndex = roles.IndexOf(role);
					bool forceRedraw = false;
					int redrawIndexBound = -1;
					ExternalConstraintShape sourceShape = mySourceShape;
					if (roleIndex >= 0)
					{
						// Only remove a role when the control key is down. Otherwise,
						// there is no way to double-click on a previously selected
						// role without turning it off, and this is a natural gesture.
						// Add shift key as well for discoverability.
						if (0 != (0xff00 & GetKeyState(Keys.ControlKey)) ||
							0 != (0xff00 & GetKeyState(Keys.ShiftKey)))
						{
							forceRedraw = true;
							roles.RemoveAt(roleIndex);
							redrawIndexBound = roles.Count;
							if (roles.Count == 0 && mySubtypeConnection && InitialRoles.Count == 0)
							{
								mySubtypeConnection = false;
							}
						}
					}
					else
					{
						bool allowAdd = false;
						if (mySubtypeConnection)
						{
							allowAdd = isSupertypeRole;
						}
						else if (isSupertypeRole)
						{
							if (roles.Count == 0 && InitialRoles.Count == 0 && myAllowSubtypeConnection)
							{
								mySubtypeConnection = true;
								allowAdd = true;
							}
						}
						else
						{
							allowAdd = true;
						}
						if (allowAdd)
						{
							forceRedraw = true;
							roles.Add(role);
						}
						else
						{
							sourceShape = null;
						}
					}
					if (sourceShape != null)
					{
						myPendingOnClickedAction = OnClickedAction.CheckForCommit;
					}

					if (forceRedraw)
					{
						// Force the shape types to redraw
						RedrawOwningFactType(role);

						// Force anything with a later index to redraw as well.
						// These roles may be on different fact types than the
						// original.
						for (int i = roleIndex; i < redrawIndexBound; ++i)
						{
							RedrawOwningFactType(roles[i]);
						}
					}
				}
				else if (mySourceShape != null && null != (ormDiagram = currentElement as ORMDiagram))
				{
#if VISUALSTUDIO_10_0
					if (IsActive)
					{
						Cancel(e.DiagramClientView);
					}
#else
					base.OnClicked(e); // Let through to allow a cancel
#endif
				}
			}
		}