/// <summary>
            /// Gets the enumerator for the collection.
            /// </summary>
            /// <returns>Enumerator for the collection.</returns>
            public IEnumerator <TSDrawing> GetEnumerator()
            {
                var snapshot = new List <TSDrawing>();

                try
                {
                    if (this.parent.IsActive)
                    {
                        SeparateThread.Execute(
                            LongOperation,
                            delegate
                        {
                            foreach (TSDrawing item in this.parent.connection.GetDrawings())
                            {
                                if (item != null)
                                {
                                    snapshot.Add(item);
                                }
                            }
                        });
                    }
                }
                catch (Exception ex)
                {
                    Debug.WriteLine(ex);

                    snapshot.Clear();
                }

                return(snapshot.GetEnumerator());
            }
        /// <summary>Commits the changes made to the objects.</summary>
        /// <param name="objects">Enumerable collection of modified objects.</param>
        public void CommitChanges(IEnumerable <object> objects)
        {
            if (this.IsEditorOpen)
            {
                try
                {
                    foreach (var item in objects)
                    {
                        var drawingObject = item as TSDrawingObject;

                        if (drawingObject != null)
                        {
                            drawingObject.Modify();
                        }
                    }

                    if (SeparateThread.Execute <bool>(delegate { return(this.connection.GetActiveDrawing().CommitChanges()); }))
                    {
                        if (this.ChangesCommitted != null)
                        {
                            this.ChangesCommitted(this, EventArgs.Empty);
                        }
                    }
                }
                catch (RemotingException e)
                {
                    Debug.WriteLine(e.ToString());
                    this.DiscardChanges(objects);
                }
            }
        }
        /// <summary>
        /// Removes the event handler registration.
        /// </summary>
        private void UnregisterEvents()
        {
            if (this.events != null && this.eventsRegistered)
            {
                SeparateThread.Execute(
                    delegate
                {
                    this.eventsRegistered = false;

                    this.events.UnRegister();

                    if (this.EditorOpenedEvent != null)
                    {
                        this.events.DrawingEditorOpened -= this.OnEditorOpened;
                    }

                    if (this.EditorClosedEvent != null)
                    {
                        this.events.DrawingEditorClosed -= this.OnEditorClosed;
                    }

                    if (this.DrawingLoadedEvent != null)
                    {
                        this.events.DrawingLoaded -= this.OnDrawingLoaded;
                    }

                    if (this.SelectionChangedEvent != null)
                    {
                        this.events.SelectionChange -= this.OnSelectionChanged;
                    }
                });
            }
        }
        /// <summary>
        /// Connects the drawing interface.
        /// </summary>
        /// <returns>A boolean value indicating whether the interface is connected.</returns>
        public bool Connect()
        {
            try
            {
                if (this.connection == null)
                {
                    this.connection = new TSDrawingConnection();

                    SeparateThread.Execute(
                        delegate
                    {
                        TSDrawingConnection.SetMessageExecutionStatus(
                            TSDrawingConnection.MessageExecutionModeEnum.BY_COMMIT);
                    });
                }

                if (this.events == null)
                {
                    this.events = new TSDrawingEvents();

                    this.RegisterEvents();
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex);

                this.Disconnect();
            }

            return(this.IsActive);
        }
        /// <summary>
        /// Saves the current drawing.
        /// </summary>
        /// <returns>A boolean value indicating whether the drawing was saved.</returns>
        public bool Save()
        {
            if (this.IsEditorOpen)
            {
                return(SeparateThread.Execute <bool>(this.connection.SaveActiveDrawing));
            }

            return(false);
        }
        /// <summary>Opens a drawing in the drawing editor.</summary>
        /// <param name="drawing">Drawing to open.</param>
        /// <returns>A boolean value indicating whether the drawing was opened.</returns>
        public bool Open(TSDrawing drawing)
        {
            if (this.IsActive)
            {
                return(SeparateThread.Execute <bool>(delegate { return this.connection.SetActiveDrawing(drawing, true); }));
            }

            return(false);
        }
        /// <summary>Selects object by identifier.</summary>
        /// <param name="identifier">Object identifier.</param>
        /// <returns>Selected object or null if no matching object was found.</returns>
        public object SelectObjectByIdentifier(Identifier identifier)
        {
            if (this.IsActive)
            {
                return(SeparateThread.Execute <ModelObject>(
                           delegate { return this.connection.SelectModelObject(identifier); }));
            }

            return(null);
        }
        /// <summary>Closes the drawing editor.</summary>
        /// <param name="saveBeforeClosing">Indicates whether the drawing is saved before closing.</param>
        /// <returns>A boolean value indicating whether the drawing editor was closed.</returns>
        public bool Close(bool saveBeforeClosing)
        {
            if (this.IsEditorOpen)
            {
                return
                    (SeparateThread.Execute <bool>(delegate { return this.connection.CloseActiveDrawing(saveBeforeClosing); }));
            }

            return(false);
        }
        /// <summary>
        /// Registers the event handlers.
        /// </summary>
        private void RegisterEvents()
        {
            if (this.events != null && !this.eventsRegistered)
            {
                SeparateThread.Execute(
                    delegate
                {
                    var registeredHandlers = 0;

                    if (this.ApplicationClosed_Event != null)
                    {
                        this.events.TeklaStructuresExit += this.OnApplicationClosed;
                        registeredHandlers++;
                    }

                    if (this.Numbering_Event != null)
                    {
                        this.events.Numbering += this.OnNumbering;
                        registeredHandlers++;
                    }

                    if (this.Loaded_Event != null)
                    {
                        this.events.ModelLoad += this.OnLoaded;
                        registeredHandlers++;
                    }

                    if (this.Saved_Event != null)
                    {
                        this.events.ModelSave += this.OnSaved;
                        registeredHandlers++;
                    }

                    if (this.SelectionChanged_Event != null)
                    {
                        this.events.SelectionChange += this.OnSelectionChanged;
                        registeredHandlers++;
                    }

                    if (this.Changed_Event != null)
                    {
                        this.events.ModelChanged += this.OnChanged;
                        registeredHandlers++;
                    }

                    if (registeredHandlers > 0)
                    {
                        this.events.Register();

                        this.eventsRegistered = true;
                    }
                });
            }
        }
        /// <summary>Commits the changes made to the objects.</summary>
        /// <remarks>If Object.Modify() is not implemented this method does nothing.</remarks>
        /// <param name="objects">Enumerable collection of modified objects.</param>
        public void CommitChanges(IEnumerable <object> objects)
        {
            if (this.IsActive)
            {
                try
                {
                    foreach (var item in objects)
                    {
                        try
                        {
                            var modelObject = item as ModelObject;

                            if (modelObject != null)
                            {
                                modelObject.Modify();
                            }

                            var modelView = item as TSView;

                            if (modelView != null)
                            {
                                modelView.Modify();
                            }
                        }
                        catch (NotImplementedException)
                        {
                            // no action (at the moment)
                            // TODO: Add overloaded CommitChanges(objects, failedObjects) method
                            // TODO: to get optionally to know any possibly failed objects
                        }
                    }

                    if (SeparateThread.Execute <bool>(this.connection.CommitChanges))
                    {
                        if (this.ChangesCommitted != null)
                        {
                            this.ChangesCommitted(this, EventArgs.Empty);
                        }
                    }
                }
                catch (RemotingException e)
                {
                    Debug.WriteLine(e.ToString());
                    this.DiscardChanges(objects);
                }
            }
        }
        /// <summary>
        /// Removes the event handler registration.
        /// </summary>
        private void UnregisterEvents()
        {
            if (this.events != null && this.eventsRegistered)
            {
                SeparateThread.Execute(
                    delegate
                {
                    this.eventsRegistered = false;

                    this.events.UnRegister();

                    if (this.ApplicationClosed_Event != null)
                    {
                        this.events.TeklaStructuresExit -= this.OnApplicationClosed;
                    }

                    if (this.Numbering_Event != null)
                    {
                        this.events.Numbering -= this.OnNumbering;
                    }

                    if (this.Loaded_Event != null)
                    {
                        this.events.ModelLoad -= this.OnLoaded;
                    }

                    if (this.Saved_Event != null)
                    {
                        this.events.ModelSave -= this.OnSaved;
                    }

                    if (this.SelectionChanged_Event != null)
                    {
                        this.events.SelectionChange -= this.OnSelectionChanged;
                    }

                    if (this.Changed_Event != null)
                    {
                        this.events.ModelChanged -= this.OnChanged;
                    }
                });
            }
        }
        /// <summary>Gets an environment variable.</summary>
        /// <param name="variableName">Variable name.</param>
        /// <value>Environment variable value.</value>
        /// <returns>The System.String.</returns>
        public string this[string variableName]
        {
            get
            {
                if (this.IsActive)
                {
                    var value = string.Empty;

                    if (
                        SeparateThread.Execute <bool>(
                            delegate { return(TeklaStructuresSettings.GetAdvancedOption(variableName, ref value)); }))
                    {
                        return(value);
                    }
                }

                return(string.Empty);
            }
        }
        /// <summary>
        /// Registers the event handlers.
        /// </summary>
        private void RegisterEvents()
        {
            if (this.events != null && !this.eventsRegistered)
            {
                SeparateThread.Execute(
                    delegate
                {
                    var registeredHandlers = 0;

                    if (this.EditorOpenedEvent != null)
                    {
                        this.events.DrawingEditorOpened += this.OnEditorOpened;
                        registeredHandlers++;
                    }

                    if (this.EditorClosedEvent != null)
                    {
                        this.events.DrawingEditorClosed += this.OnEditorClosed;
                        registeredHandlers++;
                    }

                    if (this.DrawingLoadedEvent != null)
                    {
                        this.events.DrawingLoaded += this.OnDrawingLoaded;
                        registeredHandlers++;
                    }

                    if (this.SelectionChangedEvent != null)
                    {
                        this.events.SelectionChange += this.OnSelectionChanged;
                        registeredHandlers++;
                    }

                    if (registeredHandlers > 0)
                    {
                        this.events.Register();

                        this.eventsRegistered = true;
                    }
                });
            }
        }
        /// <summary>Executes a macro in the view.</summary>
        /// <param name="macroName">Macro name.</param>
        public void RunMacro(string macroName)
        {
            if (this.IsActive)
            {
                if (!Path.HasExtension(macroName))
                {
                    macroName += ".cs";
                }

                SeparateThread.Execute(
                    delegate
                {
                    while (TSModelOperation.IsMacroRunning())
                    {
                        Thread.Sleep(100);
                    }

                    TSModelOperation.RunMacro(macroName);
                });
            }
        }