Free cookie consent management tool by TermsFeed Policy Generator

source: branches/Async/HeuristicLab.ExtLibs/HeuristicLab.WinFormsUI/2.7.0/WinFormsUI-2.7.0/Docking/FloatWindow.cs @ 13780

Last change on this file since 13780 was 8616, checked in by mkommend, 12 years ago

#1939: Added DockPanelSuite 2.7.0 to ExtLibs.

File size: 15.7 KB
Line 
1using System;
2using System.Collections;
3using System.Drawing;
4using System.Windows.Forms;
5using System.Runtime.InteropServices;
6using System.Security.Permissions;
7using System.Diagnostics.CodeAnalysis;
8
9namespace WeifenLuo.WinFormsUI.Docking
10{
11    public class FloatWindow : Form, INestedPanesContainer, IDockDragSource
12  {
13    private NestedPaneCollection m_nestedPanes;
14    internal const int WM_CHECKDISPOSE = (int)(Win32.Msgs.WM_USER + 1);
15
16    internal protected FloatWindow(DockPanel dockPanel, DockPane pane)
17    {
18      InternalConstruct(dockPanel, pane, false, Rectangle.Empty);
19    }
20
21    internal protected FloatWindow(DockPanel dockPanel, DockPane pane, Rectangle bounds)
22    {
23      InternalConstruct(dockPanel, pane, true, bounds);
24    }
25
26    private void InternalConstruct(DockPanel dockPanel, DockPane pane, bool boundsSpecified, Rectangle bounds)
27    {
28      if (dockPanel == null)
29        throw(new ArgumentNullException(Strings.FloatWindow_Constructor_NullDockPanel));
30
31      m_nestedPanes = new NestedPaneCollection(this);
32
33      FormBorderStyle = FormBorderStyle.SizableToolWindow;
34      ShowInTaskbar = false;
35            if (dockPanel.RightToLeft != RightToLeft)
36                RightToLeft = dockPanel.RightToLeft;
37            if (RightToLeftLayout != dockPanel.RightToLeftLayout)
38                RightToLeftLayout = dockPanel.RightToLeftLayout;
39     
40      SuspendLayout();
41            if (boundsSpecified)
42            {
43                Bounds = bounds;
44                StartPosition = FormStartPosition.Manual;
45            }
46            else
47            {
48                StartPosition = FormStartPosition.WindowsDefaultLocation;
49                Size = dockPanel.DefaultFloatWindowSize;
50            }
51
52      m_dockPanel = dockPanel;
53      Owner = DockPanel.FindForm();
54      DockPanel.AddFloatWindow(this);
55      if (pane != null)
56        pane.FloatWindow = this;
57
58      ResumeLayout();
59    }
60
61    protected override void Dispose(bool disposing)
62    {
63      if (disposing)
64      {
65        if (DockPanel != null)
66          DockPanel.RemoveFloatWindow(this);
67        m_dockPanel = null;
68      }
69      base.Dispose(disposing);
70    }
71
72    private bool m_allowEndUserDocking = true;
73    public bool AllowEndUserDocking
74    {
75      get { return m_allowEndUserDocking; }
76      set { m_allowEndUserDocking = value;  }
77    }
78
79    public NestedPaneCollection NestedPanes
80    {
81      get { return m_nestedPanes; }
82    }
83
84    public VisibleNestedPaneCollection VisibleNestedPanes
85    {
86      get { return NestedPanes.VisibleNestedPanes;  }
87    }
88
89    private DockPanel m_dockPanel;
90    public DockPanel DockPanel
91    {
92      get { return m_dockPanel; }
93    }
94
95    public DockState DockState
96    {
97      get { return DockState.Float; }
98    }
99 
100    public bool IsFloat
101    {
102      get { return DockState == DockState.Float;  }
103    }
104
105    internal bool IsDockStateValid(DockState dockState)
106    {
107      foreach (DockPane pane in NestedPanes)
108        foreach (IDockContent content in pane.Contents)
109          if (!DockHelper.IsDockStateValid(dockState, content.DockHandler.DockAreas))
110            return false;
111
112      return true;
113    }
114
115    protected override void OnActivated(EventArgs e)
116    {
117      DockPanel.FloatWindows.BringWindowToFront(this);
118      base.OnActivated (e);
119      // Propagate the Activated event to the visible panes content objects
120      foreach (DockPane pane in VisibleNestedPanes)
121        foreach (IDockContent content in pane.Contents)
122          content.OnActivated(e);
123    }
124
125    protected override void OnDeactivate(EventArgs e)
126    {
127      base.OnDeactivate(e);
128      // Propagate the Deactivate event to the visible panes content objects
129      foreach (DockPane pane in VisibleNestedPanes)
130        foreach (IDockContent content in pane.Contents)
131          content.OnDeactivate(e);
132    }
133
134    protected override void OnLayout(LayoutEventArgs levent)
135    {
136      VisibleNestedPanes.Refresh();
137      RefreshChanges();
138            Visible = (VisibleNestedPanes.Count > 0);
139            SetText();
140
141      base.OnLayout(levent);
142    }
143
144
145        [SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters", MessageId = "System.Windows.Forms.Control.set_Text(System.String)")]
146        internal void SetText()
147    {
148      DockPane theOnlyPane = (VisibleNestedPanes.Count == 1) ? VisibleNestedPanes[0] : null;
149
150      if (theOnlyPane == null || theOnlyPane.ActiveContent == null)
151            {
152        Text = " "; // use " " instead of string.Empty because the whole title bar will disappear when ControlBox is set to false.
153                Icon = null;
154            }
155      else
156      {
157          Text = theOnlyPane.ActiveContent.DockHandler.TabText;
158                Icon = theOnlyPane.ActiveContent.DockHandler.Icon;
159      }
160    }
161
162    protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified)
163    {
164      Rectangle rectWorkArea = SystemInformation.VirtualScreen;
165
166      if (y + height > rectWorkArea.Bottom)
167        y -= (y + height) - rectWorkArea.Bottom;
168
169      if (y < rectWorkArea.Top)
170        y += rectWorkArea.Top - y;
171
172      base.SetBoundsCore (x, y, width, height, specified);
173    }
174
175        [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
176    protected override void WndProc(ref Message m)
177    {
178      if (m.Msg == (int)Win32.Msgs.WM_NCLBUTTONDOWN)
179      {
180        if (IsDisposed)
181          return;
182
183        uint result = Win32Helper.IsRunningOnMono ? 0 : NativeMethods.SendMessage(this.Handle, (int)Win32.Msgs.WM_NCHITTEST, 0, (uint)m.LParam);
184        if (result == 2 && DockPanel.AllowEndUserDocking && this.AllowEndUserDocking) // HITTEST_CAPTION
185        {
186          Activate();
187          m_dockPanel.BeginDrag(this);
188        }
189        else
190          base.WndProc(ref m);
191
192        return;
193      }
194            else if (m.Msg == (int)Win32.Msgs.WM_NCRBUTTONDOWN)
195            {
196                uint result = Win32Helper.IsRunningOnMono ? 0 : NativeMethods.SendMessage(this.Handle, (int)Win32.Msgs.WM_NCHITTEST, 0, (uint)m.LParam);
197                if (result == 2)  // HITTEST_CAPTION
198                {
199                    DockPane theOnlyPane = (VisibleNestedPanes.Count == 1) ? VisibleNestedPanes[0] : null;
200                    if (theOnlyPane != null && theOnlyPane.ActiveContent != null)
201                    {
202                        theOnlyPane.ShowTabPageContextMenu(this, PointToClient(Control.MousePosition));
203                        return;
204                    }
205                }
206
207                base.WndProc(ref m);
208                return;
209            }
210            else if (m.Msg == (int)Win32.Msgs.WM_CLOSE)
211            {
212                if (NestedPanes.Count == 0)
213                {
214                    base.WndProc(ref m);
215                    return;
216                }
217
218                for (int i = NestedPanes.Count - 1; i >= 0; i--)
219                {
220                    DockContentCollection contents = NestedPanes[i].Contents;
221                    for (int j = contents.Count - 1; j >= 0; j--)
222                    {
223                        IDockContent content = contents[j];
224                        if (content.DockHandler.DockState != DockState.Float)
225                            continue;
226
227                        if (!content.DockHandler.CloseButton)
228                            continue;
229
230                        if (content.DockHandler.HideOnClose)
231                            content.DockHandler.Hide();
232                        else
233                            content.DockHandler.Close();
234                    }
235                }
236
237                return;
238            }
239            else if (m.Msg == (int)Win32.Msgs.WM_NCLBUTTONDBLCLK)
240            {
241                uint result = Win32Helper.IsRunningOnMono ? 0: NativeMethods.SendMessage(this.Handle, (int)Win32.Msgs.WM_NCHITTEST, 0, (uint)m.LParam);
242                if (result != 2)  // HITTEST_CAPTION
243                {
244                    base.WndProc(ref m);
245                    return;
246                }
247
248                DockPanel.SuspendLayout(true);
249
250                // Restore to panel
251                foreach (DockPane pane in NestedPanes)
252                {
253                    if (pane.DockState != DockState.Float)
254                        continue;
255                    pane.RestoreToPanel();
256                }
257
258
259                DockPanel.ResumeLayout(true, true);
260                return;
261            }
262            else if (m.Msg == WM_CHECKDISPOSE)
263            {
264                if (NestedPanes.Count == 0)
265                    Dispose();
266
267                return;
268            }
269           
270      base.WndProc(ref m);
271    }
272
273    internal void RefreshChanges()
274    {
275            if (IsDisposed)
276                return;
277
278      if (VisibleNestedPanes.Count == 0)
279      {
280        ControlBox = true;
281        return;
282      }
283
284      for (int i=VisibleNestedPanes.Count - 1; i>=0; i--)
285      {
286        DockContentCollection contents = VisibleNestedPanes[i].Contents;
287        for (int j=contents.Count - 1; j>=0; j--)
288        {
289          IDockContent content = contents[j];
290          if (content.DockHandler.DockState != DockState.Float)
291            continue;
292
293          if (content.DockHandler.CloseButton && content.DockHandler.CloseButtonVisible)
294          {
295            ControlBox = true;
296            return;
297          }
298        }
299      }
300      //Only if there is a ControlBox do we turn it off
301      //old code caused a flash of the window.
302            if (ControlBox)
303        ControlBox = false;
304    }
305
306    public virtual Rectangle DisplayingRectangle
307    {
308      get { return ClientRectangle; }
309    }
310
311    internal void TestDrop(IDockDragSource dragSource, DockOutlineBase dockOutline)
312    {
313            if (VisibleNestedPanes.Count == 1)
314            {
315                DockPane pane = VisibleNestedPanes[0];
316                if (!dragSource.CanDockTo(pane))
317                    return;
318
319                Point ptMouse = Control.MousePosition;
320                uint lParam = Win32Helper.MakeLong(ptMouse.X, ptMouse.Y);
321                if (!Win32Helper.IsRunningOnMono)
322                    if (NativeMethods.SendMessage(Handle, (int)Win32.Msgs.WM_NCHITTEST, 0, lParam) == (uint)Win32.HitTest.HTCAPTION)
323                        dockOutline.Show(VisibleNestedPanes[0], -1);
324            }
325    }
326
327        #region IDockDragSource Members
328
329        #region IDragSource Members
330
331        Control IDragSource.DragControl
332        {
333            get { return this; }
334        }
335
336        #endregion
337
338        bool IDockDragSource.IsDockStateValid(DockState dockState)
339        {
340            return IsDockStateValid(dockState);
341        }
342
343        bool IDockDragSource.CanDockTo(DockPane pane)
344        {
345            if (!IsDockStateValid(pane.DockState))
346                return false;
347
348            if (pane.FloatWindow == this)
349                return false;
350
351            return true;
352        }
353
354        private int m_preDragExStyle;
355
356        Rectangle IDockDragSource.BeginDrag(Point ptMouse)
357        {
358            m_preDragExStyle = NativeMethods.GetWindowLong(this.Handle, (int)Win32.GetWindowLongIndex.GWL_EXSTYLE);
359            NativeMethods.SetWindowLong(this.Handle,
360                                        (int)Win32.GetWindowLongIndex.GWL_EXSTYLE,
361                                        m_preDragExStyle | (int)(Win32.WindowExStyles.WS_EX_TRANSPARENT | Win32.WindowExStyles.WS_EX_LAYERED) );
362            return Bounds;
363        }
364
365        void IDockDragSource.EndDrag()
366        {
367            NativeMethods.SetWindowLong(this.Handle, (int)Win32.GetWindowLongIndex.GWL_EXSTYLE, m_preDragExStyle);
368           
369            Invalidate(true);
370            NativeMethods.SendMessage(this.Handle, (int)Win32.Msgs.WM_NCPAINT, 1, 0);
371        }
372
373        public  void FloatAt(Rectangle floatWindowBounds)
374        {
375            Bounds = floatWindowBounds;
376        }
377
378        public void DockTo(DockPane pane, DockStyle dockStyle, int contentIndex)
379        {
380            if (dockStyle == DockStyle.Fill)
381            {
382                for (int i = NestedPanes.Count - 1; i >= 0; i--)
383                {
384                    DockPane paneFrom = NestedPanes[i];
385                    for (int j = paneFrom.Contents.Count - 1; j >= 0; j--)
386                    {
387                        IDockContent c = paneFrom.Contents[j];
388                        c.DockHandler.Pane = pane;
389                        if (contentIndex != -1)
390                            pane.SetContentIndex(c, contentIndex);
391                        c.DockHandler.Activate();
392                    }
393                }
394            }
395            else
396            {
397                DockAlignment alignment = DockAlignment.Left;
398                if (dockStyle == DockStyle.Left)
399                    alignment = DockAlignment.Left;
400                else if (dockStyle == DockStyle.Right)
401                    alignment = DockAlignment.Right;
402                else if (dockStyle == DockStyle.Top)
403                    alignment = DockAlignment.Top;
404                else if (dockStyle == DockStyle.Bottom)
405                    alignment = DockAlignment.Bottom;
406
407                MergeNestedPanes(VisibleNestedPanes, pane.NestedPanesContainer.NestedPanes, pane, alignment, 0.5);
408            }
409        }
410
411        public void DockTo(DockPanel panel, DockStyle dockStyle)
412        {
413            if (panel != DockPanel)
414                throw new ArgumentException(Strings.IDockDragSource_DockTo_InvalidPanel, "panel");
415
416            NestedPaneCollection nestedPanesTo = null;
417
418            if (dockStyle == DockStyle.Top)
419                nestedPanesTo = DockPanel.DockWindows[DockState.DockTop].NestedPanes;
420            else if (dockStyle == DockStyle.Bottom)
421                nestedPanesTo = DockPanel.DockWindows[DockState.DockBottom].NestedPanes;
422            else if (dockStyle == DockStyle.Left)
423                nestedPanesTo = DockPanel.DockWindows[DockState.DockLeft].NestedPanes;
424            else if (dockStyle == DockStyle.Right)
425                nestedPanesTo = DockPanel.DockWindows[DockState.DockRight].NestedPanes;
426            else if (dockStyle == DockStyle.Fill)
427                nestedPanesTo = DockPanel.DockWindows[DockState.Document].NestedPanes;
428
429            DockPane prevPane = null;
430            for (int i = nestedPanesTo.Count - 1; i >= 0; i--)
431                if (nestedPanesTo[i] != VisibleNestedPanes[0])
432                    prevPane = nestedPanesTo[i];
433            MergeNestedPanes(VisibleNestedPanes, nestedPanesTo, prevPane, DockAlignment.Left, 0.5);
434        }
435
436        private static void MergeNestedPanes(VisibleNestedPaneCollection nestedPanesFrom, NestedPaneCollection nestedPanesTo, DockPane prevPane, DockAlignment alignment, double proportion)
437        {
438            if (nestedPanesFrom.Count == 0)
439                return;
440
441            int count = nestedPanesFrom.Count;
442            DockPane[] panes = new DockPane[count];
443            DockPane[] prevPanes = new DockPane[count];
444            DockAlignment[] alignments = new DockAlignment[count];
445            double[] proportions = new double[count];
446
447            for (int i = 0; i < count; i++)
448            {
449                panes[i] = nestedPanesFrom[i];
450                prevPanes[i] = nestedPanesFrom[i].NestedDockingStatus.PreviousPane;
451                alignments[i] = nestedPanesFrom[i].NestedDockingStatus.Alignment;
452                proportions[i] = nestedPanesFrom[i].NestedDockingStatus.Proportion;
453            }
454
455            DockPane pane = panes[0].DockTo(nestedPanesTo.Container, prevPane, alignment, proportion);
456            panes[0].DockState = nestedPanesTo.DockState;
457
458            for (int i = 1; i < count; i++)
459            {
460                for (int j = i; j < count; j++)
461                {
462                    if (prevPanes[j] == panes[i - 1])
463                        prevPanes[j] = pane;
464                }
465                pane = panes[i].DockTo(nestedPanesTo.Container, prevPanes[i], alignments[i], proportions[i]);
466                panes[i].DockState = nestedPanesTo.DockState;
467            }
468        }
469
470        #endregion
471    }
472}
Note: See TracBrowser for help on using the repository browser.