Click here to Skip to main content
Click here to Skip to main content
 
Add your own
alternative version

SVG Artiste - An SVG Editor

, 3 Aug 2010 CPOL
A Vector based tool to create and edit SVG images
SVGArtiste2_exe.zip
SvgArtiste.exe
SvgArtiste.vshost.exe.manifest
SVGLib.dll
Crom.Controls.dll
Draw.dll
SVGArtiste2_SampleSVGDrawings.zip
mercialago18.svg
SVGArtiste.svg
SVGArtiste2_src.zip
SVGLib
SVGLib.csproj.user
SVGLib.ndoc
SvgArtiste2.suo
Crom.Controls
Dock16x16.bmp
Internal
Docking
ControlCollections
Controls
DockButtons
Forms
Engine
Enums
EventArgs
Helpers
SharedHelpers
Properties
Public
Docking
Enums
EventArgs
Helpers
Renderers
TabbedDocument
Controls
Enums
Helpers
Renderers
Base
Draw
Command
Draw.csproj.user
RulerControl
Ruler.bmp
SvgArtiste2
Properties
Settings.settings
Resources
cancel.png
Ellipse.cur
exit.png
exit1.png
Line.cur
new.png
new_page.png
open.png
open1.png
pan.cur
pan_close.cur
Pencil.cur
Rectangle.cur
save.png
save_as.png
save_as1.png
Text.cur
SVGArtiste.csproj.user
Tools
Forms
UserControls
/***************************************************************************
 *   CopyRight (C) 2009 by Cristinel Mazarine                              *
 *   Author:   Cristinel Mazarine                                          *
 *   Contact:  cristinel@osec.ro                                           *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the Crom Free License as published by           *
 *   the SC Crom-Osec SRL; version 1 of the License                        *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   Crom Free License for more details.                                   *
 *                                                                         *
 *   You should have received a copy of the Crom Free License along with   *
 *   this program; if not, write to the contact@osec.ro                    *
 ***************************************************************************/

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Printing;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace Crom.Controls.Docking
{
   /// <summary>
   /// Helper class which provide information about forms
   /// </summary>
   internal class FormWrapper : Disposable
   {
      #region Fields

      private IntPtr                   _hostHandle             = IntPtr.Zero;
      private Control                  _host                   = null;
      private Control[]                _keepLast               = null;
      private Control[]                _keepFirst              = null;
      private List<Control>            _ignoreOnGetFromPoint   = new List<Control>();

      #endregion Fields

      #region Instance

      /// <summary>
      /// Light-constructor
      /// </summary>
      /// <param name="control">constructor</param>
      private FormWrapper(Control control)
      {
         _hostHandle = control.Handle;
         _host       = control;
         _keepFirst  = new Control[0];
         _keepLast   = new Control[0];
      }

      /// <summary>
      /// Default constructor
      /// </summary>
      /// <param name="window">window object</param>
      /// <param name="keepFirstCount">number of controls to keep first</param>
      /// <param name="keepLastCount">number of controls to keep last</param>
      public FormWrapper(IWin32Window window, int keepFirstCount, int keepLastCount)
      {
         _hostHandle = window.Handle;
         _keepFirst  = new Control[keepFirstCount];
         _keepLast   = new Control[keepLastCount];

         // Just for now only allow .Net control
         // TODO: implement bounds change detection for any window
         _host = window as Control;
         if (_host == null)
         {
            throw new ArgumentException("In this version are allowed only .NET controls as hosts for docking");
         }
         _host.SizeChanged     += OnHostSizeChanged;
         _host.Move            += OnHostMoved;
         _host.VisibleChanged  += OnHostVisibleChanged;
      }

      #endregion Instance

      #region Public section

      /// <summary>
      /// Event raised when form size was changed
      /// </summary>
      public event EventHandler SizeChanged;

      /// <summary>
      /// Event raised when form was moved
      /// </summary>
      public event EventHandler Move;

      /// <summary>
      /// Event raised when form visibility was changed
      /// </summary>
      public event EventHandler VisibleChanged;

      /// <summary>
      /// Checks if the form is visible
      /// </summary>
      public bool Visible
      {
         get
         {
            ValidateNotDisposed();

            return _host.Visible;// IsWindowVisible(_hostHandle);
         }
      }

      /// <summary>
      /// Accessor for the form handle
      /// </summary>
      public IntPtr Handle
      {
         get
         {
            ValidateNotDisposed();

            return _hostHandle;
         }
      }

      /// <summary>
      /// Accessor for the form text
      /// </summary>
      public string Text
      {
         get
         {
            ValidateNotDisposed();

            return _host.Text;
         }
         set
         {
            ValidateNotDisposed();

            _host.Text = value;
         }
      }

      /// <summary>
      /// Accessor for the form width
      /// </summary>
      public int Width
      {
         get
         {
            ValidateNotDisposed();

            return _host.Width;
         }
      }

      /// <summary>
      /// Accessor for the form height
      /// </summary>
      public int Height
      {
         get
         {
            ValidateNotDisposed();

            return _host.Height;
         }
      }

      /// <summary>
      /// Accessor for host client size
      /// </summary>
      public Size ClientSize
      {
         get { return _host.ClientSize; }
      }

      /// <summary>
      /// Rectangle to screen coordinates
      /// </summary>
      /// <param name="clientRectangle">client rectangle</param>
      /// <returns>rectangle in screen coordinates</returns>
      public Rectangle RectangleToScreen(Rectangle clientRectangle)
      {
         return _host.RectangleToScreen(clientRectangle);
      }

      /// <summary>
      /// Rectangle to client coordinates
      /// </summary>
      /// <param name="screenRectangle">screen rectangle</param>
      /// <returns>rectangle in client coordinates</returns>
      public Rectangle RectangleToClient(Rectangle screenRectangle)
      {
         return _host.RectangleToClient(screenRectangle);
      }

      /// <summary>
      /// Converts a screen location into client location
      /// </summary>
      /// <param name="screenLocation">screen location</param>
      /// <returns>client location</returns>
      public Point PointToClient(Point screenLocation)
      {
         return _host.PointToClient(screenLocation);
      }

      /// <summary>
      /// Client rectangle in screen coordinates
      /// </summary>
      public Rectangle ScreenClientRectangle
      {
         get
         {
            return _host.RectangleToScreen(_host.ClientRectangle);
         }
      }

      /// <summary>
      /// Gets the count of child controls
      /// </summary>
      public int ControlsCount
      {
         get { return _host.Controls.Count; }
      }

      /// <summary>
      /// Gets the child control at given index
      /// </summary>
      /// <param name="index">zero based index</param>
      /// <returns>child control at given index</returns>
      public Control GetControlAt(int index)
      {
         return _host.Controls[index];
      }

      /// <summary>
      /// Add control to host
      /// </summary>
      /// <param name="control">control to add</param>
      public void AddLast(Control control)
      {
         _host.Controls.Add(control);

         int index = GetFirstIndex(KeepLast, control);

         SetChildIndex(control, index);
      }

      /// <summary>
      /// Add control to host
      /// </summary>
      /// <param name="control">control to add</param>
      public void AddFirst(Control control)
      {
         int index = GetLastIndex(KeepFirst, control);

         _host.Controls.Add(control);
         SetChildIndex(control, index);
      }

      /// <summary>
      /// Move the control first
      /// </summary>
      /// <param name="controlToMove">control to be moved first</param>
      public void MoveFirst(Control controlToMove)
      {
         int index = GetLastIndex(KeepFirst, controlToMove);

         SetChildIndex(controlToMove, index);
      }

      /// <summary>
      /// Move the control last in zorder 
      /// </summary>
      /// <param name="controlToMove">form to be moved last</param>
      public void MoveLast(Control controlToMove)
      {
         int index = GetFirstIndex(KeepLast, controlToMove);

         SetChildIndex(controlToMove, index);
      }

      /// <summary>
      /// Remove form from host
      /// </summary>
      /// <param name="form">form</param>
      public void Remove(Control form)
      {
         _host.Controls.Remove(form);
      }

      /// <summary>
      /// Get ZOrder index
      /// </summary>
      /// <param name="form">form for which ZOrder is requested</param>
      /// <returns>ZOrder index</returns>
      public int GetZOrderIndex(Control form)
      {
         return _host.Controls.GetChildIndex(form);
      }

      /// <summary>
      /// Check if the host contains this control
      /// </summary>
      /// <param name="control">control</param>
      /// <returns>true if the host contains control</returns>
      public bool Contains(Control control)
      {
         return _host.Controls.Contains(control);
      }

      /// <summary>
      /// Gets the child leaf window found at given screen location
      /// </summary>
      /// <param name="screenPoint">point in screen coordinates</param>
      /// <param name="ignored">control to be ignored from search</param>
      /// <returns>found dockable container</returns>
      public DockableContainer GetLeafDockedContainerFromPoint(Point screenPoint, Control ignored)
      {
         for (int childIndex = 0; childIndex < ControlsCount; childIndex++)
         {
            Control child = GetControlAt(childIndex);

            if (child == ignored)
            {
               continue;
            }

            if (child.Visible == false)
            {
               continue;
            }

            DockableContainer container = child as DockableContainer;
            if (container == null)
            {
               continue;
            }

            if (container.RectangleToScreen(container.ClientRectangle).Contains(screenPoint) == false)
            {
               continue;
            }

            if (container.SingleChild != null)
            {
               if (container.SingleChild.IsDocked == false)
               {
                  continue;
               }

               return container;
            }

            return GetLeafDockedContainerFromPoint(container, screenPoint);
         }

         return null;
      }



      /// <summary>
      /// Gets the fill rectangle based on a point
      /// </summary>
      /// <param name="screenPoint">point in screen coordinates</param>
      /// <returns>rectangle from point</returns>
      public static Rectangle GetFillRectangleFromPoint(Point screenPoint, Control underPoint, FormWrapper host)
      {
         if (underPoint == null)
         {
            if (host != null)
            {
               return GetFillScreenRectangle(host);
            }

            return new Rectangle();
         }

         Rectangle result  = GetFillScreenRectangle(underPoint);
         if (result.Contains(screenPoint) == false)
         {
            return new Rectangle();
         }

         return result;
      }


      /// <summary>
      /// GEt fill screen rectangle
      /// </summary>
      /// <param name="wrapper">wrapper</param>
      /// <returns></returns>
      public static Rectangle GetFillScreenRectangle(FormWrapper wrapper)
      {
         Rectangle clientArea  = wrapper.RectangleToClient(GetScreenClientRectangle(wrapper._host));

         int x1 = clientArea.Left;
         int x2 = clientArea.Right;
         int y1 = clientArea.Top;
         int y2 = clientArea.Bottom;

         for (int index = 0; index < wrapper.ControlsCount; index++)
         {
            Control control  = wrapper.GetControlAt(index);
            if (control.Dock == DockStyle.None || control.Visible == false)
            {
               continue;
            }

            if (control.Dock == DockStyle.Left)
            {
               x1 = Math.Max(x1, control.Right);
            }
            else if (control.Dock == DockStyle.Right)
            {
               x2 = Math.Min(x2, control.Left);
            }
            else if (control.Dock == DockStyle.Top)
            {
               y1 = Math.Max(y1, control.Bottom);
            }
            else if (control.Dock == DockStyle.Bottom)
            {
               y2 = Math.Min(y2, control.Top);
            }
         }

         if (x2 <= x1 || y2 <= y1)
         {
            return new Rectangle();
         }

         Rectangle result = new Rectangle(x1, y1, x2 - x1, y2 - y1);

         return wrapper.RectangleToScreen(result);
      }

      /// <summary>
      /// Get the fill rectangle of the control in screen coordinates
      /// </summary>
      /// <param name="window">window</param>
      /// <returns>fill screen rectangle</returns>
      public static Rectangle GetFillScreenRectangle(Control window)
      {
         FormWrapper wrapper = new FormWrapper(window);
         return GetFillScreenRectangle(wrapper);
      }


      /// <summary>
      /// Gets the client rectangle of given form
      /// </summary>
      /// <param name="form">form object</param>
      /// <returns>client rectangle for given form</returns>
      public static Rectangle GetScreenClientRectangle(Control form)
      {
         return form.RectangleToScreen(form.ClientRectangle);
      }

      /// <summary>
      /// Form from point
      /// </summary>
      /// <param name="screenPoint">screen point</param>
      /// <returns>form</returns>
      public static Control FromPoint(Point screenPoint)
      {
         IntPtr handle = WindowFromPoint(screenPoint);
         if (handle == null)
         {
            return null;
         }

         try
         {
            Control control = Control.FromHandle(handle);
            return control;
         }
         catch { }

         return null;
      }

      /// <summary>
      /// Gets the margins of the control
      /// </summary>
      /// <param name="control">control</param>
      /// <returns>margins</returns>
      public static Margins GetMargins(Control control)
      {
         Margins margins  = new Margins();

         if (control != null)
         {
            WindowInfo info = new WindowInfo();
            info.cbSize = Marshal.SizeOf(info);

            if (GetWindowInfo(control.Handle, ref info) == false)
            {
               throw new InvalidOperationException();
            }

            margins.Left   = info.rcClient.left    - info.rcWindow.left;
            margins.Right  = info.rcWindow.right   - info.rcClient.right;
            margins.Top    = info.rcClient.top     - info.rcWindow.top;
            margins.Bottom = info.rcWindow.bottom  - info.rcClient.bottom;
         }

         return margins;
      }

      /// <summary>
      /// Get the container bounds inside host
      /// </summary>
      /// <param name="container">container</param>
      /// <returns>bounds relative to host</returns>
      public Rectangle GetBoundsInHost(Control control)
      {
         Rectangle bounds = control.Bounds;
         Control parent   = control.Parent;

         while (parent != null)
         {
            if (parent.Handle == Handle)
            {
               return bounds;
            }

            bounds.X += parent.Left;
            bounds.Y += parent.Top;

            parent = parent.Parent;
         }

         throw new InvalidOperationException("The control should be parented inside host");
      }

      /// <summary>
      /// Accessor for the controls to keep last
      /// </summary>
      public Control[] KeepLast
      {
         get { return _keepLast; }
      }

      /// <summary>
      /// Accessor for the controls to keep first
      /// </summary>
      public Control[] KeepFirst
      {
         get { return _keepFirst; }
      }


      /// <summary>
      /// Add control to the list of controls ignored when getting child from point
      /// </summary>
      /// <param name="control">control to ignore</param>
      public void AddToIgnoreOnGetChildFromPoint(Control control)
      {
         if (_ignoreOnGetFromPoint.Contains(control) == false)
         {
            _ignoreOnGetFromPoint.Add(control);
         }
      }

      #endregion Public section

      #region Protected section

      /// <summary>
      /// Dispose current instance
      /// </summary>
      /// <param name="fromIDisposableDispose">call from IDisposable.Dispose</param>
      protected override void Dispose(bool fromIDisposableDispose)
      {
         if (fromIDisposableDispose)
         {
            _host.SizeChanged     -= OnHostSizeChanged;
            _host.Move            -= OnHostMoved;
            _host.VisibleChanged  -= OnHostVisibleChanged;
         }

         _host = null;
      }

      #endregion Protected section

      #region Private section
      #region API

      /// <summary>
      /// Rect
      /// </summary>
      [StructLayout(LayoutKind.Sequential)]
      public struct Rect
      {
          public int left;
          public int top;
          public int right;
          public int bottom;
      };

      /// <summary>
      /// Titlebar info
      /// </summary>
      [StructLayout(LayoutKind.Sequential)]
      private struct TitlebarInfo
      {
         public int  cbSize;
         public Rect rcTitleBar;
         public int childBar0;
         public int childBar1;
         public int childBar2;
         public int childBar3;
         public int childBar4;
         public int childBar5;
      };

      /// <summary>
      /// Window info
      /// </summary>
      [StructLayout(LayoutKind.Sequential)]
      private struct WindowInfo
      {
         public int cbSize;
         public Rect rcWindow;
         public Rect rcClient;
         public int dwStyle;
         public int dwExStyle;
         public int dwWindowStatus;
         public int cxWindowBorders;
         public int cyWindowBorders;
         public short atomWindowType;
         public short wCreatorVersion;
      }

      [DllImport("user32")]
      private static extern bool GetTitleBarInfo(IntPtr hWnd, ref TitlebarInfo info);

      [DllImport("user32")]
      private static extern bool GetWindowInfo(IntPtr hWnd, ref WindowInfo info);

      [DllImport("user32")]
      private static extern bool IsWindowVisible(IntPtr hWnd);

      [DllImport("user32")]
      private static extern IntPtr WindowFromPoint(Point screenPoint);

      #endregion API

      /// <summary>
      /// On host moved
      /// </summary>
      /// <param name="sender">sender of the event</param>
      /// <param name="e">event argument</param>
      private void OnHostMoved(object sender, EventArgs e)
      {
         if (Move != null)
         {
            Move(this, EventArgs.Empty);
         }
      }

      /// <summary>
      /// On host size changed
      /// </summary>
      /// <param name="sender">sender of the event</param>
      /// <param name="e">event argument</param>
      private void OnHostSizeChanged(object sender, EventArgs e)
      {
         if (SizeChanged != null)
         {
            SizeChanged(this, EventArgs.Empty);
         }
      }

      /// <summary>
      /// On host visibility changed
      /// </summary>
      /// <param name="sender">sender of the event</param>
      /// <param name="e">event argument</param>
      private void OnHostVisibleChanged(object sender, EventArgs e)
      {
         if (VisibleChanged != null)
         {
            VisibleChanged(this, EventArgs.Empty);
         }
      }

      ///// <summary>
      ///// Gets the child leaf window found at given screen location
      ///// </summary>
      ///// <param name="screenPoint">point in screen coordinates</param>
      ///// <param name="parent">parent inside which the child is searched</param>
      ///// <param name="validate">handler to validate if child is included in search</param>
      ///// <param name="containedExcluded">flag indicating that parent contained excluded</param>
      ///// <returns>rectangle from point</returns>
      //private static Control ChildLeafFromPoint(Point screenPoint, FormWrapper parent, ExtractControlHandler validate, out bool containedExcluded)
      //{
      //   containedExcluded = false;

      //   if (parent == null)
      //   {
      //      return null;
      //   }

      //   for (int childIndex = 0; childIndex < parent.ControlsCount; childIndex++)
      //   {
      //      Control child = parent.GetControlAt(childIndex);
      //      if (IgnoreOnGetFromPoint(parent, child))
      //      {
      //         continue;
      //      }

      //      if (child.RectangleToScreen(child.ClientRectangle).Contains(screenPoint) == false)
      //      {
      //         continue;
      //      }

      //      if (validate(child) == false)
      //      {
      //         containedExcluded = true;
      //         continue;
      //      }

      //      FormWrapper childWrapper    = new FormWrapper(child);
      //      bool childContainedExcluded = false;
      //      Control found = ChildLeafFromPoint(screenPoint, childWrapper, validate, out childContainedExcluded);
      //      if (childContainedExcluded)
      //      {
      //         continue;
      //      }

      //      if (found != null)
      //      {
      //         return found;
      //      }

      //      return child;
      //   }

      //   return null;
      //}

      /// <summary>
      /// Check if should ignore the child on get from point
      /// </summary>
      /// <param name="parent">parent</param>
      /// <param name="child">child</param>
      /// <returns></returns>
      private static bool IgnoreOnGetFromPoint(FormWrapper parent, Control child)
      {
         if (child == null)
         {
            return true;
         }

         if (child.Visible == false)
         {
            return true;
         }

         Control control = child;
         while (control != null)
         {
            if (parent._ignoreOnGetFromPoint.Contains(control))
            {
               return true;
            }

            control = control.Parent;
         }

         return false;
      }

      /// <summary>
      /// Get first index of the controls
      /// </summary>
      /// <param name="controls">controls array</param>
      /// <param name="match">control that should be checked for a match in controls list</param>
      /// <returns>first index</returns>
      private int GetFirstIndex(Control[] controls, Control match)
      {
         int firstIndex = _host.Controls.Count - 1;
         if (controls != null)
         {
            for (int index = controls.Length - 1; index >= 0; index--)
            {
               Control control = controls[index];
               if (control == null)
               {
                  continue;
               }

               if (control == match)
               {
                  break;
               }

               firstIndex--;
            }
         }

         return firstIndex;
      }

      /// <summary>
      /// Get last index of the controls
      /// </summary>
      /// <param name="controls">controls array</param>
      /// <param name="match">control that should be checked for a match in controls list</param>
      /// <returns>last index</returns>
      private int GetLastIndex(Control[] controls, Control match)
      {
         int lastIndex = 0;
         if (controls != null)
         {
            for (int index = 0; index < controls.Length; index++)
            {
               Control control = controls[index];
               if (control == null)
               {
                  continue;
               }

               if (control == match)
               {
                  break;
               }

               lastIndex++;
            }
         }

         return lastIndex;
      }


      /// <summary>
      /// Set child index
      /// </summary>
      /// <param name="controlToMove">control to move</param>
      /// <param name="index">index</param>
      private void SetChildIndex(Control controlToMove, int newIndex)
      {
         _host.Controls.SetChildIndex(controlToMove, newIndex);

         int orderIndex = 0;
         for (int index = 0; index < KeepFirst.Length; index++)
         {
            if (KeepFirst[index] == null)
            {
               continue;
            }

            _host.Controls.SetChildIndex(KeepFirst[index], orderIndex);

            orderIndex++;
         }

         orderIndex = _host.Controls.Count - 1;
         for (int index = KeepLast.Length - 1; index >= 0; index--)
         {
            if (KeepLast[index] == null)
            {
               continue;
            }

            _host.Controls.SetChildIndex(KeepLast[index], orderIndex);

            orderIndex--;
         }
      }

      /// <summary>
      /// Get dock container from point
      /// </summary>
      /// <param name="parentContainer">parent container</param>
      /// <param name="screenPoint">screen point</param>
      /// <returns>leaf dock container under given screen point</returns>
      private DockableContainer GetLeafDockedContainerFromPoint(DockableContainer parentContainer, Point screenPoint)
      {
         if (parentContainer.SingleChild != null)
         {
            return parentContainer;
         }

         if (parentContainer.LeftPane != null)
         {
            if (parentContainer.LeftPane.RectangleToScreen(parentContainer.LeftPane.ClientRectangle).Contains(screenPoint))
            {
               return GetLeafDockedContainerFromPoint(parentContainer.LeftPane, screenPoint);
            }
            else if (parentContainer.RightPane.RectangleToScreen(parentContainer.RightPane.ClientRectangle).Contains(screenPoint))
            {
               return GetLeafDockedContainerFromPoint(parentContainer.RightPane, screenPoint);
            }

            // Mouse over splitter
            return null;
         }

         if (parentContainer.TopPane != null)
         {
            if (parentContainer.TopPane.RectangleToScreen(parentContainer.TopPane.ClientRectangle).Contains(screenPoint))
            {
               return GetLeafDockedContainerFromPoint(parentContainer.TopPane, screenPoint);
            }
            else if (parentContainer.BottomPane.RectangleToScreen(parentContainer.BottomPane.ClientRectangle).Contains(screenPoint))
            {
               return GetLeafDockedContainerFromPoint(parentContainer.BottomPane, screenPoint);
            }

            // Mouse over splitter
            return null;
         }

         // Mouse over splitter
         return null;
      }

      #endregion Private section
   }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Ajay Britto
Engineer
Singapore Singapore
He is a Microsoft technology enthusiast, who wish to create applications which others find useful.He loves making small tools and getting involved in architecting bigger systems.

He is currently working as a professional developer in a software development firm in .Net technologies.
 
He likes reading technical blogs, contributing to opensource and most importantly, enjoying life.
 
His ambition is to be an impressive software maker.

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.150123.1 | Last Updated 3 Aug 2010
Article Copyright 2010 by Ajay Britto
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid