// ----------------------------------------------------------------------
        void AddDeleteMenuItem(ref iCS_MenuContext[] menu)
        {
            int idx = GrowMenuBy(ref menu, 2);

            menu[idx]     = new iCS_MenuContext(SeparatorStr);
            menu[idx + 1] = new iCS_MenuContext(DeleteStr);
        }
 // ----------------------------------------------------------------------
 void FunctionMenu(iCS_EditorObject selectedObject, iCS_IStorage storage)
 {
     iCS_MenuContext[] menu;
     if (!selectedObject.IsIconizedInLayout)
     {
         // Base menu items
         menu = new iCS_MenuContext[0];
         int idx = 0;
         // -- Add Enable & Trigger --
         idx       = GrowMenuBy(ref menu, 1);
         menu[idx] = new iCS_MenuContext(EnablePortStr);
         idx       = GrowMenuBy(ref menu, 1);
         if (storage.HasTriggerPort(selectedObject))
         {
             menu[idx] = new iCS_MenuContext("#" + TriggerPortStr);
         }
         else
         {
             menu[idx] = new iCS_MenuContext(TriggerPortStr);
         }
         idx       = GrowMenuBy(ref menu, 1);
         menu[idx] = new iCS_MenuContext(SeparatorStr);
     }
     else
     {
         menu = new iCS_MenuContext[0];
     }
     AddWrapInPackageIfAppropriate(ref menu, selectedObject);
     AddShowInHierarchyMenuItem(ref menu);
     AddDeleteMenuItem(ref menu);
     ShowMenu(menu, selectedObject, storage);
 }
        // ----------------------------------------------------------------------
        void AddShowInHierarchyMenuItem(ref iCS_MenuContext[] menu)
        {
            int idx = GrowMenuBy(ref menu, 2);

            menu[idx]     = new iCS_MenuContext(SeparatorStr);
            menu[idx + 1] = new iCS_MenuContext(ShowHierarchyStr);
        }
        // ----------------------------------------------------------------------
        iCS_MenuContext[] StartWithFocusMenu(iCS_EditorObject selectedObject)
        {
            iCS_MenuContext[] menu = new iCS_MenuContext[0];
            AddNavigationMenu(ref menu, selectedObject);
            int idx = GrowMenuBy(ref menu, 1);

            menu[idx] = new iCS_MenuContext(SeparatorStr);
            return(menu);
        }
 // ----------------------------------------------------------------------
 void SelectedPortMenu(iCS_EditorObject port, iCS_IStorage storage)
 {
     iCS_MenuContext[] menu = new iCS_MenuContext[1];
     menu[0] = new iCS_MenuContext(ShowHierarchyStr);
     // Allow to delete a port if its parent is a module.
     if (port.CanBeDeleted())
     {
         AddDeleteMenuItem(ref menu);
     }
     ShowMenu(menu, port, storage);
 }
        // ----------------------------------------------------------------------
        void MultiSelectionMenu(iCS_IStorage iStorage)
        {
            var multiSelectedObjects = iStorage.GetMultiSelectedObjects();

            if (multiSelectedObjects == null || multiSelectedObjects.Length == 0)
            {
                return;
            }
            iCS_MenuContext[] menu = new iCS_MenuContext[3];
            menu[0] = new iCS_MenuContext(MultiSelectionWrapInPackageStr);
            menu[1] = new iCS_MenuContext(SeparatorStr);
            menu[2] = new iCS_MenuContext(MultiSelectionDeleteStr);
            ShowMenu(menu, null, iStorage);
        }
        // ======================================================================
        // Menu Creation Utilities
        // ----------------------------------------------------------------------
        int GrowMenuBy(ref iCS_MenuContext[] menu, int additionalSize)
        {
            int sze = menu == null ? 0 : menu.Length;

            if (additionalSize == 0)
            {
                return(sze);
            }
            var newMenu = new iCS_MenuContext[sze + additionalSize];

            menu.CopyTo(newMenu, 0);
            menu = newMenu;
            return(sze);
        }
 // ----------------------------------------------------------------------
 void OnStatePackageMenu(iCS_EditorObject targetObject)
 {
     iCS_MenuContext[] menu = StartWithFocusMenu(targetObject);
     if (!targetObject.IsIconizedInLayout && !targetObject.IsFoldedInLayout)
     {
         // Base menu items
         int idx = GrowMenuBy(ref menu, 3);
         menu[idx]     = new iCS_MenuContext(PackageStr);
         menu[idx + 1] = new iCS_MenuContext(StateChartStr);
         menu[idx + 2] = new iCS_MenuContext(SeparatorStr);
     }
     AddShowInHierarchyMenuItem(ref menu);
     AddDeleteMenuItem(ref menu);
     ShowMenu(menu, targetObject, targetObject.IStorage);
 }
        // ----------------------------------------------------------------------
        void AddNavigationMenu(ref iCS_MenuContext[] menu, iCS_EditorObject obj)
        {
            var iStorage = obj.IStorage;

            if (iStorage.DisplayRoot != iStorage.RootObject ||
                iStorage.HasForwardNavigationHistory || iStorage.HasBackwardNavigationHistory)
            {
                int idx = GrowMenuBy(ref menu, 1);
                menu[idx] = new iCS_MenuContext(ClearNavigationHistoryStr);
            }
            if (obj != iStorage.DisplayRoot)
            {
                int idx = GrowMenuBy(ref menu, 1);
                menu[idx] = new iCS_MenuContext(SetAsDisplayRootStr);
            }
        }
        // ----------------------------------------------------------------------
        void CommonPackageMenu(iCS_EditorObject selectedObject, iCS_IStorage storage, ref iCS_MenuContext[] menu)
        {
            int idx;

            if (!selectedObject.IsIconizedInLayout && !selectedObject.IsFoldedInLayout)
            {
                // Base menu items
                idx           = GrowMenuBy(ref menu, 4);
                menu[idx]     = new iCS_MenuContext(PackageStr);
                menu[idx + 1] = new iCS_MenuContext(StateChartStr);
                menu[idx + 2] = new iCS_MenuContext(InlineCodeStr);
                menu[idx + 3] = new iCS_MenuContext(SeparatorStr);
            }
            if (!selectedObject.IsFunctionDefinition && !selectedObject.IsEventHandler)
            {
                idx       = GrowMenuBy(ref menu, 2);
                menu[idx] = new iCS_MenuContext(EnablePortStr);
                if (storage.HasTriggerPort(selectedObject))
                {
                    menu[idx + 1] = new iCS_MenuContext("#" + TriggerPortStr);
                }
                else
                {
                    menu[idx + 1] = new iCS_MenuContext(TriggerPortStr);
                }
            }
            AddWrapInPackageIfAppropriate(ref menu, selectedObject);
            if (selectedObject.ObjectType == VSObjectType.Package)
            {
                if (selectedObject.HasChildNode())
                {
                    idx       = GrowMenuBy(ref menu, 1);
                    menu[idx] = new iCS_MenuContext(UnwrapPackageStr);
                }
            }
            AddShowInHierarchyMenuItem(ref menu);
            AddDeleteMenuItem(ref menu);
            if (selectedObject.ObjectType == VSObjectType.Package)
            {
                if (selectedObject.HasChildNode())
                {
                    idx       = GrowMenuBy(ref menu, 1);
                    menu[idx] = new iCS_MenuContext(UnwrapPackageStr);
                }
            }
        }
 // ----------------------------------------------------------------------
 void StateChartMenu(iCS_EditorObject selectedObject, iCS_IStorage storage)
 {
     iCS_MenuContext[] menu = StartWithFocusMenu(selectedObject);
     AddEnableAndTriggerMenuItem(ref menu, selectedObject);
     if (!selectedObject.IsIconizedInLayout && !selectedObject.IsFoldedInLayout)
     {
         int idx = GrowMenuBy(ref menu, 1);
         menu[idx] = new iCS_MenuContext(StateStr);
     }
     AddWrapInPackageIfAppropriate(ref menu, selectedObject);
     AddShowInHierarchyMenuItem(ref menu);
     if (selectedObject.InstanceId != 0)
     {
         AddDeleteMenuItem(ref menu);
     }
     ShowMenu(menu, selectedObject, storage);
 }
        // ----------------------------------------------------------------------
        void AddWrapInPackageIfAppropriate(ref iCS_MenuContext[] menu, iCS_EditorObject obj)
        {
            // Don't add if object cannot support a parent package.
            if (!obj.CanHavePackageAsParent())
            {
                return;
            }
            if (menu == null || menu.Length == 0)
            {
                menu    = new iCS_MenuContext[1];
                menu[0] = new iCS_MenuContext(WrapInPackageStr);
                return;
            }
            int i = GrowMenuBy(ref menu, 2);

            menu[i]     = new iCS_MenuContext(SeparatorStr);
            menu[i + 1] = new iCS_MenuContext(WrapInPackageStr);
        }
        // ======================================================================
        // High-Level Creation Utilities
        // ----------------------------------------------------------------------
        static void CreateObjectInstance(iCS_MenuContext context)
        {
            var iStorage   = context.Storage;
            var sourcePort = context.SelectedObject;
            var pos        = context.GraphPosition;
            var parent     = iStorage.GetNodeAt(pos);

            if (parent == null)
            {
                return;
            }
            iCS_UserCommands.OpenTransaction(iStorage);
            var instance = iCS_UserCommands.CreateObjectInstance(parent, pos, sourcePort.RuntimeType);

            if (sourcePort != null)
            {
                var thisPort = iStorage.PropertiesWizardGetInputThisPort(instance);
                iStorage.SetNewDataConnection(thisPort, sourcePort);
            }
            iCS_UserCommands.CloseTransaction(iStorage, "Create Object Instance");
        }
        // ----------------------------------------------------------------------
        void AddEnableAndTriggerMenuItem(ref iCS_MenuContext[] menu, iCS_EditorObject node)
        {
            if (node.IsIconizedInLayout)
            {
                return;
            }
            int idx = GrowMenuBy(ref menu, 3);

            menu[idx] = new iCS_MenuContext(EnablePortStr);
            var iStorage = node.IStorage;

            if (iStorage.HasTriggerPort(node))
            {
                menu[idx + 1] = new iCS_MenuContext("#" + TriggerPortStr);
            }
            else
            {
                menu[idx + 1] = new iCS_MenuContext(TriggerPortStr);
            }
            menu[idx + 2] = new iCS_MenuContext(SeparatorStr);
        }
        // ----------------------------------------------------------------------
        void CanvasMenu(iCS_EditorObject selectedObject, iCS_IStorage iStorage)
        {
            // Don't show any menu if behaviour not visible.
            if (selectedObject.IsIconizedInLayout || selectedObject.IsFoldedInLayout)
            {
                return;
            }

            iCS_MenuContext[] menu = new iCS_MenuContext[3];
            menu[0] = new iCS_MenuContext(VariableCreationStr);
            menu[1] = new iCS_MenuContext(FunctionCreationStr);
            menu[2] = new iCS_MenuContext(NestedTypeCreationStr);
            // Add Unity message handlers
            var baseType = CodeGenerationUtility.GetBaseType(iStorage);

            if (iCS_Types.IsA <MonoBehaviour>(baseType))
            {
                var libraryType   = LibraryController.LibraryDatabase.GetLibraryType(typeof(MonoBehaviour));
                var eventHandlers = libraryType.GetMembers <LibraryEventHandler>();
                int len           = P.length(eventHandlers);
                int idx           = GrowMenuBy(ref menu, len);
                for (int i = 0; i < len; ++i)
                {
                    var    eventHandler  = eventHandlers[i];
                    string nodeName      = eventHandler.nodeName;
                    string displayString = eventHandler.displayString;
                    if (iCS_AllowedChildren.CanAddChildNode(nodeName, VSObjectType.InstanceMessage, selectedObject, iStorage))
                    {
                        menu[idx + i] = new iCS_MenuContext(String.Concat("+ " + AddUnityEventStr, displayString), eventHandler);
                    }
                    else
                    {
                        menu[idx + i] = new iCS_MenuContext(String.Concat("#+ " + AddUnityEventStr, displayString), eventHandler);
                    }
                }
            }
            ShowMenu(menu, selectedObject, iStorage);
        }
 // ----------------------------------------------------------------------
 void InstanceMenu(iCS_EditorObject selectedObject, iCS_IStorage storage)
 {
     iCS_MenuContext[] menu = new iCS_MenuContext[0];
     if (!selectedObject.IsIconizedInLayout)
     {
         // Base menu items
         menu    = new iCS_MenuContext[3];
         menu[0] = new iCS_MenuContext(EnablePortStr);
         if (storage.HasTriggerPort(selectedObject))
         {
             menu[1] = new iCS_MenuContext("#" + TriggerPortStr);
         }
         else
         {
             menu[1] = new iCS_MenuContext(TriggerPortStr);
         }
         menu[2] = new iCS_MenuContext(SeparatorStr);
     }
     AddWrapInPackageIfAppropriate(ref menu, selectedObject);
     AddShowInHierarchyMenuItem(ref menu);
     AddDeleteMenuItem(ref menu);
     ShowMenu(menu, selectedObject, storage);
 }
        // ----------------------------------------------------------------------
        void StateMenu(iCS_EditorObject selectedObject, iCS_IStorage storage)
        {
            iCS_MenuContext[] menu = StartWithFocusMenu(selectedObject);
            if (!selectedObject.IsIconizedInLayout && !selectedObject.IsFoldedInLayout)
            {
                int len = iCS_AllowedChildren.StateChildNames.Length;
                int idx = GrowMenuBy(ref menu, len + 3);
                menu[idx]     = new iCS_MenuContext(StateStr);
                menu[idx + 1] = new iCS_MenuContext(SeparatorStr);
                for (int i = 0; i < len; ++i)
                {
                    string name = iCS_AllowedChildren.StateChildNames[i];
                    if (iCS_AllowedChildren.CanAddChildNode(name, VSObjectType.Package, selectedObject, storage))
                    {
                        menu[idx + i + 2] = new iCS_MenuContext(String.Concat("+ ", name));
                    }
                    else
                    {
                        menu[idx + i + 2] = new iCS_MenuContext(String.Concat("#+ ", name));
                    }
                }
                menu[idx + len + 2] = new iCS_MenuContext(SeparatorStr);
            }
            int cursor = GrowMenuBy(ref menu, 1);

            if (selectedObject.IsEntryState)
            {
                menu[cursor] = new iCS_MenuContext(String.Concat("#", SetAsEntryStr));
            }
            else
            {
                menu[cursor] = new iCS_MenuContext(SetAsEntryStr);
            }
            AddShowInHierarchyMenuItem(ref menu);
            AddDeleteMenuItem(ref menu);
            ShowMenu(menu, selectedObject, storage);
        }
        // ======================================================================
        // Menu processing
        // ----------------------------------------------------------------------
        void ProcessMenu(object obj)
        {
            iCS_MenuContext  context      = obj as iCS_MenuContext;
            iCS_EditorObject targetObject = context.SelectedObject;
            Vector2          globalPos    = context.GraphPosition;
            iCS_IStorage     iStorage     = context.Storage;

            // Process all other types of requests.
            switch (context.HiddenCommand)
            {
            case SetAsDisplayRootStr:       iCS_UserCommands.SetAsDisplayRoot(targetObject); break;

            case ClearNavigationHistoryStr: iCS_UserCommands.ResetDisplayRoot(iStorage); break;

            case PackageStr:                iCS_UserCommands.CreatePackage(targetObject, globalPos, null); break;

            case InlineCodeStr:             iCS_UserCommands.CreateInlineCode(targetObject, globalPos, "InlineCode"); break;

            case StateChartStr:             iCS_UserCommands.CreateStateChart(targetObject, globalPos, null); break;

            case StateStr:                  iCS_UserCommands.CreateState(targetObject, globalPos, null);  break;

            case SetAsEntryStr:             iCS_UserCommands.SetAsStateEntry(targetObject); break;

            case OnEntryStr:                iCS_UserCommands.CreateOnEntryPackage(targetObject, globalPos); break;

            case OnUpdateStr:               iCS_UserCommands.CreateOnUpdatePackage(targetObject, globalPos); break;

            case OnExitStr:                 iCS_UserCommands.CreateOnExitPackage(targetObject, globalPos); break;

            case ObjectInstanceStr:         CreateObjectInstance(context); break;

            case ShowHierarchyStr:          iCS_UserCommands.ShowInHierarchy(targetObject); break;

            case DeleteStr:                 iCS_UserCommands.DeleteObject(targetObject); break;

            case EnablePortStr:             iCS_UserCommands.CreateEnablePort(targetObject); break;

            case TriggerPortStr:            iCS_UserCommands.CreateTriggerPort(targetObject); break;

            case WrapInPackageStr:          iCS_UserCommands.WrapInPackage(targetObject); break;

            case MultiSelectionWrapInPackageStr: iCS_UserCommands.WrapMultiSelectionInPackage(iStorage); break;

            case MultiSelectionDeleteStr:        iCS_UserCommands.DeleteMultiSelectedObjects(iStorage); break;

            case UnwrapPackageStr:               iCS_UserCommands.DeleteKeepChildren(targetObject); break;

            case FunctionCreationStr:            iCS_UserCommands.CreateFunctionDefinition(targetObject, globalPos); break;

            default: {
                if (targetObject == null)
                {
                    break;
                }
                var libraryObject = context.myLibraryObject;
                if (libraryObject == null)
                {
                    Debug.LogWarning(iCS_Config.ProductName + ": Can find reflection descriptor to create node !!!");
                    break;
                }
                if (libraryObject is LibraryEventHandler)
                {
                    iCS_UserCommands.CreateEventHandler(targetObject, globalPos, libraryObject as LibraryEventHandler);
                    break;
                }
                if (targetObject.IsPort)
                {
                    CreateAttachedMethod(targetObject, iStorage, globalPos, libraryObject);
                }
                else
                {
                    iCS_UserCommands.CreateFunctionCallNode(targetObject, globalPos, libraryObject);
                }
                break;
            }
            }
        }
        // ----------------------------------------------------------------------
        void AddSeparator(ref iCS_MenuContext[] menu)
        {
            int idx = GrowMenuBy(ref menu, 1);

            menu[idx] = new iCS_MenuContext(SeparatorStr);
        }
        // ----------------------------------------------------------------------
        void ReleaseAfterDragPortMenu(iCS_EditorObject port, iCS_IStorage storage, bool reverseInOut)
        {
            // Different behaviour for "object instance" and standard packages.
            var newNodeParent  = storage.GetNodeAt(GraphPosition);
            var portParentNode = port.ParentNode;

            if (newNodeParent == null)
            {
                return;
            }
            iCS_MenuContext[] menu = new iCS_MenuContext[0];
            var portType           = iCS_Types.RemoveRefOrPointer(port.RuntimeType);

            if (!newNodeParent.IsInstanceNode && portType != typeof(float) && portType != typeof(int) && portType != typeof(bool) &&
                (port.IsOutputPort && newNodeParent != portParentNode && !portParentNode.IsParentOf(newNodeParent)) ||
                (port.IsInputPort && (newNodeParent == portParentNode || portParentNode.IsParentOf(newNodeParent))))
            {
                // Add shortcut to instance node creation.
                menu            = new iCS_MenuContext[2];
                menu[0]         = new iCS_MenuContext(ObjectInstanceStr);
                menu[0].Command = "+ Create Property Accessor";
                menu[1]         = new iCS_MenuContext(SeparatorStr);
            }
            // TODO: Rebuild release after drag menu
//            // Get compatible functions.
//            if(port.IsDataOrControlPort) {
//                List<iCS_FunctionPrototype> functionMenu= null;
//              Type inputType= null;
//              Type outputType= null;
//              if(port.IsInputPort) {
//                    outputType= port.RuntimeType;
//                } else {
//                    inputType= port.RuntimeType;
//                }
//              if(reverseInOut) {
//                  var tmp= inputType;
//                  inputType= outputType;
//                  outputType= tmp;
//              }
//              if(newNodeParent.IsInstanceNode) {
//                  functionMenu= iCS_LibraryDatabase.BuildMenuForMembersOfType(newNodeParent.RuntimeType, inputType, outputType);
//              }
//              else {
//                  functionMenu= iCS_LibraryDatabase.BuildMenu(inputType, outputType);
//              }
//                if(functionMenu.Count != 0) {
//                    int len= menu.Length;
//                    iCS_MenuContext[] tmp= null;
//                    if(len == 0) {
//                        tmp= new iCS_MenuContext[functionMenu.Count];
//                    } else {
//                        tmp= new iCS_MenuContext[len+1+functionMenu.Count];
//                        menu.CopyTo(tmp, 0);
//                        tmp[len]= new iCS_MenuContext(SeparatorStr);
//                        ++len;
//                    }
//                    menu= tmp;
//                    for(int i= 0; i < functionMenu.Count; ++i) {
//                        menu[len+i]= new iCS_MenuContext(functionMenu[i].ToMenu(), functionMenu[i]);
//                    }
//                }
//            }
            ShowMenu(menu, port, storage);
        }