Free cookie consent management tool by TermsFeed Policy Generator

source: branches/Persistence Test/WinFormsUI/Docking/FloatWindow.cs @ 3962

Last change on this file since 3962 was 2134, checked in by gkronber, 15 years ago

Added up to date source of Weifen Luo dock panel suit in a separate project (and added strong name key). Removed binary versions of Weifen Luo dock panel suite and references to it. #687 (Update AdvancedOptimizationFrontend to use more recent version of Weifen Luo Docking library)

File size: 14.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)
151        Text = " "; // use " " instead of string.Empty because the whole title bar will disappear when ControlBox is set to false.
152      else if (theOnlyPane.ActiveContent == null)
153        Text = " ";
154      else
155        Text = theOnlyPane.ActiveContent.DockHandler.TabText;
156    }
157
158    protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified)
159    {
160      Rectangle rectWorkArea = SystemInformation.VirtualScreen;
161
162      if (y + height > rectWorkArea.Bottom)
163        y -= (y + height) - rectWorkArea.Bottom;
164
165      if (y < rectWorkArea.Top)
166        y += rectWorkArea.Top - y;
167
168      base.SetBoundsCore (x, y, width, height, specified);
169    }
170
171        [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
172    protected override void WndProc(ref Message m)
173    {
174      if (m.Msg == (int)Win32.Msgs.WM_NCLBUTTONDOWN)
175      {
176        if (IsDisposed)
177          return;
178
179        uint result = NativeMethods.SendMessage(this.Handle, (int)Win32.Msgs.WM_NCHITTEST, 0, (uint)m.LParam);
180        if (result == 2 && DockPanel.AllowEndUserDocking && this.AllowEndUserDocking) // HITTEST_CAPTION
181        {
182          Activate();
183          m_dockPanel.BeginDrag(this);
184        }
185        else
186          base.WndProc(ref m);
187
188        return;
189      }
190            else if (m.Msg == (int)Win32.Msgs.WM_NCRBUTTONDOWN)
191            {
192                uint result = NativeMethods.SendMessage(this.Handle, (int)Win32.Msgs.WM_NCHITTEST, 0, (uint)m.LParam);
193                if (result == 2)  // HITTEST_CAPTION
194                {
195                    DockPane theOnlyPane = (VisibleNestedPanes.Count == 1) ? VisibleNestedPanes[0] : null;
196                    if (theOnlyPane != null && theOnlyPane.ActiveContent != null)
197                    {
198                        theOnlyPane.ShowTabPageContextMenu(this, PointToClient(Control.MousePosition));
199                        return;
200                    }
201                }
202
203                base.WndProc(ref m);
204                return;
205            }
206            else if (m.Msg == (int)Win32.Msgs.WM_CLOSE)
207            {
208                if (NestedPanes.Count == 0)
209                {
210                    base.WndProc(ref m);
211                    return;
212                }
213
214                for (int i = NestedPanes.Count - 1; i >= 0; i--)
215                {
216                    DockContentCollection contents = NestedPanes[i].Contents;
217                    for (int j = contents.Count - 1; j >= 0; j--)
218                    {
219                        IDockContent content = contents[j];
220                        if (content.DockHandler.DockState != DockState.Float)
221                            continue;
222
223                        if (!content.DockHandler.CloseButton)
224                            continue;
225
226                        if (content.DockHandler.HideOnClose)
227                            content.DockHandler.Hide();
228                        else
229                            content.DockHandler.Close();
230                    }
231                }
232
233                return;
234            }
235            else if (m.Msg == (int)Win32.Msgs.WM_NCLBUTTONDBLCLK)
236            {
237                uint result = NativeMethods.SendMessage(this.Handle, (int)Win32.Msgs.WM_NCHITTEST, 0, (uint)m.LParam);
238                if (result != 2)  // HITTEST_CAPTION
239                {
240                    base.WndProc(ref m);
241                    return;
242                }
243
244                DockPanel.SuspendLayout(true);
245
246                // Restore to panel
247                foreach (DockPane pane in NestedPanes)
248                {
249                    if (pane.DockState != DockState.Float)
250                        continue;
251                    pane.RestoreToPanel();
252                }
253
254
255                DockPanel.ResumeLayout(true, true);
256                return;
257            }
258            else if (m.Msg == WM_CHECKDISPOSE)
259            {
260                if (NestedPanes.Count == 0)
261                    Dispose();
262
263                return;
264            }
265
266      base.WndProc(ref m);
267    }
268
269    internal void RefreshChanges()
270    {
271            if (IsDisposed)
272                return;
273
274      if (VisibleNestedPanes.Count == 0)
275      {
276        ControlBox = true;
277        return;
278      }
279
280      for (int i=VisibleNestedPanes.Count - 1; i>=0; i--)
281      {
282        DockContentCollection contents = VisibleNestedPanes[i].Contents;
283        for (int j=contents.Count - 1; j>=0; j--)
284        {
285          IDockContent content = contents[j];
286          if (content.DockHandler.DockState != DockState.Float)
287            continue;
288
289          if (content.DockHandler.CloseButton && content.DockHandler.CloseButtonVisible)
290          {
291            ControlBox = true;
292            return;
293          }
294        }
295      }
296      //Only if there is a ControlBox do we turn it off
297      //old code caused a flash of the window.
298            if (ControlBox)
299        ControlBox = false;
300    }
301
302    public virtual Rectangle DisplayingRectangle
303    {
304      get { return ClientRectangle; }
305    }
306
307    internal void TestDrop(IDockDragSource dragSource, DockOutlineBase dockOutline)
308    {
309            if (VisibleNestedPanes.Count == 1)
310            {
311                DockPane pane = VisibleNestedPanes[0];
312                if (!dragSource.CanDockTo(pane))
313                    return;
314
315                Point ptMouse = Control.MousePosition;
316                uint lParam = Win32Helper.MakeLong(ptMouse.X, ptMouse.Y);
317                if (NativeMethods.SendMessage(Handle, (int)Win32.Msgs.WM_NCHITTEST, 0, lParam) == (uint)Win32.HitTest.HTCAPTION)
318                    dockOutline.Show(VisibleNestedPanes[0], -1);
319            }
320    }
321
322        #region IDockDragSource Members
323
324        #region IDragSource Members
325
326        Control IDragSource.DragControl
327        {
328            get { return this; }
329        }
330
331        #endregion
332
333        bool IDockDragSource.IsDockStateValid(DockState dockState)
334        {
335            return IsDockStateValid(dockState);
336        }
337
338        bool IDockDragSource.CanDockTo(DockPane pane)
339        {
340            if (!IsDockStateValid(pane.DockState))
341                return false;
342
343            if (pane.FloatWindow == this)
344                return false;
345
346            return true;
347        }
348
349        Rectangle IDockDragSource.BeginDrag(Point ptMouse)
350        {
351            return Bounds;
352        }
353
354        public  void FloatAt(Rectangle floatWindowBounds)
355        {
356            Bounds = floatWindowBounds;
357        }
358
359        public void DockTo(DockPane pane, DockStyle dockStyle, int contentIndex)
360        {
361            if (dockStyle == DockStyle.Fill)
362            {
363                for (int i = NestedPanes.Count - 1; i >= 0; i--)
364                {
365                    DockPane paneFrom = NestedPanes[i];
366                    for (int j = paneFrom.Contents.Count - 1; j >= 0; j--)
367                    {
368                        IDockContent c = paneFrom.Contents[j];
369                        c.DockHandler.Pane = pane;
370                        if (contentIndex != -1)
371                            pane.SetContentIndex(c, contentIndex);
372                        c.DockHandler.Activate();
373                    }
374                }
375            }
376            else
377            {
378                DockAlignment alignment = DockAlignment.Left;
379                if (dockStyle == DockStyle.Left)
380                    alignment = DockAlignment.Left;
381                else if (dockStyle == DockStyle.Right)
382                    alignment = DockAlignment.Right;
383                else if (dockStyle == DockStyle.Top)
384                    alignment = DockAlignment.Top;
385                else if (dockStyle == DockStyle.Bottom)
386                    alignment = DockAlignment.Bottom;
387
388                MergeNestedPanes(VisibleNestedPanes, pane.NestedPanesContainer.NestedPanes, pane, alignment, 0.5);
389            }
390        }
391
392        public void DockTo(DockPanel panel, DockStyle dockStyle)
393        {
394            if (panel != DockPanel)
395                throw new ArgumentException(Strings.IDockDragSource_DockTo_InvalidPanel, "panel");
396
397            NestedPaneCollection nestedPanesTo = null;
398
399            if (dockStyle == DockStyle.Top)
400                nestedPanesTo = DockPanel.DockWindows[DockState.DockTop].NestedPanes;
401            else if (dockStyle == DockStyle.Bottom)
402                nestedPanesTo = DockPanel.DockWindows[DockState.DockBottom].NestedPanes;
403            else if (dockStyle == DockStyle.Left)
404                nestedPanesTo = DockPanel.DockWindows[DockState.DockLeft].NestedPanes;
405            else if (dockStyle == DockStyle.Right)
406                nestedPanesTo = DockPanel.DockWindows[DockState.DockRight].NestedPanes;
407            else if (dockStyle == DockStyle.Fill)
408                nestedPanesTo = DockPanel.DockWindows[DockState.Document].NestedPanes;
409
410            DockPane prevPane = null;
411            for (int i = nestedPanesTo.Count - 1; i >= 0; i--)
412                if (nestedPanesTo[i] != VisibleNestedPanes[0])
413                    prevPane = nestedPanesTo[i];
414            MergeNestedPanes(VisibleNestedPanes, nestedPanesTo, prevPane, DockAlignment.Left, 0.5);
415        }
416
417        private static void MergeNestedPanes(VisibleNestedPaneCollection nestedPanesFrom, NestedPaneCollection nestedPanesTo, DockPane prevPane, DockAlignment alignment, double proportion)
418        {
419            if (nestedPanesFrom.Count == 0)
420                return;
421
422            int count = nestedPanesFrom.Count;
423            DockPane[] panes = new DockPane[count];
424            DockPane[] prevPanes = new DockPane[count];
425            DockAlignment[] alignments = new DockAlignment[count];
426            double[] proportions = new double[count];
427
428            for (int i = 0; i < count; i++)
429            {
430                panes[i] = nestedPanesFrom[i];
431                prevPanes[i] = nestedPanesFrom[i].NestedDockingStatus.PreviousPane;
432                alignments[i] = nestedPanesFrom[i].NestedDockingStatus.Alignment;
433                proportions[i] = nestedPanesFrom[i].NestedDockingStatus.Proportion;
434            }
435
436            DockPane pane = panes[0].DockTo(nestedPanesTo.Container, prevPane, alignment, proportion);
437            panes[0].DockState = nestedPanesTo.DockState;
438
439            for (int i = 1; i < count; i++)
440            {
441                for (int j = i; j < count; j++)
442                {
443                    if (prevPanes[j] == panes[i - 1])
444                        prevPanes[j] = pane;
445                }
446                pane = panes[i].DockTo(nestedPanesTo.Container, prevPanes[i], alignments[i], proportions[i]);
447                panes[i].DockState = nestedPanesTo.DockState;
448            }
449        }
450
451        #endregion
452    }
453}
Note: See TracBrowser for help on using the repository browser.