34
34
using System.Collections.Generic;
38
using MonoDevelop.Ide.Gui;
38
40
namespace MonoDevelop.Components.Docking
40
class DockContainer: Container, IShadedWidget
42
class DockContainer: Container
45
47
List<TabStrip> notebooks = new List<TabStrip> ();
46
48
List<DockItem> items = new List<DockItem> ();
50
List<SplitterWidget> splitters = new List<SplitterWidget> ();
48
52
bool needsRelayout = true;
50
DockGroup currentHandleGrp;
51
int currentHandleIndex;
56
54
PlaceholderWindow placeholderWindow;
58
static Gdk.Cursor hresizeCursor = new Gdk.Cursor (CursorType.SbHDoubleArrow);
59
static Gdk.Cursor vresizeCursor = new Gdk.Cursor (CursorType.SbVDoubleArrow);
55
PadTitleWindow padTitleWindow;
61
57
public DockContainer (DockFrame frame)
150
147
LayoutWidgets ();
151
148
layout.Size = -1;
152
149
layout.SizeAllocate (rect);
152
layout.DrawSeparators (Gdk.Rectangle.Zero, null, 0, DrawSeparatorOperation.Allocate, null);
157
internal void AllocateSplitter (DockGroup grp, int index, Gdk.Rectangle a)
159
var s = splitters[usedSplitters++];
160
if (a.Height > a.Width) {
155
172
protected override void ForAll (bool include_internals, Gtk.Callback callback)
271
// Create and add the required splitters
273
int reqSpliters = CountRequiredSplitters (layout);
275
for (int n=0; n < splitters.Count; n++) {
276
var s = splitters [n];
277
if (s.Parent != null)
281
// Hide the splitters that are not required
283
for (int n=reqSpliters; n < splitters.Count; n++)
284
splitters[n].Hide ();
243
286
// Add widgets to the container
245
288
layout.LayoutWidgets ();
246
NotifySeparatorsChanged ();
290
// Create and add the required splitters
292
for (int n=0; n < reqSpliters; n++) {
293
if (n < splitters.Count) {
294
var s = splitters [n];
299
var s = new SplitterWidget ();
249
307
void GetTabbedGroups (DockGroup grp, List<DockGroup> tabbedGroups)
251
309
if (grp.Type == DockGroupType.Tabbed) {
267
protected override bool OnButtonPressEvent (Gdk.EventButton ev)
269
if (currentHandleGrp != null) {
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;
275
return base.OnButtonPressEvent (ev);
278
protected override bool OnButtonReleaseEvent (Gdk.EventButton e)
281
return base.OnButtonReleaseEvent (e);
284
protected override bool OnMotionNotifyEvent (Gdk.EventMotion e)
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);
295
else if (layout != null && placeholderWindow == null) {
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;
303
this.GdkWindow.Cursor = vresizeCursor;
304
currentHandleGrp = grp;
305
currentHandleIndex = index;
306
layout.DrawSeparators (Allocation, currentHandleGrp, currentHandleIndex, true, null);
309
else if (currentHandleGrp != null) {
310
ResetHandleHighlight ();
313
return base.OnMotionNotifyEvent (e);
316
void ResetHandleHighlight ()
318
this.GdkWindow.Cursor = null;
319
currentHandleGrp = null;
320
currentHandleIndex = -1;
322
layout.DrawSeparators (Allocation, null, -1, true, null);
325
protected override bool OnLeaveNotifyEvent (EventCrossing evnt)
327
if (!dragging && evnt.Mode != CrossingMode.Grab)
328
ResetHandleHighlight ();
329
return base.OnLeaveNotifyEvent (evnt);
333
bool FindHandle (DockGroup grp, int x, int y, out DockGroup foundGrp, out int objectIndex)
325
int CountRequiredSplitters (DockGroup grp)
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))
347
if (obj is DockGroup) {
348
if (FindHandle ((DockGroup) obj, x, y, out foundGrp, out objectIndex))
327
if (grp.Type == DockGroupType.Tabbed)
330
int num = grp.VisibleObjects.Count - 1;
333
foreach (var c in grp.VisibleObjects.OfType<DockGroup> ())
334
num += CountRequiredSplitters (c);
359
339
protected override void OnRealized ()
416
399
placeholderWindow.AllowDocking = allowDocking;
402
GdkWindow.GetOrigin (out ox, out oy);
405
padTitleWindow.GetSize (out tw, out th);
406
padTitleWindow.Move (ox + px - tw/2, oy + py - th/2);
407
padTitleWindow.GdkWindow.KeepAbove = true;
418
409
DockDelegate dockDelegate;
419
410
Gdk.Rectangle rect;
420
411
if (allowDocking && layout.GetDockTarget (item, px, py, out dockDelegate, out rect)) {
422
GdkWindow.GetOrigin (out ox, out oy);
424
412
placeholderWindow.Relocate (ox + rect.X, oy + rect.Y, rect.Width, rect.Height, true);
425
413
placeholderWindow.Show ();
414
placeholderWindow.SetDockInfo (dockDelegate, rect);
429
GdkWindow.GetOrigin (out ox, out oy);
430
placeholderWindow.Relocate (ox + px - size.Width / 2, oy + py - 18, size.Width, size.Height, false);
418
var gi = layout.FindDockGroupItem (item.Id);
420
w = gi.Allocation.Width;
421
h = gi.Allocation.Height;
423
w = item.DefaultWidth;
424
h = item.DefaultHeight;
426
placeholderWindow.Relocate (ox + px - w / 2, oy + py - h / 2, w, h, false);
431
427
placeholderWindow.Show ();
428
placeholderWindow.AllowDocking = false;
438
436
if (placeholderWindow == null || !placeholderWindow.Visible)
441
item.Status = DockItemStatus.Dockable;
444
GetPointer (out px, out py);
446
DockDelegate dockDelegate;
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);
444
placeholderWindow.DockDelegate (item);
453
445
dummyItem.ParentGroup.Remove (dummyItem);
454
446
RelayoutWidgets ();
449
GetPointer (out px, out py);
456
450
DockGroupItem gi = FindDockGroupItem (item.Id);
458
452
placeholderWindow.GetPosition (out px, out py);
468
462
placeholderWindow.Destroy ();
469
463
placeholderWindow = null;
473
public IEnumerable<Rectangle> GetShadedAreas ()
475
List<Gdk.Rectangle> rects = new List<Gdk.Rectangle> ();
477
layout.DrawSeparators (Allocation, currentHandleGrp, currentHandleIndex, true, rects);
481
internal void NotifySeparatorsChanged ()
483
if (AreasChanged != null)
484
AreasChanged (this, EventArgs.Empty);
487
public event EventHandler AreasChanged;
465
if (padTitleWindow != null) {
466
padTitleWindow.Destroy ();
467
padTitleWindow = null;
471
internal class SplitterWidget: EventBox
473
static Gdk.Cursor hresizeCursor = new Gdk.Cursor (CursorType.SbHDoubleArrow);
474
static Gdk.Cursor vresizeCursor = new Gdk.Cursor (CursorType.SbVDoubleArrow);
483
public SplitterWidget ()
485
this.VisibleWindow = false;
486
this.AboveChild = true;
489
public void Init (DockGroup grp, int index)
495
protected override void OnSizeAllocated (Rectangle allocation)
497
base.OnSizeAllocated (allocation);
500
protected override void OnRealized ()
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));
510
protected override bool OnEnterNotifyEvent (EventCrossing evnt)
512
if (Allocation.Height > Allocation.Width)
513
GdkWindow.Cursor = hresizeCursor;
515
GdkWindow.Cursor = vresizeCursor;
516
return base.OnEnterNotifyEvent (evnt);
519
protected override bool OnLeaveNotifyEvent (EventCrossing evnt)
521
GdkWindow.Cursor = null;
522
return base.OnLeaveNotifyEvent (evnt);
525
protected override bool OnButtonPressEvent (Gdk.EventButton ev)
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);
534
protected override bool OnButtonReleaseEvent (Gdk.EventButton e)
537
return base.OnButtonReleaseEvent (e);
540
protected override bool OnMotionNotifyEvent (Gdk.EventMotion e)
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);
549
return base.OnMotionNotifyEvent (e);
554
enum DrawSeparatorOperation