~ubuntu-branches/ubuntu/saucy/monodevelop/saucy-proposed

10.2.6 by Jo Shields
Import upstream version 2.4+dfsg
1
//
2
// DockToolbar.cs
3
//
4
// Author:
5
//   Lluis Sanchez Gual
6
//
7
// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
8
//
9
// Permission is hereby granted, free of charge, to any person obtaining
10
// a copy of this software and associated documentation files (the
11
// "Software"), to deal in the Software without restriction, including
12
// without limitation the rights to use, copy, modify, merge, publish,
13
// distribute, sublicense, and/or sell copies of the Software, and to
14
// permit persons to whom the Software is furnished to do so, subject to
15
// the following conditions:
16
// 
17
// The above copyright notice and this permission notice shall be
18
// included in all copies or substantial portions of the Software.
19
// 
20
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
//
28
29
using System;
30
using System.Collections.Generic;
31
using Gtk;
32
using Gdk;
33
34
namespace MonoDevelop.Components.DockToolbars
35
{
36
	public class DockToolbar: Toolbar, IDockToolbar
37
	{
38
		DockGrip grip;
39
		DockToolbarFrame parentFrame;
40
		bool dragging;
41
		FloatingDock floatingDock;
42
		string id;
43
		string title;
44
		
45
		int row;
46
		int offset;
47
		int shiftOffset = -1;
48
		
49
		// Offset requested by the user. It is used to know where the
50
		// toolbar is expected to move when the window is expanded.
51
		int anchorOffset;	
52
		
53
		Animation animation;
54
		DockToolbarPosition lastPosition;
55
		DockToolbarStatus defaultStatus;
56
		
57
		int defaultSize;
58
		int defaultHeight;
59
		bool gotSize = false;
60
		bool gettingSize;
61
		Dictionary<Gtk.Widget,int> calculatedSizes = new Dictionary<Gtk.Widget, int> ();
62
		
63
		public DockToolbar (string id, string title)
64
		{
65
			grip = new DockGrip ();
66
			Add (grip);
67
			grip.Hide ();
68
			this.id = id;
69
			this.title = title;
70
			ShowArrow = false;
71
		}
72
		
73
		internal void SetParentFrame (DockToolbarFrame frame)
74
		{
75
			parentFrame = frame;
76
			grip.Show ();
77
		}
78
		
79
		public string Id {
80
			get { return id; }
81
		}
82
		
83
		public string Title {
84
			get { return title; }
85
		}
86
		
87
		public bool Floating {
88
			get { return floatingDock != null; }
89
		}
90
		
91
		bool IDockToolbar.Visible {
92
			get { return Parent != null; }
93
			set {
94
				if (value == ((IDockToolbar)this).Visible)
95
					return;
96
					
97
				if (value) {
98
					if (lastPosition != null)
99
						lastPosition.RestorePosition (parentFrame, this);
100
					else
101
						defaultStatus.Position.RestorePosition (parentFrame, this);
102
				} else {
103
					lastPosition = DockToolbarPosition.Create (this);
104
					if (Floating) {
105
						FloatingDock win = FloatingDock;
106
						win.Detach ();
107
						win.Destroy ();
108
					}
109
					else
110
						DockPanel.RemoveBar (this);
111
				}
112
			}
113
		}
114
		
115
		internal DockToolbarPosition Position {
116
			get {
117
				if (((IDockToolbar)this).Visible) return DockToolbarPosition.Create (this);
118
				else if (lastPosition != null) return lastPosition;
119
				else return defaultStatus.Position;
120
			}
121
		}
122
		
123
		internal DockToolbarStatus Status {
124
			get {
125
				return new DockToolbarStatus (id, ((IDockToolbar)this).Visible, Position);
126
			}
127
			set {
128
				if (value.Visible) {
129
					((IDockToolbar)this).Visible = false;
130
					lastPosition = value.Position;
131
					((IDockToolbar)this).Visible = true;
132
				} else {
133
					((IDockToolbar)this).Visible = false;
134
					lastPosition = value.Position;
135
				}
136
			}
137
			
138
		}
139
		
140
		internal DockToolbarStatus DefaultStatus {
141
			get { return defaultStatus; }
142
			set { defaultStatus = value; }
143
		}
144
		
145
		internal int DockRow {
146
			get { return row; }
147
			set { row = value; }
148
		}
149
		
150
		/// <summary>
151
		/// The current offset of the toolbar
152
		/// </summary>
153
		internal int DockOffset {
154
			get { return offset; }
155
			set { offset = value; }
156
		}
157
		
158
		internal int DockShiftOffset {
159
			get { return shiftOffset; }
160
			set { shiftOffset = value; }
161
		}
162
		
163
		/// <summary>
164
		/// The ideal offset of the toolbar. It may not be the real offset if the
165
		/// toolbar has been forced to move to make room for other toolbars
166
		/// </summary>
167
		internal int AnchorOffset {
168
			get { return anchorOffset; }
169
			set { anchorOffset = value; }
170
		}
171
		
172
		internal int DefaultSize {
173
			get {
174
				if (!gotSize) CalcSizes ();
175
				return defaultSize;
176
			}
177
		}
178
		
179
		public int DefaultHeight {
180
			get {
181
				if (!gotSize) CalcSizes ();
182
				return defaultHeight;
183
			}
184
		}
185
		
186
		internal void CalcSizes ()
187
		{
188
			// Calculates the real size of the toolbar. ShowArrow=false is
189
			// needed, since SizeRequest reports 0 size requested if not.
190
			
191
			gettingSize = true;
192
			bool olda = ShowArrow;
193
			int oldw = WidthRequest;
194
			int oldh = HeightRequest;
195
			WidthRequest = -1;
196
			HeightRequest = -1;
197
			
198
			ShowArrow = false;
199
			Requisition r = SizeRequest ();
200
			if (Orientation == Orientation.Horizontal) {
201
				defaultSize = r.Width;
202
				defaultHeight = r.Height;
203
			}
204
			else {
205
				defaultSize = r.Height;
206
				defaultHeight = r.Width;
207
			}
208
		
209
			calculatedSizes.Clear ();
210
			foreach (Widget w in Children) {
211
				if (!w.Visible)
212
					continue;
213
				if (Orientation == Orientation.Horizontal)
214
					calculatedSizes [w] = w.Allocation.Width;
215
				else
216
					calculatedSizes [w] = w.Allocation.Height;
217
			}
218
			
219
			WidthRequest = oldw;
220
			HeightRequest = oldh;
221
			ShowArrow = olda;
222
			gotSize = true;
223
			gettingSize = false;
224
		}
225
		
226
		internal bool CanDockTo (DockToolbarPanel panel)
227
		{
228
			return true;
229
		}
230
		
231
		internal FloatingDock FloatingDock {
232
			get { return floatingDock; }
233
			set { floatingDock = value; }
234
		}
235
		
236
		internal DockToolbarPanel DockPanel {
237
			get { return Parent as DockToolbarPanel; }
238
		}
239
		
240
		internal Animation Animation {
241
			get { return animation; }
242
			set { animation = value; }
243
		}
244
		
245
		protected override bool OnButtonPressEvent (EventButton e)
246
		{
247
			if (parentFrame != null && e.Button == 1) {
248
				if (Orientation == Orientation.Horizontal && e.X <= 10) {
249
					dragging = true;
250
					parentFrame.StartDragBar (this, (int)e.X, (int)e.Y, e.Time);
251
					return true;
252
				}
253
				else if (Orientation == Orientation.Vertical && e.Y <= 10) {
254
					dragging = true;
255
					parentFrame.StartDragBar (this, (int)e.X, (int)e.Y, e.Time);
256
					return true;
257
				}
258
			}
259
			return base.OnButtonPressEvent (e);
260
		}
261
		
262
		protected override bool OnButtonReleaseEvent (EventButton e)
263
		{
264
			if (e.Button == 1 && dragging) {
265
				dragging = false;
266
				parentFrame.EndDragBar (this, e.Time);
267
			}
268
			return base.OnButtonReleaseEvent (e);
269
		}
270
		
271
/*		protected override bool OnExposeEvent (EventExpose evnt)
272
		{
273
			//use the base class to paint the background like a toolbar, which may be a gradient
274
			// but only if horizontal, else the gradient usually looks really ugly
275
			if (this.Orientation == Orientation.Horizontal){
276
				//the WIMP theme engine's rendering is a bit off, need to force it to render wider
277
				int widen = MonoDevelop.Core.PropertyService.IsWindows? 1 : 0;
278
				
279
				var shadowType = (ShadowType)StyleGetProperty ("shadow-type");
280
				Style.PaintBox (Style, evnt.Window, State, shadowType, evnt.Area, this, "toolbar", 
281
				                Allocation.X - widen, Allocation.Y, Allocation.Width + widen + widen, Allocation.Height);
282
			} else {
283
				//else we paint a plain flat background to make everything even - see DockToolbarPanel.OnExposeEvent
284
				GdkWindow.DrawRectangle (Style.BackgroundGC (State), true, Allocation);
285
			}
286
            
287
            foreach (Widget child in Children) {
288
                PropagateExpose (child, evnt);
289
            }
290
		
291
		    return true;
292
		}*/
293
		
294
		bool firstRealized;
295
		protected override void OnRealized ()
296
		{
297
			base.OnRealized ();
298
			if (!firstRealized) {
299
				OnItemChange (null, null);
300
				firstRealized = true;
301
			}
302
		}
303
304
305
		internal void ResetSize ()
306
		{
307
			WidthRequest = -1;
308
			HeightRequest = -1;
309
			ShowArrow = false;
310
		}
311
		
312
		public int Size {
313
			set {
314
				if (Orientation == Orientation.Horizontal) {
315
					if (value >= DefaultSize)
316
						WidthRequest = -1;
317
					else
318
						WidthRequest = value;
319
				}
320
				else {
321
					if (value >= DefaultSize)
322
						HeightRequest = -1;
323
					else
324
						HeightRequest = value;
325
					HeightRequest = value;
326
				}
327
			}
328
			get {
329
				if (Orientation == Orientation.Horizontal)
330
					return SizeRequest ().Width;
331
				else
332
					return SizeRequest ().Height;
333
			}
334
		}
335
		
336
		public new Orientation Orientation {
337
			get {
338
				return base.Orientation;
339
			}
340
			set {
341
				if (value == base.Orientation)
342
					return;
343
				
344
				if (FloatingDock != null) {
345
					// I create a new dock window because resizing the
346
					// current one has lots of issues (mainly synchronization
347
					// problems between the size change of the window and
348
					// the toolbar).
349
					
350
					int x,y;
351
					FloatingDock w = FloatingDock;
352
					w.GetPosition (out x, out y);
353
					w.Detach ();
354
					
355
					base.Orientation = value;
356
					
357
					FloatingDock fdock = new FloatingDock (parentFrame);
358
					fdock.Move (x, y);
359
					fdock.Attach (this);
360
					w.Destroy ();
361
				} else
362
					base.Orientation = value;
363
				gotSize = false;
364
			}
365
		}
366
		
367
		protected override void OnAdded (Widget w)
368
		{
369
			base.OnAdded (w);
370
			gotSize = false;
371
			if (DefaultSizeChanged != null)
372
				DefaultSizeChanged (this, EventArgs.Empty);
373
			w.Shown += OnItemChange;
374
			w.Hidden += OnItemChange;
375
			w.SizeAllocated += OnItemSizeChange;
376
		}
377
378
		protected override void OnRemoved (Widget w)
379
		{
380
			base.OnRemoved (w);
381
			gotSize = false;
382
			if (DefaultSizeChanged != null)
383
				DefaultSizeChanged (this, EventArgs.Empty);
384
			w.Shown -= OnItemChange;
385
			w.Hidden -= OnItemChange;
386
			w.SizeAllocated -= OnItemSizeChange;
387
		}
388
		
389
		void OnItemSizeChange (object o, SizeAllocatedArgs args)
390
		{
391
			if (gettingSize || !gotSize)
392
				return;
393
			int os;
394
			if (calculatedSizes.TryGetValue ((Gtk.Widget) o, out os)) {
395
				int ns = (Orientation == Orientation.Horizontal ? args.Allocation.Width : args.Allocation.Height);
396
				if (os != ns) {
397
					Gtk.Application.Invoke (delegate {
398
						OnItemChange (null, null);
399
					});
400
				}
401
			}
402
		}
403
		
404
		void OnItemChange (object o, EventArgs args)
405
		{
406
			// This notifies changes in the size of the toolbar
407
			gotSize = false;
408
			if (DefaultSizeChanged != null)
409
				DefaultSizeChanged (this, EventArgs.Empty);
410
		}
411
		
412
		internal event EventHandler DefaultSizeChanged;
413
	}
414
}
415