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 |