~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockContainer.cs

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
34
34
using System.Collections.Generic;
35
35
using Gtk;
36
36
using Gdk;
 
37
using System.Linq;
 
38
using MonoDevelop.Ide.Gui;
37
39
 
38
40
namespace MonoDevelop.Components.Docking
39
41
{
40
 
        class DockContainer: Container, IShadedWidget
 
42
        class DockContainer: Container
41
43
        {
42
44
                DockLayout layout;
43
45
                DockFrame frame;
44
46
                
45
47
                List<TabStrip> notebooks = new List<TabStrip> ();
46
48
                List<DockItem> items = new List<DockItem> ();
47
 
                
 
49
 
 
50
                List<SplitterWidget> splitters = new List<SplitterWidget> ();
 
51
 
48
52
                bool needsRelayout = true;
49
 
                
50
 
                DockGroup currentHandleGrp;
51
 
                int currentHandleIndex;
52
 
                bool dragging;
53
 
                int dragPos;
54
 
                int dragSize;
55
 
                
 
53
 
56
54
                PlaceholderWindow placeholderWindow;
57
 
                
58
 
                static Gdk.Cursor hresizeCursor = new Gdk.Cursor (CursorType.SbHDoubleArrow);
59
 
                static Gdk.Cursor vresizeCursor = new Gdk.Cursor (CursorType.SbVDoubleArrow);
 
55
                PadTitleWindow padTitleWindow;
60
56
                
61
57
                public DockContainer (DockFrame frame)
62
58
                {
64
60
                        
65
61
                        this.Events = EventMask.ButtonPressMask | EventMask.ButtonReleaseMask | EventMask.PointerMotionMask | EventMask.LeaveNotifyMask;
66
62
                        this.frame = frame;
67
 
                        frame.ShadedContainer.Add (this);
68
63
                }
69
64
 
70
65
                internal DockGroupItem FindDockGroupItem (string id)
91
86
 
92
87
                public void LoadLayout (DockLayout dl)
93
88
                {
 
89
                        HidePlaceholder ();
 
90
 
94
91
                        // Sticky items currently selected in notebooks will remain
95
92
                        // selected after switching the layout
96
93
                        List<DockItem> sickyOnTop = new List<DockItem> ();
150
147
                        LayoutWidgets ();
151
148
                        layout.Size = -1;
152
149
                        layout.SizeAllocate (rect);
 
150
 
 
151
                        usedSplitters = 0;
 
152
                        layout.DrawSeparators (Gdk.Rectangle.Zero, null, 0, DrawSeparatorOperation.Allocate, null);
 
153
                }
 
154
 
 
155
                int usedSplitters;
 
156
 
 
157
                internal void AllocateSplitter (DockGroup grp, int index, Gdk.Rectangle a)
 
158
                {
 
159
                        var s = splitters[usedSplitters++];
 
160
                        if (a.Height > a.Width) {
 
161
                                a.Width = 5;
 
162
                                a.X -= 2;
 
163
                        }
 
164
                        else {
 
165
                                a.Height = 5;
 
166
                                a.Y -= 2;
 
167
                        }
 
168
                        s.SizeAllocate (a);
 
169
                        s.Init (grp, index);
153
170
                }
154
171
                
155
172
                protected override void ForAll (bool include_internals, Gtk.Callback callback)
158
175
                        foreach (Widget w in notebooks)
159
176
                                widgets.Add (w);
160
177
                        foreach (DockItem it in items) {
161
 
                                if (it.HasWidget && it.Widget.Parent == this)
 
178
                                if (it.HasWidget && it.Widget.Parent == this) {
162
179
                                        widgets.Add (it.Widget);
 
180
                                        if (it.TitleTab.Parent == this)
 
181
                                                widgets.Add (it.TitleTab);
 
182
                                }
163
183
                        }
 
184
                        foreach (var s in splitters.Where (w => w.Parent != null))
 
185
                                widgets.Add (s);
 
186
 
164
187
                        foreach (Widget w in widgets)
165
188
                                callback (w);
166
189
                }
170
193
                        bool res = base.OnExposeEvent (evnt);
171
194
                        
172
195
                        if (layout != null) {
173
 
                                layout.Draw (evnt.Area, currentHandleGrp, currentHandleIndex);
 
196
                                layout.Draw (evnt.Area, null, 0);
174
197
                        }
175
198
                        return res;
176
199
                }
201
224
 
202
225
                public void RelayoutWidgets ()
203
226
                {
 
227
                        if (layout != null)
 
228
                                layout.AddRemoveWidgets ();
 
229
 
204
230
                        needsRelayout = true;
205
231
                        QueueResize ();
206
232
                }
228
254
                                        notebooks.Add (ts);
229
255
                                        ts.Parent = this;
230
256
                                }
 
257
                                frame.UpdateRegionStyle (grp);
 
258
                                ts.VisualStyle = grp.VisualStyle;
231
259
                                grp.UpdateNotebook (ts);
232
260
                        }
233
261
                        
239
267
                                ts.Unparent ();
240
268
                                ts.Destroy ();
241
269
                        }
242
 
                                
 
270
 
 
271
                        // Create and add the required splitters
 
272
 
 
273
                        int reqSpliters = CountRequiredSplitters (layout);
 
274
 
 
275
                        for (int n=0; n < splitters.Count; n++) {
 
276
                                var s = splitters [n];
 
277
                                if (s.Parent != null)
 
278
                                        Remove (s);
 
279
                        }
 
280
 
 
281
                        // Hide the splitters that are not required
 
282
 
 
283
                        for (int n=reqSpliters; n < splitters.Count; n++)
 
284
                                splitters[n].Hide ();
 
285
 
243
286
                        // Add widgets to the container
244
287
                        
245
288
                        layout.LayoutWidgets ();
246
 
                        NotifySeparatorsChanged ();
 
289
 
 
290
                        // Create and add the required splitters
 
291
 
 
292
                        for (int n=0; n < reqSpliters; n++) {
 
293
                                if (n < splitters.Count) {
 
294
                                        var s = splitters [n];
 
295
                                        if (!s.Visible)
 
296
                                                s.Show ();
 
297
                                        Add (s);
 
298
                                } else {
 
299
                                        var s = new SplitterWidget ();
 
300
                                        splitters.Add (s);
 
301
                                        s.Show ();
 
302
                                        Add (s);
 
303
                                }
 
304
                        }
247
305
                }
248
 
                
 
306
 
249
307
                void GetTabbedGroups (DockGroup grp, List<DockGroup> tabbedGroups)
250
308
                {
251
309
                        if (grp.Type == DockGroupType.Tabbed) {
263
321
                                }
264
322
                        }
265
323
                }
266
 
                
267
 
                protected override bool OnButtonPressEvent (Gdk.EventButton ev)
268
 
                {
269
 
                        if (currentHandleGrp != null) {
270
 
                                dragging = true;
271
 
                                dragPos = (currentHandleGrp.Type == DockGroupType.Horizontal) ? (int)ev.XRoot : (int)ev.YRoot;
272
 
                                DockObject obj = currentHandleGrp.VisibleObjects [currentHandleIndex];
273
 
                                dragSize = (currentHandleGrp.Type == DockGroupType.Horizontal) ? obj.Allocation.Width : obj.Allocation.Height;
274
 
                        }
275
 
                        return base.OnButtonPressEvent (ev);
276
 
                }
277
 
                
278
 
                protected override bool OnButtonReleaseEvent (Gdk.EventButton e)
279
 
                {
280
 
                        dragging = false;
281
 
                        return base.OnButtonReleaseEvent (e);
282
 
                }
283
 
                
284
 
                protected override bool OnMotionNotifyEvent (Gdk.EventMotion e)
285
 
                {
286
 
                        if (dragging) {
287
 
                                NotifySeparatorsChanged ();
288
 
                                int newpos = (currentHandleGrp.Type == DockGroupType.Horizontal) ? (int)e.XRoot : (int)e.YRoot;
289
 
                                if (newpos != dragPos) {
290
 
                                        int nsize = dragSize + (newpos - dragPos);
291
 
                                        currentHandleGrp.ResizeItem (currentHandleIndex, nsize);
292
 
                                        layout.DrawSeparators (Allocation, currentHandleGrp, currentHandleIndex, true, null);
293
 
                                }
294
 
                        }
295
 
                        else if (layout != null && placeholderWindow == null) {
296
 
                                int index;
297
 
                                DockGroup grp;
298
 
                                if (FindHandle (layout, (int)e.X, (int)e.Y, out grp, out index)) {
299
 
                                        if (currentHandleGrp != grp || currentHandleIndex != index) {
300
 
                                                if (grp.Type == DockGroupType.Horizontal)
301
 
                                                        this.GdkWindow.Cursor = hresizeCursor;
302
 
                                                else
303
 
                                                        this.GdkWindow.Cursor = vresizeCursor;
304
 
                                                currentHandleGrp = grp;
305
 
                                                currentHandleIndex = index;
306
 
                                                layout.DrawSeparators (Allocation, currentHandleGrp, currentHandleIndex, true, null);
307
 
                                        }
308
 
                                }
309
 
                                else if (currentHandleGrp != null) {
310
 
                                        ResetHandleHighlight ();
311
 
                                }
312
 
                        }
313
 
                        return base.OnMotionNotifyEvent (e);
314
 
                }
315
 
                
316
 
                void ResetHandleHighlight ()
317
 
                {
318
 
                        this.GdkWindow.Cursor = null;
319
 
                        currentHandleGrp = null;
320
 
                        currentHandleIndex = -1;
321
 
                        if (layout != null)
322
 
                                layout.DrawSeparators (Allocation, null, -1, true, null);
323
 
                }
324
 
                
325
 
                protected override bool OnLeaveNotifyEvent (EventCrossing evnt)
326
 
                {
327
 
                        if (!dragging && evnt.Mode != CrossingMode.Grab)
328
 
                                ResetHandleHighlight ();
329
 
                        return base.OnLeaveNotifyEvent (evnt);
330
 
                }
331
324
 
332
 
                
333
 
                bool FindHandle (DockGroup grp, int x, int y, out DockGroup foundGrp, out int objectIndex)
 
325
                int CountRequiredSplitters (DockGroup grp)
334
326
                {
335
 
                        if (grp.Type != DockGroupType.Tabbed && grp.Allocation.Contains (x, y)) {
336
 
                                for (int n=0; n<grp.VisibleObjects.Count; n++) {
337
 
                                        DockObject obj = grp.VisibleObjects [n];
338
 
                                        if (n < grp.Objects.Count - 1) {
339
 
                                                if ((grp.Type == DockGroupType.Horizontal && x > obj.Allocation.Right && x < obj.Allocation.Right + frame.TotalHandleSize) ||
340
 
                                                    (grp.Type == DockGroupType.Vertical && y > obj.Allocation.Bottom && y < obj.Allocation.Bottom + frame.TotalHandleSize))
341
 
                                                {
342
 
                                                        foundGrp = grp;
343
 
                                                        objectIndex = n;
344
 
                                                        return true;
345
 
                                                }
346
 
                                        }
347
 
                                        if (obj is DockGroup) {
348
 
                                                if (FindHandle ((DockGroup) obj, x, y, out foundGrp, out objectIndex))
349
 
                                                        return true;
350
 
                                        }
351
 
                                }
 
327
                        if (grp.Type == DockGroupType.Tabbed)
 
328
                                return 0;
 
329
                        else {
 
330
                                int num = grp.VisibleObjects.Count - 1;
 
331
                                if (num < 0)
 
332
                                        return 0;
 
333
                                foreach (var c in grp.VisibleObjects.OfType<DockGroup> ())
 
334
                                        num += CountRequiredSplitters (c);
 
335
                                return num;
352
336
                        }
353
 
                        
354
 
                        foundGrp = null;
355
 
                        objectIndex = 0;
356
 
                        return false;
357
337
                }
358
338
                
359
339
                protected override void OnRealized ()
388
368
                        this.WidgetFlags &= ~WidgetFlags.NoWindow;
389
369
                        
390
370
                        //GdkWindow.SetBackPixmap (null, true);
 
371
 
 
372
                        ModifyBase (StateType.Normal, Styles.DockFrameBackground);
391
373
                }
392
374
                
393
375
                protected override void OnUnrealized ()
400
382
                        base.OnUnrealized ();
401
383
                }
402
384
                
403
 
                internal void ShowPlaceholder ()
 
385
                internal void ShowPlaceholder (DockItem draggedItem)
404
386
                {
 
387
                        padTitleWindow = new PadTitleWindow (frame, draggedItem);
405
388
                        placeholderWindow = new PlaceholderWindow (frame);
406
389
                }
407
390
                
415
398
                        
416
399
                        placeholderWindow.AllowDocking = allowDocking;
417
400
                        
 
401
                        int ox, oy;
 
402
                        GdkWindow.GetOrigin (out ox, out oy);
 
403
 
 
404
                        int tw, th;
 
405
                        padTitleWindow.GetSize (out tw, out th);
 
406
                        padTitleWindow.Move (ox + px - tw/2, oy + py - th/2);
 
407
                        padTitleWindow.GdkWindow.KeepAbove = true;
 
408
 
418
409
                        DockDelegate dockDelegate;
419
410
                        Gdk.Rectangle rect;
420
411
                        if (allowDocking && layout.GetDockTarget (item, px, py, out dockDelegate, out rect)) {
421
 
                                int ox, oy;
422
 
                                GdkWindow.GetOrigin (out ox, out oy);
423
 
                                
424
412
                                placeholderWindow.Relocate (ox + rect.X, oy + rect.Y, rect.Width, rect.Height, true);
425
413
                                placeholderWindow.Show ();
 
414
                                placeholderWindow.SetDockInfo (dockDelegate, rect);
426
415
                                return true;
427
416
                        } else {
428
 
                                int ox, oy;
429
 
                                GdkWindow.GetOrigin (out ox, out oy);
430
 
                                placeholderWindow.Relocate (ox + px - size.Width / 2, oy + py - 18, size.Width, size.Height, false);
 
417
                                int w,h;
 
418
                                var gi = layout.FindDockGroupItem (item.Id);
 
419
                                if (gi != null) {
 
420
                                        w = gi.Allocation.Width;
 
421
                                        h = gi.Allocation.Height;
 
422
                                } else {
 
423
                                        w = item.DefaultWidth;
 
424
                                        h = item.DefaultHeight;
 
425
                                }
 
426
                                placeholderWindow.Relocate (ox + px - w / 2, oy + py - h / 2, w, h, false);
431
427
                                placeholderWindow.Show ();
 
428
                                placeholderWindow.AllowDocking = false;
432
429
                        }
 
430
 
433
431
                        return false;
434
432
                }
435
433
                
438
436
                        if (placeholderWindow == null || !placeholderWindow.Visible)
439
437
                                return;
440
438
                        
441
 
                        item.Status = DockItemStatus.Dockable;
442
 
                        
443
 
                        int px, py;
444
 
                        GetPointer (out px, out py);
445
 
                        
446
 
                        DockDelegate dockDelegate;
447
 
                        Gdk.Rectangle rect;
448
 
                        if (placeholderWindow.AllowDocking && layout.GetDockTarget (item, px, py, out dockDelegate, out rect)) {
 
439
                        if (placeholderWindow.AllowDocking && placeholderWindow.DockDelegate != null) {
 
440
                                item.Status = DockItemStatus.Dockable;
449
441
                                DockGroupItem dummyItem = new DockGroupItem (frame, new DockItem (frame, "__dummy"));
450
442
                                DockGroupItem gitem = layout.FindDockGroupItem (item.Id);
451
443
                                gitem.ParentGroup.ReplaceItem (gitem, dummyItem);
452
 
                                dockDelegate (item);
 
444
                                placeholderWindow.DockDelegate (item);
453
445
                                dummyItem.ParentGroup.Remove (dummyItem);
454
446
                                RelayoutWidgets ();
455
447
                        } else {
 
448
                                int px, py;
 
449
                                GetPointer (out px, out py);
456
450
                                DockGroupItem gi = FindDockGroupItem (item.Id);
457
451
                                int pw, ph;
458
452
                                placeholderWindow.GetPosition (out px, out py);
468
462
                                placeholderWindow.Destroy ();
469
463
                                placeholderWindow = null;
470
464
                        }
471
 
                }
472
 
                
473
 
                public IEnumerable<Rectangle> GetShadedAreas ()
474
 
                {
475
 
                        List<Gdk.Rectangle> rects = new List<Gdk.Rectangle> ();
476
 
                        if (layout != null)
477
 
                                layout.DrawSeparators (Allocation, currentHandleGrp, currentHandleIndex, true, rects);
478
 
                        return rects;
479
 
                }
480
 
                
481
 
                internal void NotifySeparatorsChanged ()
482
 
                {
483
 
                        if (AreasChanged != null)
484
 
                                AreasChanged (this, EventArgs.Empty);
485
 
                }
486
 
                
487
 
                public event EventHandler AreasChanged;
488
 
 
 
465
                        if (padTitleWindow != null) {
 
466
                                padTitleWindow.Destroy ();
 
467
                                padTitleWindow = null;
 
468
                        }
 
469
                }
 
470
                
 
471
                internal class SplitterWidget: EventBox
 
472
                {
 
473
                        static Gdk.Cursor hresizeCursor = new Gdk.Cursor (CursorType.SbHDoubleArrow);
 
474
                        static Gdk.Cursor vresizeCursor = new Gdk.Cursor (CursorType.SbVDoubleArrow);
 
475
 
 
476
                        bool dragging;
 
477
                        int dragPos;
 
478
                        int dragSize;
 
479
 
 
480
                        DockGroup dockGroup;
 
481
                        int dockIndex;
 
482
        
 
483
                        public SplitterWidget ()
 
484
                        {
 
485
                                this.VisibleWindow = false;
 
486
                                this.AboveChild = true;
 
487
                        }
 
488
 
 
489
                        public void Init (DockGroup grp, int index)
 
490
                        {
 
491
                                dockGroup = grp;
 
492
                                dockIndex = index;
 
493
                        }
 
494
 
 
495
                        protected override void OnSizeAllocated (Rectangle allocation)
 
496
                        {
 
497
                                base.OnSizeAllocated (allocation);
 
498
                        }
 
499
 
 
500
                        protected override void OnRealized ()
 
501
                        {
 
502
                                base.OnRealized ();
 
503
 
 
504
                                // For testing purposes. Not being shown while VisibleWindow = false
 
505
                                ModifyBg (StateType.Normal, new Gdk.Color (255,0,0));
 
506
                                ModifyBase (StateType.Normal, new Gdk.Color (255,0,0));
 
507
                                ModifyFg (StateType.Normal, new Gdk.Color (255,0,0));
 
508
                        }
 
509
 
 
510
                        protected override bool OnEnterNotifyEvent (EventCrossing evnt)
 
511
                        {
 
512
                                if (Allocation.Height > Allocation.Width)
 
513
                                        GdkWindow.Cursor = hresizeCursor;
 
514
                                else
 
515
                                        GdkWindow.Cursor = vresizeCursor;
 
516
                                return base.OnEnterNotifyEvent (evnt);
 
517
                        }
 
518
 
 
519
                        protected override bool OnLeaveNotifyEvent (EventCrossing evnt)
 
520
                        {
 
521
                                GdkWindow.Cursor = null;
 
522
                                return base.OnLeaveNotifyEvent (evnt);
 
523
                        }
 
524
 
 
525
                        protected override bool OnButtonPressEvent (Gdk.EventButton ev)
 
526
                        {
 
527
                                dragging = true;
 
528
                                dragPos = (dockGroup.Type == DockGroupType.Horizontal) ? (int)ev.XRoot : (int)ev.YRoot;
 
529
                                DockObject obj = dockGroup.VisibleObjects [dockIndex];
 
530
                                dragSize = (dockGroup.Type == DockGroupType.Horizontal) ? obj.Allocation.Width : obj.Allocation.Height;
 
531
                                return base.OnButtonPressEvent (ev);
 
532
                        }
 
533
                        
 
534
                        protected override bool OnButtonReleaseEvent (Gdk.EventButton e)
 
535
                        {
 
536
                                dragging = false;
 
537
                                return base.OnButtonReleaseEvent (e);
 
538
                        }
 
539
                        
 
540
                        protected override bool OnMotionNotifyEvent (Gdk.EventMotion e)
 
541
                        {
 
542
                                if (dragging) {
 
543
                                        int newpos = (dockGroup.Type == DockGroupType.Horizontal) ? (int)e.XRoot : (int)e.YRoot;
 
544
                                        if (newpos != dragPos) {
 
545
                                                int nsize = dragSize + (newpos - dragPos);
 
546
                                                dockGroup.ResizeItem (dockIndex, nsize);
 
547
                                        }
 
548
                                }
 
549
                                return base.OnMotionNotifyEvent (e);
 
550
                        }
 
551
                }
 
552
        }
 
553
 
 
554
        enum DrawSeparatorOperation
 
555
        {
 
556
                Draw,
 
557
                Invalidate,
 
558
                Allocate,
 
559
                CollectAreas
489
560
        }
490
561
}