public void ClearSelectionWorks()
        {
            var node1 = new NodeModel();
            var node2 = new NodeModel();

            var viewGuid1 = SerializableGUID.Generate();
            var state     = new GraphToolState(viewGuid1, null);

            using (var selectionUpdater = state.SelectionState.UpdateScope)
            {
                selectionUpdater.ClearSelection(state.WindowState.GraphModel);
                selectionUpdater.SelectElements(new[] { node1, node2 }, true);
            }

            Assert.IsTrue(state.SelectionState.IsSelected(node1));
            Assert.IsTrue(state.SelectionState.IsSelected(node2));

            using (var selectionUpdater = state.SelectionState.UpdateScope)
            {
                selectionUpdater.ClearSelection(state.WindowState.GraphModel);
            }

            Assert.IsFalse(state.SelectionState.IsSelected(node1));
            Assert.IsFalse(state.SelectionState.IsSelected(node2));
        }
 /// <summary>
 /// Initializes a new GraphNodeCreationData.
 /// </summary>
 /// <param name="graphModel">The interface to the graph where we want the node to be created in.</param>
 /// <param name="position">The position at which the node should be created.</param>
 /// <param name="spawnFlags">The flags specifying how the node is to be spawned.</param>
 /// <param name="guid">The SerializableGUID to assign to the newly created item.</param>
 public GraphNodeCreationData(IGraphModel graphModel, Vector2 position, SpawnFlags spawnFlags = SpawnFlags.Default, SerializableGUID guid = default)
 {
     GraphModel = graphModel;
     Position   = position;
     SpawnFlags = spawnFlags;
     Guid       = guid;
 }
Esempio n. 3
0
        static void SetupLogStickyCallback()
        {
            ConsoleWindowBridge.SetEntryDoubleClickedDelegate((file, entryInstanceId) =>
            {
                // FIXME: will not work with files that contains multiple GraphAssetModel.

                var pathAndGuid = file.Split('@');

                bool assetOpened = false;
                var asset        = AssetDatabase.LoadAssetAtPath <GraphAssetModel>(pathAndGuid[0]);
                if (asset != null)
                {
                    assetOpened = AssetDatabase.OpenAsset(asset);
                }

                if (assetOpened)
                {
                    var guid   = new SerializableGUID(pathAndGuid[1]);
                    var window = focusedWindow as GraphViewEditorWindow;
                    if (window != null && window.GraphView.GraphModel.TryGetModelFromGuid(guid, out var nodeModel))
                    {
                        var graphElement = nodeModel.GetUI <GraphElement>(window.GraphView);
                        if (graphElement != null)
                        {
                            window.GraphView.DispatchFrameAndSelectElementsCommand(true, graphElement);
                        }
                    }
                }
            });
        }
Esempio n. 4
0
        protected override INodeModel InstantiateNode(Type nodeTypeToCreate, string nodeName, Vector2 position,
                                                      SerializableGUID guid = default, Action <INodeModel> initializationCallback = null)
        {
            if (nodeTypeToCreate == null)
            {
                throw new ArgumentNullException(nameof(nodeTypeToCreate));
            }

            BasicModel.NodeModel nodeModel;
            if (typeof(IConstant).IsAssignableFrom(nodeTypeToCreate))
            {
                nodeModel = new ConstantNodeModel {
                    Value = (IConstant)Activator.CreateInstance(nodeTypeToCreate)
                }
            }
            ;
            else if (typeof(BasicModel.NodeModel).IsAssignableFrom(nodeTypeToCreate))
            {
                nodeModel = (BasicModel.NodeModel)Activator.CreateInstance(nodeTypeToCreate);
            }
            else
            {
                throw new ArgumentOutOfRangeException(nameof(nodeTypeToCreate));
            }

            nodeModel.Position = position;
            nodeModel.Guid     = guid.Valid ? guid : SerializableGUID.Generate();
            nodeModel.Title    = nodeName;
            (nodeModel as ITestNodeModel).SetGraphModel(this);
            initializationCallback?.Invoke(nodeModel);
            nodeModel.OnCreateNode();

            return(nodeModel);
        }
Esempio n. 5
0
 /// <summary>
 /// Initializes a new CreateNodeFromSearcherCommand.
 /// </summary>
 /// <param name="position">The position where to create the node.</param>
 /// <param name="selectedItem">The searcher item representing the node to create.</param>
 /// <param name="guid">The SerializableGUID to assign to the newly created item. If none is provided, a new
 /// SerializableGUID will be generated for it.</param>
 public CreateNodeFromSearcherCommand(Vector2 position,
                                      GraphNodeModelSearcherItem selectedItem,
                                      SerializableGUID guid = default) : this()
 {
     Position     = position;
     SelectedItem = selectedItem;
     Guid         = guid.Valid ? guid : SerializableGUID.Generate();
 }
Esempio n. 6
0
 /// <summary>
 /// Initializes a new CreateNodeFromSearcherCommand.
 /// </summary>
 /// <param name="edgeModel">The edge model on which to insert the newly created node.</param>
 /// <param name="position">The position where to create the node.</param>
 /// <param name="selectedItem">The searcher item representing the node to create.</param>
 /// <param name="guid">The SerializableGUID to assign to the newly created item. If none is provided, a new
 /// SerializableGUID will be generated for it.</param>
 public CreateNodeOnEdgeCommand(IEdgeModel edgeModel, Vector2 position,
                                GraphNodeModelSearcherItem selectedItem, SerializableGUID guid = default) : this()
 {
     EdgeModel    = edgeModel;
     Position     = position;
     SelectedItem = selectedItem;
     Guid         = guid.Valid ? guid : SerializableGUID.Generate();
 }
Esempio n. 7
0
 /// <summary>
 /// Creates a new variable declaration in the graph.
 /// </summary>
 /// <param name="self">The graph to add a variable declaration to.</param>
 /// <param name="variableDataType">The type of data the new variable declaration to create represents.</param>
 /// <param name="variableName">The name of the new variable declaration to create.</param>
 /// <param name="modifierFlags">The modifier flags of the new variable declaration to create.</param>
 /// <param name="isExposed">Whether the variable is exposed externally or not.</param>
 /// <param name="initializationModel">The initialization model of the new variable declaration to create. Can be <code>null</code>.</param>
 /// <param name="guid">The SerializableGUID to assign to the newly created item.</param>
 /// <param name="initializationCallback">An initialization method to be called right after the variable declaration is created.</param>
 /// <param name="spawnFlags">The flags specifying how the variable declaration is to be spawned.</param>
 /// <typeparam name="TDeclType">The type of variable declaration to create.</typeparam>
 /// <returns>The newly created variable declaration.</returns>
 public static TDeclType CreateGraphVariableDeclaration <TDeclType>(this IGraphModel self, TypeHandle variableDataType,
                                                                    string variableName, ModifierFlags modifierFlags, bool isExposed, IConstant initializationModel = null,
                                                                    SerializableGUID guid = default, Action <TDeclType, IConstant> initializationCallback = null,
                                                                    SpawnFlags spawnFlags = SpawnFlags.Default)
     where TDeclType : class, IVariableDeclarationModel
 {
     return((TDeclType)self.CreateGraphVariableDeclaration(typeof(TDeclType), variableDataType, variableName,
                                                           modifierFlags, isExposed, initializationModel, guid, (d, c) => initializationCallback?.Invoke((TDeclType)d, c), spawnFlags));
 }
Esempio n. 8
0
 /// <summary>
 /// Initializes a new CreateGraphVariableDeclarationCommand.
 /// </summary>
 /// <remarks>This constructor will create the graph's default variable declaration.</remarks>
 /// <param name="name">The name of the variable to create.</param>
 /// <param name="isExposed">Whether or not the variable is exposed.</param>
 /// <param name="typeHandle">The type of data the new variable declaration to create represents.</param>
 /// <param name="modifierFlags">The modifiers to apply to the newly created variable.</param>
 /// <param name="guid">The SerializableGUID to assign to the newly created item. If none is provided, a new
 /// SerializableGUID will be generated for it.</param>
 public CreateGraphVariableDeclarationCommand(string name, bool isExposed, TypeHandle typeHandle,
                                              ModifierFlags modifierFlags = ModifierFlags.None, SerializableGUID guid = default) : this()
 {
     VariableName  = name;
     IsExposed     = isExposed;
     TypeHandle    = typeHandle;
     Guid          = guid.Valid ? guid : SerializableGUID.Generate();
     ModifierFlags = modifierFlags;
 }
 void FrameAndSelectElement(SerializableGUID errorModelGuid)
 {
     if (m_GraphView.GraphModel.TryGetModelFromGuid(errorModelGuid, out var errorModel))
     {
         var ui = errorModel.GetUI <GraphElement>(m_GraphView);
         if (ui != null)
         {
             m_GraphView.DispatchFrameAndSelectElementsCommand(true, ui);
         }
     }
 }
Esempio n. 10
0
        /// <summary>
        /// Creates a new node in a graph.
        /// </summary>
        /// <param name="self">The graph to add a node to.</param>
        /// <param name="nodeName">The name of the node to create.</param>
        /// <param name="position">The position of the node to create.</param>
        /// <param name="guid">The SerializableGUID to assign to the newly created item.</param>
        /// <param name="initializationCallback">An initialization method to be called right after the node is created.</param>
        /// <param name="spawnFlags">The flags specifying how the node is to be spawned.</param>
        /// <typeparam name="TNodeType">The type of the new node to create.</typeparam>
        /// <returns>The newly created node.</returns>
        public static TNodeType CreateNode <TNodeType>(this IGraphModel self, string nodeName = "", Vector2 position = default,
                                                       SerializableGUID guid = default, Action <TNodeType> initializationCallback = null, SpawnFlags spawnFlags = SpawnFlags.Default)
            where TNodeType : class, INodeModel
        {
            Action <INodeModel> setupWrapper = null;

            if (initializationCallback != null)
            {
                setupWrapper = n => initializationCallback.Invoke(n as TNodeType);
            }

            return((TNodeType)self.CreateNode(typeof(TNodeType), nodeName, position, guid, setupWrapper, spawnFlags));
        }
        public void EmptyChangeSetsDoNotDirtyAsset()
        {
            var viewGuid1         = SerializableGUID.Generate();
            var state             = new GraphToolState(viewGuid1, null);
            var initialDirtyCount = EditorUtility.GetDirtyCount(m_Asset1 as Object);

            using (var graphUpdater = state.GraphViewState.UpdateScope)
            {
                graphUpdater.MarkNew(Enumerable.Empty <IGraphElementModel>());
                graphUpdater.MarkChanged(Enumerable.Empty <IGraphElementModel>());
                graphUpdater.MarkDeleted(Enumerable.Empty <IGraphElementModel>());
            }

            Assert.AreEqual(initialDirtyCount, EditorUtility.GetDirtyCount(m_Asset1 as Object));
        }
        protected virtual void OnEnable()
        {
            // When we open a window (including when we start the Editor), a new GUID is assigned.
            // When a window is opened and there is a domain reload, the GUID stays the same.
            if (m_GUID == default)
            {
                m_GUID = SerializableGUID.Generate();
            }

            var root = rootVisualElement;

            this.SetAntiAliasing(4);

            m_Toolbar = new UIElements.Toolbar();

            // Register panel choice refresh on the toolbar so the event
            // is received before the ToolbarPopup clickable handle it.
            m_Toolbar.RegisterCallback <MouseDownEvent>(e =>
            {
                if (e.target == m_SelectorMenu)
                {
                    RefreshPanelChoices();
                }
            }, TrickleDown.TrickleDown);
            m_GraphViewChoices = new List <GraphViewChoice>();
            m_SelectorMenu     = new ToolbarMenu {
                name = "panelSelectPopup", text = "Select a panel"
            };

            var menu = m_SelectorMenu.menu;

            menu.AppendAction("None", OnSelectGraphView,
                              a => m_SelectedGraphView == null ?
                              DropdownMenuAction.Status.Checked : DropdownMenuAction.Status.Normal);

            m_Toolbar.Add(m_SelectorMenu);
            m_Toolbar.style.flexGrow = 1;
            m_Toolbar.style.overflow = Overflow.Hidden;
            m_ToolbarContainer       = new VisualElement();
            m_ToolbarContainer.style.flexDirection = FlexDirection.Row;
            m_ToolbarContainer.Add(m_Toolbar);

            root.Add(m_ToolbarContainer);

            m_FirstUpdate = true;

            titleContent.text = ToolName;
        }
        public void AllStateComponentsReturnsAllStateComponents()
        {
            var viewGuid1       = SerializableGUID.Generate();
            var state           = new GraphToolState(viewGuid1, null);
            var sc              = new HashSet <IStateComponent>(state.AllStateComponents);
            var foundComponents = new HashSet <IStateComponent>();

            foreach (var fieldInfo in typeof(GraphToolState)
                     .GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
                     .Where(fi => typeof(IStateComponent).IsAssignableFrom(fi.FieldType))
                     )
            {
                foundComponents.Add(fieldInfo.GetValue(state) as IStateComponent);
                Assert.IsTrue(sc.Contains(fieldInfo.GetValue(state) as IStateComponent), fieldInfo.Name + " is not included in AllStateComponents");
            }

            Assert.AreEqual(sc, foundComponents);
        }
        public void SettingAStateComponentAndGettingItWorks()
        {
            var persistedState = new PersistedState();

            persistedState.SetAssetKey("42424242");
            var viewGuid1 = SerializableGUID.Generate();

            // View State Components
            {
                var firstState        = persistedState.GetOrCreateViewStateComponent <WindowStateComponent>(viewGuid1, "");
                var newStateComponent = new WindowStateComponent();
                persistedState.SetViewStateComponent(viewGuid1, newStateComponent);
                var secondState = persistedState.GetOrCreateViewStateComponent <WindowStateComponent>(viewGuid1, "");
                Assert.IsNotNull(firstState);
                Assert.IsNotNull(secondState);
                Assert.AreSame(newStateComponent, secondState);
            }

            // Asset State Components
            {
                var firstState        = persistedState.GetOrCreateAssetStateComponent <BlackboardViewStateComponent>("");
                var newStateComponent = new BlackboardViewStateComponent();
                persistedState.SetAssetStateComponent(newStateComponent);
                var secondState = persistedState.GetOrCreateAssetStateComponent <BlackboardViewStateComponent>("");
                Assert.IsNotNull(firstState);
                Assert.IsNotNull(secondState);
                Assert.AreSame(newStateComponent, secondState);
            }

            // Asset View State Components
            {
                var firstState        = persistedState.GetOrCreateAssetViewStateComponent <SelectionStateComponent>(viewGuid1, "");
                var newStateComponent = new SelectionStateComponent();
                persistedState.SetAssetViewStateComponent(viewGuid1, newStateComponent);
                var secondState = persistedState.GetOrCreateAssetViewStateComponent <SelectionStateComponent>(viewGuid1, "");
                Assert.IsNotNull(firstState);
                Assert.IsNotNull(secondState);
                Assert.AreSame(newStateComponent, secondState);
            }

            PersistedState.RemoveViewState(viewGuid1);
        }
        public void SelectionStateIsTiedToAssetAndView()
        {
            var node = new NodeModel();

            var viewGuid1 = SerializableGUID.Generate();
            var state     = new GraphToolState(viewGuid1, null);

            state.LoadGraphAsset(m_Asset1, null);
            Assert.IsNotNull(state.SelectionState);
            using (var selectionUpdater = state.SelectionState.UpdateScope)
            {
                selectionUpdater.SelectElements(new[] { node }, true);
            }
            Assert.IsTrue(state.SelectionState.IsSelected(node));

            // Load another asset in the same view: node is not selected anymore.
            var state2 = new GraphToolState(viewGuid1, null);

            state2.LoadGraphAsset(m_Asset2, null);
            var selectionState2 = state2.SelectionState;

            Assert.IsNotNull(selectionState2);
            Assert.IsFalse(selectionState2.IsSelected(node));

            // Load the same asset in the another view: node is not selected anymore.
            var viewGuid2 = SerializableGUID.Generate();

            state2 = new GraphToolState(viewGuid2, null);
            state2.LoadGraphAsset(m_Asset1, null);
            selectionState2 = state2.SelectionState;
            Assert.IsNotNull(selectionState2);
            Assert.IsFalse(selectionState2.IsSelected(node));

            // Reload the same asset in the original view: node is still selected.
            state2 = new GraphToolState(viewGuid1, null);
            state2.LoadGraphAsset(m_Asset1, null);
            selectionState2 = state2.SelectionState;
            Assert.IsNotNull(selectionState2);
            Assert.IsTrue(selectionState2.IsSelected(node));
        }
        public void Remove(SerializableGUID a, SerializableGUID b)
        {
            SerializableGUID parent;
            SerializableGUID child;

            if (m_DependenciesByNode.TryGetValue(a, out var link) &&
                link.TryGetValue(b, out var dependency))
            {
                parent = a;
                child  = b;
            }
            else if (m_DependenciesByNode.TryGetValue(b, out link) &&
                     link.TryGetValue(a, out dependency))
            {
                parent = b;
                child  = a;
            }
            else
            {
                return;
            }

            if (dependency is LinkedNodesDependency linked)
            {
                linked.Count--;
                if (linked.Count <= 0)
                {
                    link.Remove(child);
                }
            }
            else
            {
                link.Remove(child);
            }
            if (link.Count == 0)
            {
                m_DependenciesByNode.Remove(parent);
            }
        }
        public void MarkChangedHasNoEffectIfModelIsNew()
        {
            var viewGuid1  = SerializableGUID.Generate();
            var state      = new GraphToolState(viewGuid1, null);
            var dummyModel = new TestNodeModel();

            using (var graphUpdater = state.GraphViewState.UpdateScope)
            {
                graphUpdater.MarkNew(dummyModel);
            }

            var changes = state.GraphViewState.GetAggregatedChangeset(0);

            Assert.IsTrue(changes.NewModels.Contains(dummyModel));

            using (var graphUpdater = state.GraphViewState.UpdateScope)
            {
                graphUpdater.MarkChanged(dummyModel);
            }

            changes = state.GraphViewState.GetAggregatedChangeset(0);
            Assert.IsFalse(changes.ChangedModels.Contains(dummyModel));
        }
        public void MarkDeletedRemovesModelFromTheChangedList()
        {
            var viewGuid1  = SerializableGUID.Generate();
            var state      = new GraphToolState(viewGuid1, null);
            var dummyModel = new TestNodeModel();

            using (var graphUpdater = state.GraphViewState.UpdateScope)
            {
                graphUpdater.MarkChanged(dummyModel);
            }

            var changes = state.GraphViewState.GetAggregatedChangeset(0);

            Assert.IsTrue(changes.ChangedModels.Contains(dummyModel));

            using (var graphUpdater = state.GraphViewState.UpdateScope)
            {
                graphUpdater.MarkDeleted(dummyModel);
            }

            changes = state.GraphViewState.GetAggregatedChangeset(0);
            Assert.IsFalse(changes.ChangedModels.Contains(dummyModel));
            Assert.IsTrue(changes.DeletedModels.Contains(dummyModel));
        }
Esempio n. 19
0
        protected override IEdgeModel InstantiateEdge(IPortModel toPort, IPortModel fromPort, SerializableGUID guid = default)
        {
            var edgeModel = base.InstantiateEdge(toPort, fromPort, guid);

            if (edgeModel is EdgeModel testEdgeModel)
            {
                testEdgeModel.SetGraphModel(this);
            }

            return(edgeModel);
        }
Esempio n. 20
0
 public override IVariableNodeModel CreateVariableNode(IVariableDeclarationModel declarationModel,
                                                       Vector2 position, SerializableGUID guid = default, SpawnFlags spawnFlags = SpawnFlags.Default)
 {
     return(this.CreateNode <VariableNodeModel>(declarationModel.DisplayTitle, position, guid, v => v.DeclarationModel = declarationModel, spawnFlags));
 }
Esempio n. 21
0
 /// <summary>
 /// Converts a <see cref="SerializableGUID"/> to a <see cref="GUID"/>.
 /// </summary>
 /// <param name="guid">The SerializableGUID to convert.</param>
 /// <returns>The resulting GUID.</returns>
 public static unsafe GUID ToGUID(this SerializableGUID guid)
 {
     return(*(GUID *)&guid);
 }
 public GraphToolState(SerializableGUID graphViewEditorWindowGUID, IGraphModel graphModel)
     : base(graphViewEditorWindowGUID, CreatePreferences())
 {
     m_GraphModel = graphModel;
 }
 public TestGraphToolState(SerializableGUID graphViewEditorWindowGUID, Preferences preferences)
     : base(graphViewEditorWindowGUID, preferences)
 {
 }
 static string UnexpectedValueMessage(string fieldName, SerializableGUID guid)
 {
     return(UnexpectedValueMessage(fieldName, NiceGuid(guid)));
 }
 static string NiceGuid(SerializableGUID guid)
 {
     var(a, b) = guid.ToParts();
     return($"GUID {{m_Value0: {a} m_Value1: {b}}}");
 }
Esempio n. 26
0
        protected override IVariableDeclarationModel InstantiateVariableDeclaration(Type variableTypeToCreate,
                                                                                    TypeHandle variableDataType, string variableName, ModifierFlags modifierFlags, bool isExposed,
                                                                                    IConstant initializationModel, SerializableGUID guid, Action <IVariableDeclarationModel, IConstant> initializationCallback = null)
        {
            var vdm = base.InstantiateVariableDeclaration(variableTypeToCreate, variableDataType, variableName, modifierFlags, isExposed, initializationModel, guid, initializationCallback);

            if (vdm is VariableDeclarationModel testVdm)
            {
                testVdm.SetGraphModel(this);
            }

            return(vdm);
        }
Esempio n. 27
0
 /// <summary>
 /// Initializes a new CreateGraphVariableDeclarationCommand.
 /// </summary>
 /// <param name="name">The name of the variable to create.</param>
 /// <param name="isExposed">Whether or not the variable is exposed.</param>
 /// <param name="typeHandle">The type of data the new variable declaration to create represents.</param>
 /// <param name="variableType">The type of variable declaration to create.</param>
 /// <param name="modifierFlags">The modifiers to apply to the newly created variable.</param>
 /// <param name="guid">The SerializableGUID to assign to the newly created item. If none is provided, a new
 /// SerializableGUID will be generated for it.</param>
 public CreateGraphVariableDeclarationCommand(string name, bool isExposed, TypeHandle typeHandle, Type variableType,
                                              ModifierFlags modifierFlags = ModifierFlags.None, SerializableGUID guid = default)
     : this(name, isExposed, typeHandle, modifierFlags, guid)
 {
     VariableType = variableType;
 }
Esempio n. 28
0
        protected virtual void OnEnable()
        {
            // When we open a window (including when we start the Editor), a new GUID is assigned.
            // When a window is opened and there is a domain reload, the GUID stays the same.
            if (m_GUID == default)
            {
                m_GUID = SerializableGUID.Generate();
            }

            var initialState = CreateInitialState();

            CommandDispatcher = new CommandDispatcher(initialState);

            PluginRepository = new PluginRepository(this);

            rootVisualElement.Clear();
            rootVisualElement.pickingMode = PickingMode.Ignore;

            m_GraphContainer = new VisualElement {
                name = "graphContainer"
            };
            m_GraphView    = CreateGraphView();
            m_MainToolbar  = CreateMainToolbar();
            m_ErrorToolbar = CreateErrorToolbar();
            m_BlankPage    = CreateBlankPage();
            m_BlankPage?.CreateUI();

            if (m_MainToolbar != null)
            {
                rootVisualElement.Add(m_MainToolbar);
            }
            // AddTracingTimeline();
            rootVisualElement.Add(m_GraphContainer);
            if (m_ErrorToolbar != null)
            {
                m_GraphView.Add(m_ErrorToolbar);
            }

            m_GraphContainer.Add(m_GraphView);

            rootVisualElement.name = "gtfRoot";
            rootVisualElement.AddStylesheet("GraphViewWindow.uss");

            // PF FIXME: Use EditorApplication.playModeStateChanged / AssemblyReloadEvents ? Make sure it works on all domain reloads.

            // After a domain reload, all loaded objects will get reloaded and their OnEnable() called again
            // It looks like all loaded objects are put in a deserialization/OnEnable() queue
            // the previous graph's nodes/edges/... might be queued AFTER this window's OnEnable
            // so relying on objects to be loaded/initialized is not safe
            // hence, we need to defer the loading command
            rootVisualElement.schedule.Execute(() =>
            {
                var lastGraphFilePath = CommandDispatcher.State.WindowState.LastOpenedGraph.GetGraphAssetModelPath();
                var lastGraphId       = CommandDispatcher.State.WindowState.LastOpenedGraph.AssetLocalId;
                if (!string.IsNullOrEmpty(lastGraphFilePath))
                {
                    try
                    {
                        CommandDispatcher.Dispatch(new LoadGraphAssetCommand(
                                                       lastGraphFilePath,
                                                       lastGraphId,
                                                       PluginRepository,
                                                       CommandDispatcher.State.WindowState.LastOpenedGraph.BoundObject,
                                                       LoadGraphAssetCommand.LoadStrategies.KeepHistory));
                    }
                    catch (Exception e)
                    {
                        Debug.LogError(e);
                    }
                }
            }).ExecuteLater(0);

            m_GraphProcessingPendingLabel = new Label("Graph Processing Pending")
            {
                name = "graph-processing-pending-label"
            };

            if (WithSidePanel)
            {
                m_SidePanel = CreateModelInspectorView();
            }

            if (m_SidePanel != null)
            {
                m_GraphContainer.Add(m_SidePanel);
            }

            rootVisualElement.RegisterCallback <AttachToPanelEvent>(OnEnterPanel);
            rootVisualElement.RegisterCallback <DetachFromPanelEvent>(OnLeavePanel);
            // that will be true when the window is restored during the editor startup, so OnEnterPanel won't be called later
            if (rootVisualElement.panel != null)
            {
                OnEnterPanel(null);
            }

            titleContent = new GUIContent("Graph Tool");

            m_LockTracker.lockStateChanged.AddListener(OnLockStateChanged);

            m_AutomaticGraphProcessor = new AutomaticGraphProcessor(PluginRepository);
            CommandDispatcher.RegisterObserver(m_AutomaticGraphProcessor);
            rootVisualElement.RegisterCallback <MouseMoveEvent>(ResetGraphProcessorTimer);

            m_GraphProcessingStatusObserver = new GraphProcessingStatusObserver(m_GraphProcessingPendingLabel, m_ErrorToolbar);
            CommandDispatcher.RegisterObserver(m_GraphProcessingStatusObserver);

            m_SidePanelObserver = new SidePanelObserver(this);
            CommandDispatcher.RegisterObserver(m_SidePanelObserver);
        }