Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/HeuristicLab.ExtLibs/HeuristicLab.WinFormsUI/2.7.0/WinFormsUI-2.7.0/Docking/DockPane.cs @ 18190

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

#1939: Added DockPanelSuite 2.7.0 to ExtLibs.

File size: 45.4 KB
Line 
1using System;
2using System.ComponentModel;
3using System.Drawing;
4using System.Drawing.Drawing2D;
5using System.Windows.Forms;
6using System.Runtime.InteropServices;
7using System.Security.Permissions;
8using System.Diagnostics.CodeAnalysis;
9
10namespace WeifenLuo.WinFormsUI.Docking
11{
12    [ToolboxItem(false)]
13    public partial class DockPane : UserControl, IDockDragSource
14    {
15        public enum AppearanceStyle
16        {
17            ToolWindow,
18            Document
19        }
20
21        private enum HitTestArea
22        {
23            Caption,
24            TabStrip,
25            Content,
26            None
27        }
28
29        private struct HitTestResult
30        {
31            public HitTestArea HitArea;
32            public int Index;
33
34            public HitTestResult(HitTestArea hitTestArea, int index)
35            {
36                HitArea = hitTestArea;
37                Index = index;
38            }
39        }
40
41        private DockPaneCaptionBase m_captionControl;
42        private DockPaneCaptionBase CaptionControl
43        {
44            get { return m_captionControl; }
45        }
46
47        private DockPaneStripBase m_tabStripControl;
48        internal DockPaneStripBase TabStripControl
49        {
50            get { return m_tabStripControl; }
51        }
52
53        internal protected DockPane(IDockContent content, DockState visibleState, bool show)
54        {
55            InternalConstruct(content, visibleState, false, Rectangle.Empty, null, DockAlignment.Right, 0.5, show);
56        }
57
58        [SuppressMessage("Microsoft.Naming", "CA1720:AvoidTypeNamesInParameters", MessageId = "1#")]
59        internal protected DockPane(IDockContent content, FloatWindow floatWindow, bool show)
60        {
61            if (floatWindow == null)
62                throw new ArgumentNullException("floatWindow");
63
64            InternalConstruct(content, DockState.Float, false, Rectangle.Empty, floatWindow.NestedPanes.GetDefaultPreviousPane(this), DockAlignment.Right, 0.5, show);
65        }
66
67        internal protected DockPane(IDockContent content, DockPane previousPane, DockAlignment alignment, double proportion, bool show)
68        {
69            if (previousPane == null)
70                throw (new ArgumentNullException("previousPane"));
71            InternalConstruct(content, previousPane.DockState, false, Rectangle.Empty, previousPane, alignment, proportion, show);
72        }
73
74        [SuppressMessage("Microsoft.Naming", "CA1720:AvoidTypeNamesInParameters", MessageId = "1#")]
75        internal protected DockPane(IDockContent content, Rectangle floatWindowBounds, bool show)
76        {
77            InternalConstruct(content, DockState.Float, true, floatWindowBounds, null, DockAlignment.Right, 0.5, show);
78        }
79
80        private void InternalConstruct(IDockContent content, DockState dockState, bool flagBounds, Rectangle floatWindowBounds, DockPane prevPane, DockAlignment alignment, double proportion, bool show)
81        {
82            if (dockState == DockState.Hidden || dockState == DockState.Unknown)
83                throw new ArgumentException(Strings.DockPane_SetDockState_InvalidState);
84
85            if (content == null)
86                throw new ArgumentNullException(Strings.DockPane_Constructor_NullContent);
87
88            if (content.DockHandler.DockPanel == null)
89                throw new ArgumentException(Strings.DockPane_Constructor_NullDockPanel);
90
91
92            SuspendLayout();
93            SetStyle(ControlStyles.Selectable, false);
94
95            m_isFloat = (dockState == DockState.Float);
96
97            m_contents = new DockContentCollection();
98            m_displayingContents = new DockContentCollection(this);
99            m_dockPanel = content.DockHandler.DockPanel;
100            m_dockPanel.AddPane(this);
101
102            m_splitter = new SplitterControl(this);
103
104            m_nestedDockingStatus = new NestedDockingStatus(this);
105
106            m_captionControl = DockPanel.DockPaneCaptionFactory.CreateDockPaneCaption(this);
107            m_tabStripControl = DockPanel.DockPaneStripFactory.CreateDockPaneStrip(this);
108            Controls.AddRange(new Control[] { m_captionControl, m_tabStripControl });
109
110            DockPanel.SuspendLayout(true);
111            if (flagBounds)
112                FloatWindow = DockPanel.FloatWindowFactory.CreateFloatWindow(DockPanel, this, floatWindowBounds);
113            else if (prevPane != null)
114                DockTo(prevPane.NestedPanesContainer, prevPane, alignment, proportion);
115
116            SetDockState(dockState);
117            if (show)
118                content.DockHandler.Pane = this;
119            else if (this.IsFloat)
120                content.DockHandler.FloatPane = this;
121            else
122                content.DockHandler.PanelPane = this;
123
124            ResumeLayout();
125            DockPanel.ResumeLayout(true, true);
126        }
127
128        private bool m_isDisposing;
129
130        protected override void Dispose(bool disposing)
131        {
132            if (disposing)
133            {
134                // IMPORTANT: avoid nested call into this method on Mono.
135                // https://github.com/dockpanelsuite/dockpanelsuite/issues/16
136                if (Win32Helper.IsRunningOnMono)
137                {
138                    if (m_isDisposing)
139                        return;
140
141                    m_isDisposing = true;
142                }
143
144                m_dockState = DockState.Unknown;
145
146                if (NestedPanesContainer != null)
147                    NestedPanesContainer.NestedPanes.Remove(this);
148
149                if (DockPanel != null)
150                {
151                    DockPanel.RemovePane(this);
152                    m_dockPanel = null;
153                }
154
155                Splitter.Dispose();
156                if (m_autoHidePane != null)
157                    m_autoHidePane.Dispose();
158            }
159            base.Dispose(disposing);
160        }
161
162        private IDockContent m_activeContent = null;
163        public virtual IDockContent ActiveContent
164        {
165            get { return m_activeContent; }
166            set
167            {
168                if (ActiveContent == value)
169                    return;
170
171                if (value != null)
172                {
173                    if (!DisplayingContents.Contains(value))
174                        throw (new InvalidOperationException(Strings.DockPane_ActiveContent_InvalidValue));
175                }
176                else
177                {
178                    if (DisplayingContents.Count != 0)
179                        throw (new InvalidOperationException(Strings.DockPane_ActiveContent_InvalidValue));
180                }
181
182                IDockContent oldValue = m_activeContent;
183
184                if (DockPanel.ActiveAutoHideContent == oldValue)
185                    DockPanel.ActiveAutoHideContent = null;
186
187                m_activeContent = value;
188
189                if (DockPanel.DocumentStyle == DocumentStyle.DockingMdi && DockState == DockState.Document)
190                {
191                    if (m_activeContent != null)
192                        m_activeContent.DockHandler.Form.BringToFront();
193                }
194                else
195                {
196                    if (m_activeContent != null)
197                        m_activeContent.DockHandler.SetVisible();
198                    if (oldValue != null && DisplayingContents.Contains(oldValue))
199                        oldValue.DockHandler.SetVisible();
200                    if (IsActivated && m_activeContent != null)
201                        m_activeContent.DockHandler.Activate();
202                }
203
204                if (FloatWindow != null)
205                    FloatWindow.SetText();
206
207                if (DockPanel.DocumentStyle == DocumentStyle.DockingMdi &&
208                    DockState == DockState.Document)
209                    RefreshChanges(false);  // delayed layout to reduce screen flicker
210                else
211                    RefreshChanges();
212
213                if (m_activeContent != null)
214                    TabStripControl.EnsureTabVisible(m_activeContent);
215            }
216        }
217
218        private bool m_allowDockDragAndDrop = true;
219        public virtual bool AllowDockDragAndDrop
220        {
221            get { return m_allowDockDragAndDrop; }
222            set { m_allowDockDragAndDrop = value; }
223        }
224
225        private IDisposable m_autoHidePane = null;
226        internal IDisposable AutoHidePane
227        {
228            get { return m_autoHidePane; }
229            set { m_autoHidePane = value; }
230        }
231
232        private object m_autoHideTabs = null;
233        internal object AutoHideTabs
234        {
235            get { return m_autoHideTabs; }
236            set { m_autoHideTabs = value; }
237        }
238
239        private object TabPageContextMenu
240        {
241            get
242            {
243                IDockContent content = ActiveContent;
244
245                if (content == null)
246                    return null;
247
248                if (content.DockHandler.TabPageContextMenuStrip != null)
249                    return content.DockHandler.TabPageContextMenuStrip;
250                else if (content.DockHandler.TabPageContextMenu != null)
251                    return content.DockHandler.TabPageContextMenu;
252                else
253                    return null;
254            }
255        }
256
257        internal bool HasTabPageContextMenu
258        {
259            get { return TabPageContextMenu != null; }
260        }
261
262        internal void ShowTabPageContextMenu(Control control, Point position)
263        {
264            object menu = TabPageContextMenu;
265
266            if (menu == null)
267                return;
268
269            ContextMenuStrip contextMenuStrip = menu as ContextMenuStrip;
270            if (contextMenuStrip != null)
271            {
272                contextMenuStrip.Show(control, position);
273                return;
274            }
275
276            ContextMenu contextMenu = menu as ContextMenu;
277            if (contextMenu != null)
278                contextMenu.Show(this, position);
279        }
280
281        private Rectangle CaptionRectangle
282        {
283            get
284            {
285                if (!HasCaption)
286                    return Rectangle.Empty;
287
288                Rectangle rectWindow = DisplayingRectangle;
289                int x, y, width;
290                x = rectWindow.X;
291                y = rectWindow.Y;
292                width = rectWindow.Width;
293                int height = CaptionControl.MeasureHeight();
294
295                return new Rectangle(x, y, width, height);
296            }
297        }
298
299        internal Rectangle ContentRectangle
300        {
301            get
302            {
303                Rectangle rectWindow = DisplayingRectangle;
304                Rectangle rectCaption = CaptionRectangle;
305                Rectangle rectTabStrip = TabStripRectangle;
306
307                int x = rectWindow.X;
308
309                int y = rectWindow.Y + (rectCaption.IsEmpty ? 0 : rectCaption.Height);
310                if (DockState == DockState.Document && DockPanel.DocumentTabStripLocation == DocumentTabStripLocation.Top)
311                    y += rectTabStrip.Height;
312
313                int width = rectWindow.Width;
314                int height = rectWindow.Height - rectCaption.Height - rectTabStrip.Height;
315
316                return new Rectangle(x, y, width, height);
317            }
318        }
319
320        internal Rectangle TabStripRectangle
321        {
322            get
323            {
324                if (Appearance == AppearanceStyle.ToolWindow)
325                    return TabStripRectangle_ToolWindow;
326                else
327                    return TabStripRectangle_Document;
328            }
329        }
330
331        private Rectangle TabStripRectangle_ToolWindow
332        {
333            get
334            {
335                if (DisplayingContents.Count <= 1 || IsAutoHide)
336                    return Rectangle.Empty;
337
338                Rectangle rectWindow = DisplayingRectangle;
339
340                int width = rectWindow.Width;
341                int height = TabStripControl.MeasureHeight();
342                int x = rectWindow.X;
343                int y = rectWindow.Bottom - height;
344                Rectangle rectCaption = CaptionRectangle;
345                if (rectCaption.Contains(x, y))
346                    y = rectCaption.Y + rectCaption.Height;
347
348                return new Rectangle(x, y, width, height);
349            }
350        }
351
352        private Rectangle TabStripRectangle_Document
353        {
354            get
355            {
356                if (DisplayingContents.Count == 0)
357                    return Rectangle.Empty;
358
359                if (DisplayingContents.Count == 1 && DockPanel.DocumentStyle == DocumentStyle.DockingSdi)
360                    return Rectangle.Empty;
361
362                Rectangle rectWindow = DisplayingRectangle;
363                int x = rectWindow.X;
364                int width = rectWindow.Width;
365                int height = TabStripControl.MeasureHeight();
366
367                int y = 0;
368                if (DockPanel.DocumentTabStripLocation == DocumentTabStripLocation.Bottom)
369                    y = rectWindow.Height - height;
370                else
371                    y = rectWindow.Y;
372
373                return new Rectangle(x, y, width, height);
374            }
375        }
376
377        public virtual string CaptionText
378        {
379            get { return ActiveContent == null ? string.Empty : ActiveContent.DockHandler.TabText; }
380        }
381
382        private DockContentCollection m_contents;
383        public DockContentCollection Contents
384        {
385            get { return m_contents; }
386        }
387
388        private DockContentCollection m_displayingContents;
389        public DockContentCollection DisplayingContents
390        {
391            get { return m_displayingContents; }
392        }
393
394        private DockPanel m_dockPanel;
395        public DockPanel DockPanel
396        {
397            get { return m_dockPanel; }
398        }
399
400        private bool HasCaption
401        {
402            get
403            {
404                if (DockState == DockState.Document ||
405                    DockState == DockState.Hidden ||
406                    DockState == DockState.Unknown ||
407                    (DockState == DockState.Float && FloatWindow.VisibleNestedPanes.Count <= 1))
408                    return false;
409                else
410                    return true;
411            }
412        }
413
414        private bool m_isActivated = false;
415        public bool IsActivated
416        {
417            get { return m_isActivated; }
418        }
419        internal void SetIsActivated(bool value)
420        {
421            if (m_isActivated == value)
422                return;
423
424            m_isActivated = value;
425            if (DockState != DockState.Document)
426                RefreshChanges(false);
427            OnIsActivatedChanged(EventArgs.Empty);
428        }
429
430        private bool m_isActiveDocumentPane = false;
431        public bool IsActiveDocumentPane
432        {
433            get { return m_isActiveDocumentPane; }
434        }
435        internal void SetIsActiveDocumentPane(bool value)
436        {
437            if (m_isActiveDocumentPane == value)
438                return;
439
440            m_isActiveDocumentPane = value;
441            if (DockState == DockState.Document)
442                RefreshChanges();
443            OnIsActiveDocumentPaneChanged(EventArgs.Empty);
444        }
445
446        public bool IsDockStateValid(DockState dockState)
447        {
448            foreach (IDockContent content in Contents)
449                if (!content.DockHandler.IsDockStateValid(dockState))
450                    return false;
451
452            return true;
453        }
454
455        public bool IsAutoHide
456        {
457            get { return DockHelper.IsDockStateAutoHide(DockState); }
458        }
459
460        public AppearanceStyle Appearance
461        {
462            get { return (DockState == DockState.Document) ? AppearanceStyle.Document : AppearanceStyle.ToolWindow; }
463        }
464
465        internal Rectangle DisplayingRectangle
466        {
467            get { return ClientRectangle; }
468        }
469
470        public void Activate()
471        {
472            if (DockHelper.IsDockStateAutoHide(DockState) && DockPanel.ActiveAutoHideContent != ActiveContent)
473                DockPanel.ActiveAutoHideContent = ActiveContent;
474            else if (!IsActivated && ActiveContent != null)
475                ActiveContent.DockHandler.Activate();
476        }
477
478        internal void AddContent(IDockContent content)
479        {
480            if (Contents.Contains(content))
481                return;
482
483            Contents.Add(content);
484        }
485
486        internal void Close()
487        {
488            Dispose();
489        }
490
491        public void CloseActiveContent()
492        {
493            CloseContent(ActiveContent);
494        }
495
496        internal void CloseContent(IDockContent content)
497        {
498            if (content == null)
499                return;
500
501            if (!content.DockHandler.CloseButton)
502                return;
503
504            DockPanel dockPanel = DockPanel;
505
506            dockPanel.SuspendLayout(true);
507
508            try
509            {
510                if (content.DockHandler.HideOnClose)
511                {
512                    content.DockHandler.Hide();
513                    NestedDockingStatus.NestedPanes.SwitchPaneWithFirstChild(this);
514                }
515                else
516                    content.DockHandler.Close();
517            }
518            finally
519            {
520                dockPanel.ResumeLayout(true, true);
521            }
522        }
523
524        private HitTestResult GetHitTest(Point ptMouse)
525        {
526            Point ptMouseClient = PointToClient(ptMouse);
527
528            Rectangle rectCaption = CaptionRectangle;
529            if (rectCaption.Contains(ptMouseClient))
530                return new HitTestResult(HitTestArea.Caption, -1);
531
532            Rectangle rectContent = ContentRectangle;
533            if (rectContent.Contains(ptMouseClient))
534                return new HitTestResult(HitTestArea.Content, -1);
535
536            Rectangle rectTabStrip = TabStripRectangle;
537            if (rectTabStrip.Contains(ptMouseClient))
538                return new HitTestResult(HitTestArea.TabStrip, TabStripControl.HitTest(TabStripControl.PointToClient(ptMouse)));
539
540            return new HitTestResult(HitTestArea.None, -1);
541        }
542
543        private bool m_isHidden = true;
544        public bool IsHidden
545        {
546            get { return m_isHidden; }
547        }
548        private void SetIsHidden(bool value)
549        {
550            if (m_isHidden == value)
551                return;
552
553            m_isHidden = value;
554            if (DockHelper.IsDockStateAutoHide(DockState))
555            {
556                DockPanel.RefreshAutoHideStrip();
557                DockPanel.PerformLayout();
558            }
559            else if (NestedPanesContainer != null)
560                ((Control)NestedPanesContainer).PerformLayout();
561        }
562
563        protected override void OnLayout(LayoutEventArgs levent)
564        {
565            SetIsHidden(DisplayingContents.Count == 0);
566            if (!IsHidden)
567            {
568                CaptionControl.Bounds = CaptionRectangle;
569                TabStripControl.Bounds = TabStripRectangle;
570
571                SetContentBounds();
572
573                foreach (IDockContent content in Contents)
574                {
575                    if (DisplayingContents.Contains(content))
576                        if (content.DockHandler.FlagClipWindow && content.DockHandler.Form.Visible)
577                            content.DockHandler.FlagClipWindow = false;
578                }
579            }
580
581            base.OnLayout(levent);
582        }
583
584        internal void SetContentBounds()
585        {
586            Rectangle rectContent = ContentRectangle;
587            if (DockState == DockState.Document && DockPanel.DocumentStyle == DocumentStyle.DockingMdi)
588                rectContent = DockPanel.RectangleToMdiClient(RectangleToScreen(rectContent));
589
590            Rectangle rectInactive = new Rectangle(-rectContent.Width, rectContent.Y, rectContent.Width, rectContent.Height);
591            foreach (IDockContent content in Contents)
592                if (content.DockHandler.Pane == this)
593                {
594                    if (content == ActiveContent)
595                        content.DockHandler.Form.Bounds = rectContent;
596                    else
597                        content.DockHandler.Form.Bounds = rectInactive;
598                }
599        }
600
601        internal void RefreshChanges()
602        {
603            RefreshChanges(true);
604        }
605
606        private void RefreshChanges(bool performLayout)
607        {
608            if (IsDisposed)
609                return;
610
611            CaptionControl.RefreshChanges();
612            TabStripControl.RefreshChanges();
613            if (DockState == DockState.Float && FloatWindow != null)
614                FloatWindow.RefreshChanges();
615            if (DockHelper.IsDockStateAutoHide(DockState) && DockPanel != null)
616            {
617                DockPanel.RefreshAutoHideStrip();
618                DockPanel.PerformLayout();
619            }
620
621            if (performLayout)
622                PerformLayout();
623        }
624
625        internal void RemoveContent(IDockContent content)
626        {
627            if (!Contents.Contains(content))
628                return;
629
630            Contents.Remove(content);
631        }
632
633        public void SetContentIndex(IDockContent content, int index)
634        {
635            int oldIndex = Contents.IndexOf(content);
636            if (oldIndex == -1)
637                throw (new ArgumentException(Strings.DockPane_SetContentIndex_InvalidContent));
638
639            if (index < 0 || index > Contents.Count - 1)
640                if (index != -1)
641                    throw (new ArgumentOutOfRangeException(Strings.DockPane_SetContentIndex_InvalidIndex));
642
643            if (oldIndex == index)
644                return;
645            if (oldIndex == Contents.Count - 1 && index == -1)
646                return;
647
648            Contents.Remove(content);
649            if (index == -1)
650                Contents.Add(content);
651            else if (oldIndex < index)
652                Contents.AddAt(content, index - 1);
653            else
654                Contents.AddAt(content, index);
655
656            RefreshChanges();
657        }
658
659        private void SetParent()
660        {
661            if (DockState == DockState.Unknown || DockState == DockState.Hidden)
662            {
663                SetParent(null);
664                Splitter.Parent = null;
665            }
666            else if (DockState == DockState.Float)
667            {
668                SetParent(FloatWindow);
669                Splitter.Parent = FloatWindow;
670            }
671            else if (DockHelper.IsDockStateAutoHide(DockState))
672            {
673                SetParent(DockPanel.AutoHideControl);
674                Splitter.Parent = null;
675            }
676            else
677            {
678                SetParent(DockPanel.DockWindows[DockState]);
679                Splitter.Parent = Parent;
680            }
681        }
682
683        private void SetParent(Control value)
684        {
685            if (Parent == value)
686                return;
687
688            //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
689            // Workaround of .Net Framework bug:
690            // Change the parent of a control with focus may result in the first
691            // MDI child form get activated.
692            //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
693            IDockContent contentFocused = GetFocusedContent();
694            if (contentFocused != null)
695                DockPanel.SaveFocus();
696
697            //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
698
699            Parent = value;
700
701            //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
702            // Workaround of .Net Framework bug:
703            // Change the parent of a control with focus may result in the first
704            // MDI child form get activated.
705            //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
706            if (contentFocused != null)
707                contentFocused.DockHandler.Activate();
708            //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
709        }
710
711        public new void Show()
712        {
713            Activate();
714        }
715
716        internal void TestDrop(IDockDragSource dragSource, DockOutlineBase dockOutline)
717        {
718            if (!dragSource.CanDockTo(this))
719                return;
720
721            Point ptMouse = Control.MousePosition;
722
723            HitTestResult hitTestResult = GetHitTest(ptMouse);
724            if (hitTestResult.HitArea == HitTestArea.Caption)
725                dockOutline.Show(this, -1);
726            else if (hitTestResult.HitArea == HitTestArea.TabStrip && hitTestResult.Index != -1)
727                dockOutline.Show(this, hitTestResult.Index);
728        }
729
730        internal void ValidateActiveContent()
731        {
732            if (ActiveContent == null)
733            {
734                if (DisplayingContents.Count != 0)
735                    ActiveContent = DisplayingContents[0];
736                return;
737            }
738
739            if (DisplayingContents.IndexOf(ActiveContent) >= 0)
740                return;
741
742            IDockContent prevVisible = null;
743            for (int i = Contents.IndexOf(ActiveContent) - 1; i >= 0; i--)
744                if (Contents[i].DockHandler.DockState == DockState)
745                {
746                    prevVisible = Contents[i];
747                    break;
748                }
749
750            IDockContent nextVisible = null;
751            for (int i = Contents.IndexOf(ActiveContent) + 1; i < Contents.Count; i++)
752                if (Contents[i].DockHandler.DockState == DockState)
753                {
754                    nextVisible = Contents[i];
755                    break;
756                }
757
758            if (prevVisible != null)
759                ActiveContent = prevVisible;
760            else if (nextVisible != null)
761                ActiveContent = nextVisible;
762            else
763                ActiveContent = null;
764        }
765
766        private static readonly object DockStateChangedEvent = new object();
767        public event EventHandler DockStateChanged
768        {
769            add { Events.AddHandler(DockStateChangedEvent, value); }
770            remove { Events.RemoveHandler(DockStateChangedEvent, value); }
771        }
772        protected virtual void OnDockStateChanged(EventArgs e)
773        {
774            EventHandler handler = (EventHandler)Events[DockStateChangedEvent];
775            if (handler != null)
776                handler(this, e);
777        }
778
779        private static readonly object IsActivatedChangedEvent = new object();
780        public event EventHandler IsActivatedChanged
781        {
782            add { Events.AddHandler(IsActivatedChangedEvent, value); }
783            remove { Events.RemoveHandler(IsActivatedChangedEvent, value); }
784        }
785        protected virtual void OnIsActivatedChanged(EventArgs e)
786        {
787            EventHandler handler = (EventHandler)Events[IsActivatedChangedEvent];
788            if (handler != null)
789                handler(this, e);
790        }
791
792        private static readonly object IsActiveDocumentPaneChangedEvent = new object();
793        public event EventHandler IsActiveDocumentPaneChanged
794        {
795            add { Events.AddHandler(IsActiveDocumentPaneChangedEvent, value); }
796            remove { Events.RemoveHandler(IsActiveDocumentPaneChangedEvent, value); }
797        }
798        protected virtual void OnIsActiveDocumentPaneChanged(EventArgs e)
799        {
800            EventHandler handler = (EventHandler)Events[IsActiveDocumentPaneChangedEvent];
801            if (handler != null)
802                handler(this, e);
803        }
804
805        public DockWindow DockWindow
806        {
807            get { return (m_nestedDockingStatus.NestedPanes == null) ? null : m_nestedDockingStatus.NestedPanes.Container as DockWindow; }
808            set
809            {
810                DockWindow oldValue = DockWindow;
811                if (oldValue == value)
812                    return;
813
814                DockTo(value);
815            }
816        }
817
818        public FloatWindow FloatWindow
819        {
820            get { return (m_nestedDockingStatus.NestedPanes == null) ? null : m_nestedDockingStatus.NestedPanes.Container as FloatWindow; }
821            set
822            {
823                FloatWindow oldValue = FloatWindow;
824                if (oldValue == value)
825                    return;
826
827                DockTo(value);
828            }
829        }
830
831        private NestedDockingStatus m_nestedDockingStatus;
832        public NestedDockingStatus NestedDockingStatus
833        {
834            get { return m_nestedDockingStatus; }
835        }
836
837        private bool m_isFloat;
838        public bool IsFloat
839        {
840            get { return m_isFloat; }
841        }
842
843        public INestedPanesContainer NestedPanesContainer
844        {
845            get
846            {
847                if (NestedDockingStatus.NestedPanes == null)
848                    return null;
849                else
850                    return NestedDockingStatus.NestedPanes.Container;
851            }
852        }
853
854        private DockState m_dockState = DockState.Unknown;
855        public DockState DockState
856        {
857            get { return m_dockState; }
858            set
859            {
860                SetDockState(value);
861            }
862        }
863
864        public DockPane SetDockState(DockState value)
865        {
866            if (value == DockState.Unknown || value == DockState.Hidden)
867                throw new InvalidOperationException(Strings.DockPane_SetDockState_InvalidState);
868
869            if ((value == DockState.Float) == this.IsFloat)
870            {
871                InternalSetDockState(value);
872                return this;
873            }
874
875            if (DisplayingContents.Count == 0)
876                return null;
877
878            IDockContent firstContent = null;
879            for (int i = 0; i < DisplayingContents.Count; i++)
880            {
881                IDockContent content = DisplayingContents[i];
882                if (content.DockHandler.IsDockStateValid(value))
883                {
884                    firstContent = content;
885                    break;
886                }
887            }
888            if (firstContent == null)
889                return null;
890
891            firstContent.DockHandler.DockState = value;
892            DockPane pane = firstContent.DockHandler.Pane;
893            DockPanel.SuspendLayout(true);
894            for (int i = 0; i < DisplayingContents.Count; i++)
895            {
896                IDockContent content = DisplayingContents[i];
897                if (content.DockHandler.IsDockStateValid(value))
898                    content.DockHandler.Pane = pane;
899            }
900            DockPanel.ResumeLayout(true, true);
901            return pane;
902        }
903
904        private void InternalSetDockState(DockState value)
905        {
906            if (m_dockState == value)
907                return;
908
909            DockState oldDockState = m_dockState;
910            INestedPanesContainer oldContainer = NestedPanesContainer;
911
912            m_dockState = value;
913
914            SuspendRefreshStateChange();
915
916            IDockContent contentFocused = GetFocusedContent();
917            if (contentFocused != null)
918                DockPanel.SaveFocus();
919
920            if (!IsFloat)
921                DockWindow = DockPanel.DockWindows[DockState];
922            else if (FloatWindow == null)
923                FloatWindow = DockPanel.FloatWindowFactory.CreateFloatWindow(DockPanel, this);
924
925            if (contentFocused != null)
926                if (!Win32Helper.IsRunningOnMono)
927                DockPanel.ContentFocusManager.Activate(contentFocused);
928
929            ResumeRefreshStateChange(oldContainer, oldDockState);
930        }
931
932        private int m_countRefreshStateChange = 0;
933        private void SuspendRefreshStateChange()
934        {
935            m_countRefreshStateChange++;
936            DockPanel.SuspendLayout(true);
937        }
938
939        private void ResumeRefreshStateChange()
940        {
941            m_countRefreshStateChange--;
942            System.Diagnostics.Debug.Assert(m_countRefreshStateChange >= 0);
943            DockPanel.ResumeLayout(true, true);
944        }
945
946        private bool IsRefreshStateChangeSuspended
947        {
948            get { return m_countRefreshStateChange != 0; }
949        }
950
951        private void ResumeRefreshStateChange(INestedPanesContainer oldContainer, DockState oldDockState)
952        {
953            ResumeRefreshStateChange();
954            RefreshStateChange(oldContainer, oldDockState);
955        }
956
957        private void RefreshStateChange(INestedPanesContainer oldContainer, DockState oldDockState)
958        {
959            lock (this)
960            {
961                if (IsRefreshStateChangeSuspended)
962                    return;
963
964                SuspendRefreshStateChange();
965            }
966
967            DockPanel.SuspendLayout(true);
968
969            IDockContent contentFocused = GetFocusedContent();
970            if (contentFocused != null)
971                DockPanel.SaveFocus();
972            SetParent();
973
974            if (ActiveContent != null)
975                ActiveContent.DockHandler.SetDockState(ActiveContent.DockHandler.IsHidden, DockState, ActiveContent.DockHandler.Pane);
976            foreach (IDockContent content in Contents)
977            {
978                if (content.DockHandler.Pane == this)
979                    content.DockHandler.SetDockState(content.DockHandler.IsHidden, DockState, content.DockHandler.Pane);
980            }
981
982            if (oldContainer != null)
983            {
984                Control oldContainerControl = (Control)oldContainer;
985                if (oldContainer.DockState == oldDockState && !oldContainerControl.IsDisposed)
986                    oldContainerControl.PerformLayout();
987            }
988            if (DockHelper.IsDockStateAutoHide(oldDockState))
989                DockPanel.RefreshActiveAutoHideContent();
990
991            if (NestedPanesContainer.DockState == DockState)
992                ((Control)NestedPanesContainer).PerformLayout();
993            if (DockHelper.IsDockStateAutoHide(DockState))
994                DockPanel.RefreshActiveAutoHideContent();
995
996            if (DockHelper.IsDockStateAutoHide(oldDockState) ||
997                DockHelper.IsDockStateAutoHide(DockState))
998            {
999                DockPanel.RefreshAutoHideStrip();
1000                DockPanel.PerformLayout();
1001            }
1002
1003            ResumeRefreshStateChange();
1004
1005            if (contentFocused != null)
1006                contentFocused.DockHandler.Activate();
1007
1008            DockPanel.ResumeLayout(true, true);
1009
1010            if (oldDockState != DockState)
1011                OnDockStateChanged(EventArgs.Empty);
1012        }
1013
1014        private IDockContent GetFocusedContent()
1015        {
1016            IDockContent contentFocused = null;
1017            foreach (IDockContent content in Contents)
1018            {
1019                if (content.DockHandler.Form.ContainsFocus)
1020                {
1021                    contentFocused = content;
1022                    break;
1023                }
1024            }
1025
1026            return contentFocused;
1027        }
1028
1029        public DockPane DockTo(INestedPanesContainer container)
1030        {
1031            if (container == null)
1032                throw new InvalidOperationException(Strings.DockPane_DockTo_NullContainer);
1033
1034            DockAlignment alignment;
1035            if (container.DockState == DockState.DockLeft || container.DockState == DockState.DockRight)
1036                alignment = DockAlignment.Bottom;
1037            else
1038                alignment = DockAlignment.Right;
1039
1040            return DockTo(container, container.NestedPanes.GetDefaultPreviousPane(this), alignment, 0.5);
1041        }
1042
1043        public DockPane DockTo(INestedPanesContainer container, DockPane previousPane, DockAlignment alignment, double proportion)
1044        {
1045            if (container == null)
1046                throw new InvalidOperationException(Strings.DockPane_DockTo_NullContainer);
1047
1048            if (container.IsFloat == this.IsFloat)
1049            {
1050                InternalAddToDockList(container, previousPane, alignment, proportion);
1051                return this;
1052            }
1053
1054            IDockContent firstContent = GetFirstContent(container.DockState);
1055            if (firstContent == null)
1056                return null;
1057
1058            DockPane pane;
1059            DockPanel.DummyContent.DockPanel = DockPanel;
1060            if (container.IsFloat)
1061                pane = DockPanel.DockPaneFactory.CreateDockPane(DockPanel.DummyContent, (FloatWindow)container, true);
1062            else
1063                pane = DockPanel.DockPaneFactory.CreateDockPane(DockPanel.DummyContent, container.DockState, true);
1064
1065            pane.DockTo(container, previousPane, alignment, proportion);
1066            SetVisibleContentsToPane(pane);
1067            DockPanel.DummyContent.DockPanel = null;
1068
1069            return pane;
1070        }
1071
1072        private void SetVisibleContentsToPane(DockPane pane)
1073        {
1074            SetVisibleContentsToPane(pane, ActiveContent);
1075        }
1076
1077        private void SetVisibleContentsToPane(DockPane pane, IDockContent activeContent)
1078        {
1079            for (int i = 0; i < DisplayingContents.Count; i++)
1080            {
1081                IDockContent content = DisplayingContents[i];
1082                if (content.DockHandler.IsDockStateValid(pane.DockState))
1083                {
1084                    content.DockHandler.Pane = pane;
1085                    i--;
1086                }
1087            }
1088
1089            if (activeContent.DockHandler.Pane == pane)
1090                pane.ActiveContent = activeContent;
1091        }
1092
1093        private void InternalAddToDockList(INestedPanesContainer container, DockPane prevPane, DockAlignment alignment, double proportion)
1094        {
1095            if ((container.DockState == DockState.Float) != IsFloat)
1096                throw new InvalidOperationException(Strings.DockPane_DockTo_InvalidContainer);
1097
1098            int count = container.NestedPanes.Count;
1099            if (container.NestedPanes.Contains(this))
1100                count--;
1101            if (prevPane == null && count > 0)
1102                throw new InvalidOperationException(Strings.DockPane_DockTo_NullPrevPane);
1103
1104            if (prevPane != null && !container.NestedPanes.Contains(prevPane))
1105                throw new InvalidOperationException(Strings.DockPane_DockTo_NoPrevPane);
1106
1107            if (prevPane == this)
1108                throw new InvalidOperationException(Strings.DockPane_DockTo_SelfPrevPane);
1109
1110            INestedPanesContainer oldContainer = NestedPanesContainer;
1111            DockState oldDockState = DockState;
1112            container.NestedPanes.Add(this);
1113            NestedDockingStatus.SetStatus(container.NestedPanes, prevPane, alignment, proportion);
1114
1115            if (DockHelper.IsDockWindowState(DockState))
1116                m_dockState = container.DockState;
1117
1118            RefreshStateChange(oldContainer, oldDockState);
1119        }
1120
1121        public void SetNestedDockingProportion(double proportion)
1122        {
1123            NestedDockingStatus.SetStatus(NestedDockingStatus.NestedPanes, NestedDockingStatus.PreviousPane, NestedDockingStatus.Alignment, proportion);
1124            if (NestedPanesContainer != null)
1125                ((Control)NestedPanesContainer).PerformLayout();
1126        }
1127
1128        public DockPane Float()
1129        {
1130            DockPanel.SuspendLayout(true);
1131
1132            IDockContent activeContent = ActiveContent;
1133
1134            DockPane floatPane = GetFloatPaneFromContents();
1135            if (floatPane == null)
1136            {
1137                IDockContent firstContent = GetFirstContent(DockState.Float);
1138                if (firstContent == null)
1139                {
1140                    DockPanel.ResumeLayout(true, true);
1141                    return null;
1142                }
1143                floatPane = DockPanel.DockPaneFactory.CreateDockPane(firstContent, DockState.Float, true);
1144            }
1145            SetVisibleContentsToPane(floatPane, activeContent);
1146
1147            DockPanel.ResumeLayout(true, true);
1148            return floatPane;
1149        }
1150
1151        private DockPane GetFloatPaneFromContents()
1152        {
1153            DockPane floatPane = null;
1154            for (int i = 0; i < DisplayingContents.Count; i++)
1155            {
1156                IDockContent content = DisplayingContents[i];
1157                if (!content.DockHandler.IsDockStateValid(DockState.Float))
1158                    continue;
1159
1160                if (floatPane != null && content.DockHandler.FloatPane != floatPane)
1161                    return null;
1162                else
1163                    floatPane = content.DockHandler.FloatPane;
1164            }
1165
1166            return floatPane;
1167        }
1168
1169        private IDockContent GetFirstContent(DockState dockState)
1170        {
1171            for (int i = 0; i < DisplayingContents.Count; i++)
1172            {
1173                IDockContent content = DisplayingContents[i];
1174                if (content.DockHandler.IsDockStateValid(dockState))
1175                    return content;
1176            }
1177            return null;
1178        }
1179
1180        public void RestoreToPanel()
1181        {
1182            DockPanel.SuspendLayout(true);
1183
1184            IDockContent activeContent = DockPanel.ActiveContent;
1185
1186            for (int i = DisplayingContents.Count - 1; i >= 0; i--)
1187            {
1188                IDockContent content = DisplayingContents[i];
1189                if (content.DockHandler.CheckDockState(false) != DockState.Unknown)
1190                    content.DockHandler.IsFloat = false;
1191            }
1192
1193            DockPanel.ResumeLayout(true, true);
1194        }
1195
1196        [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
1197        protected override void WndProc(ref Message m)
1198        {
1199            if (m.Msg == (int)Win32.Msgs.WM_MOUSEACTIVATE)
1200                Activate();
1201
1202            base.WndProc(ref m);
1203        }
1204
1205        #region IDockDragSource Members
1206
1207        #region IDragSource Members
1208
1209        Control IDragSource.DragControl
1210        {
1211            get { return this; }
1212        }
1213
1214        #endregion
1215
1216        bool IDockDragSource.IsDockStateValid(DockState dockState)
1217        {
1218            return IsDockStateValid(dockState);
1219        }
1220
1221        bool IDockDragSource.CanDockTo(DockPane pane)
1222        {
1223            if (!IsDockStateValid(pane.DockState))
1224                return false;
1225
1226            if (pane == this)
1227                return false;
1228
1229            return true;
1230        }
1231
1232        Rectangle IDockDragSource.BeginDrag(Point ptMouse)
1233        {
1234            Point location = PointToScreen(new Point(0, 0));
1235            Size size;
1236
1237            DockPane floatPane = ActiveContent.DockHandler.FloatPane;
1238            if (DockState == DockState.Float || floatPane == null || floatPane.FloatWindow.NestedPanes.Count != 1)
1239                size = DockPanel.DefaultFloatWindowSize;
1240            else
1241                size = floatPane.FloatWindow.Size;
1242
1243            if (ptMouse.X > location.X + size.Width)
1244                location.X += ptMouse.X - (location.X + size.Width) + Measures.SplitterSize;
1245
1246            return new Rectangle(location, size);
1247        }
1248
1249        void IDockDragSource.EndDrag()
1250        {
1251        }
1252
1253        public void FloatAt(Rectangle floatWindowBounds)
1254        {
1255            if (FloatWindow == null || FloatWindow.NestedPanes.Count != 1)
1256                FloatWindow = DockPanel.FloatWindowFactory.CreateFloatWindow(DockPanel, this, floatWindowBounds);
1257            else
1258                FloatWindow.Bounds = floatWindowBounds;
1259
1260            DockState = DockState.Float;
1261
1262            NestedDockingStatus.NestedPanes.SwitchPaneWithFirstChild(this);
1263        }
1264
1265        public void DockTo(DockPane pane, DockStyle dockStyle, int contentIndex)
1266        {
1267            if (dockStyle == DockStyle.Fill)
1268            {
1269                IDockContent activeContent = ActiveContent;
1270                for (int i = Contents.Count - 1; i >= 0; i--)
1271                {
1272                    IDockContent c = Contents[i];
1273                    if (c.DockHandler.DockState == DockState)
1274                    {
1275                        c.DockHandler.Pane = pane;
1276                        if (contentIndex != -1)
1277                            pane.SetContentIndex(c, contentIndex);
1278                    }
1279                }
1280                pane.ActiveContent = activeContent;
1281            }
1282            else
1283            {
1284                if (dockStyle == DockStyle.Left)
1285                    DockTo(pane.NestedPanesContainer, pane, DockAlignment.Left, 0.5);
1286                else if (dockStyle == DockStyle.Right)
1287                    DockTo(pane.NestedPanesContainer, pane, DockAlignment.Right, 0.5);
1288                else if (dockStyle == DockStyle.Top)
1289                    DockTo(pane.NestedPanesContainer, pane, DockAlignment.Top, 0.5);
1290                else if (dockStyle == DockStyle.Bottom)
1291                    DockTo(pane.NestedPanesContainer, pane, DockAlignment.Bottom, 0.5);
1292
1293                DockState = pane.DockState;
1294            }
1295        }
1296
1297        public void DockTo(DockPanel panel, DockStyle dockStyle)
1298        {
1299            if (panel != DockPanel)
1300                throw new ArgumentException(Strings.IDockDragSource_DockTo_InvalidPanel, "panel");
1301
1302            if (dockStyle == DockStyle.Top)
1303                DockState = DockState.DockTop;
1304            else if (dockStyle == DockStyle.Bottom)
1305                DockState = DockState.DockBottom;
1306            else if (dockStyle == DockStyle.Left)
1307                DockState = DockState.DockLeft;
1308            else if (dockStyle == DockStyle.Right)
1309                DockState = DockState.DockRight;
1310            else if (dockStyle == DockStyle.Fill)
1311                DockState = DockState.Document;
1312        }
1313
1314        #endregion
1315    }
1316}
Note: See TracBrowser for help on using the repository browser.