1
// SummonModeRenderer.cs
3
// Copyright (C) 2008 GNOME Do
5
// This program is free software: you can redistribute it and/or modify
6
// it under the terms of the GNU General Public License as published by
7
// the Free Software Foundation, either version 3 of the License, or
8
// (at your option) any later version.
10
// This program is distributed in the hope that it will be useful,
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
// GNU General Public License for more details.
15
// You should have received a copy of the GNU General Public License
16
// along with this program. If not, see <http://www.gnu.org/licenses/>.
20
using System.Collections.Generic;
21
using System.Diagnostics;
28
using Do.Interface.AnimationBase;
29
using Do.Interface.CairoUtils;
35
using Docky.Interface;
36
using Docky.Utilities;
38
namespace Docky.Interface.Painters
40
public class SummonModeRenderer : IDockPainter
42
const int IconSize = 16;
45
Gdk.Rectangle previous_area;
47
public event EventHandler<PaintNeededArgs> PaintNeeded;
49
public event EventHandler ShowRequested;
50
public event EventHandler HideRequested;
52
PixbufSurfaceCache LargeIconCache { get; set; }
53
TextRenderer TextUtility { get; set; }
56
get { return DockState.Instance; }
59
bool ShouldRenderButton {
61
return State.CurrentPane != Pane.Third && State [State.CurrentPane] != null && State [State.CurrentPane] is Item;
67
return (int) (DockPreferences.IconSize * 3.5);
71
public bool DoubleBuffer {
75
public bool Interruptable {
79
public int MinimumWidth {
83
public SummonModeRenderer ()
86
TextUtility = new TextRenderer (DockWindow.Window);
91
void RegisterEvents ()
93
DockPreferences.IconSizeChanged += HandleIconSizeChanged;
94
DockServices.DoInteropService.Summoned += HandleSummoned;
95
DockServices.DoInteropService.Vanished += HandleVanished;
96
DockState.Instance.StateChanged += HandleStateChanged;
99
void UnregisterEvents ()
101
DockPreferences.IconSizeChanged -= HandleIconSizeChanged;
102
DockServices.DoInteropService.Summoned -= HandleSummoned;
103
DockServices.DoInteropService.Vanished -= HandleVanished;
104
DockState.Instance.StateChanged -= HandleStateChanged;
107
void HandleStateChanged (object sender, EventArgs e)
109
if (PaintNeeded != null) {
111
PaintNeededArgs args;
112
if (DateTime.UtcNow - DockState.Instance.CurrentPaneTime < DockArea.BaseAnimationTime)
113
args = new PaintNeededArgs (DockArea.BaseAnimationTime);
115
args = new PaintNeededArgs ();
116
PaintNeeded (this, args);
120
void HandleVanished(object sender, EventArgs e)
122
if (HideRequested != null)
123
HideRequested (this, new EventArgs ());
126
void HandleSummoned(object sender, EventArgs e)
128
if (ShowRequested != null)
129
ShowRequested (this, new EventArgs ());
133
void HandleIconSizeChanged ()
135
if (LargeIconCache != null)
136
LargeIconCache.Dispose ();
137
LargeIconCache = null;
140
public void Clicked (Gdk.Rectangle dockArea, Gdk.Point cursor)
142
Gdk.Point center = GetButtonCenter (ref dockArea);
143
Gdk.Rectangle rect = new Gdk.Rectangle (center.X - IconSize / 2, center.Y - IconSize / 2, IconSize, IconSize);
144
if (rect.Contains (cursor) && State [State.CurrentPane] is Item) {
145
DockServices.ItemsService.AddItemToDock (State [State.CurrentPane]);
146
DockServices.DoInteropService.RequestClickOff ();
147
} else if (!dockArea.Contains (cursor)) {
148
DockServices.DoInteropService.RequestClickOff ();
152
public void Interrupt ()
154
Log.Error ("Docky has been interupted innapropriately. Please report this bug.");
157
Gdk.Point GetButtonCenter (ref Gdk.Rectangle dockArea)
159
return new Gdk.Point (dockArea.X + IconSize / 2 + 5, dockArea.Y + dockArea.Height - (IconSize / 2 + 5));
162
public void Paint (Context cr, Gdk.Rectangle dockArea, Gdk.Point cursor)
164
if (previous_area == dockArea &&
166
DateTime.UtcNow - DockState.Instance.CurrentPaneTime > DockArea.BaseAnimationTime) {
167
previous_area = dockArea;
170
previous_area = dockArea;
175
if (LargeIconCache == null)
176
LargeIconCache = new PixbufSurfaceCache (10, 2 * DockPreferences.IconSize, 2 * DockPreferences.IconSize, cr.Target);
178
for (int i=0; i<3; i++) {
182
GetXForPane (ref dockArea, pane, out left_x, out zoom);
184
if (pane == Pane.Third && !State.ThirdPaneVisible)
188
double opacity = .6 + zoom * .4;
189
switch (PaneDrawState (pane)) {
190
case DrawState.NoResult:
193
case DrawState.Normal:
194
icon = State[pane].Icon;
197
icon = "gnome-mime-text";
199
case DrawState.ExplicitText:
200
icon = "gnome-mime-text";
201
opacity = .2 * opacity;
210
if (!LargeIconCache.ContainsKey (icon))
211
LargeIconCache.AddPixbufSurface (icon, icon);
213
cr.Scale (zoom, zoom);
214
if (DockPreferences.Orientation == DockOrientation.Top) {
215
cr.SetSource (LargeIconCache.GetSurface (icon),
217
(dockArea.Y * (1 / zoom)));
219
cr.SetSource (LargeIconCache.GetSurface (icon),
221
((dockArea.Y + dockArea.Height) - (DockPreferences.IconSize * 2 * zoom) - 5) * (1 / zoom));
223
cr.PaintWithAlpha (opacity);
224
cr.Scale (1 / zoom, 1 / zoom);
227
switch (PaneDrawState (State.CurrentPane))
229
case DrawState.NoResult:
230
RenderText (cr, Catalog.GetString ("No result found for") + ": " + State.GetPaneQuery (State.CurrentPane), ref dockArea);
232
case DrawState.Normal:
233
RenderNormalText (cr, ref dockArea);
234
if (ShouldRenderButton)
235
RenderAddButton (cr, ref dockArea, ref cursor);
238
RenderTextModeText (cr, ref dockArea);
240
case DrawState.ExplicitText:
241
RenderExplicitText (cr, ref dockArea);
249
void RenderNormalText (Context cr, ref Gdk.Rectangle dockArea)
251
int base_x = dockArea.X + 30;
252
string text = GLib.Markup.EscapeText (State[State.CurrentPane].Name);
253
text = Do.Interface.Util.FormatCommonSubstrings (text, State.GetPaneQuery (State.CurrentPane), DockPreferences.HighlightFormat);
255
Pango.Color color = new Pango.Color ();
256
color.Blue = color.Red = color.Green = ushort.MaxValue;
258
double text_scale = (DockPreferences.IconSize / 64.0);
259
int small_text_height = (int) (12 * text_scale);
262
if (8 < small_text_height) {
263
big_text_height = (int) (20 * text_scale);
264
TextUtility.RenderLayoutText (cr, text, base_x + TextOffset,
265
dockArea.Y + (int) (15 * text_scale), dockArea.Width - TextOffset - 50,
266
big_text_height, color, Pango.Alignment.Left, Pango.EllipsizeMode.End);
268
TextUtility.RenderLayoutText (cr, GLib.Markup.EscapeText (State[State.CurrentPane].Description),
269
base_x + TextOffset, dockArea.Y + (int) (42 * text_scale),
270
dockArea.Width - TextOffset - 50, small_text_height, color,
271
Pango.Alignment.Left, Pango.EllipsizeMode.End);
275
big_text_height = (int) (35 * text_scale);
276
TextUtility.RenderLayoutText (cr, text, base_x + TextOffset,
277
dockArea.Y + dockArea.Height / 2 - 3 * big_text_height / 5, dockArea.Width - TextOffset - 50,
278
big_text_height, color, Pango.Alignment.Left, Pango.EllipsizeMode.End);
282
void RenderExplicitText (Context cr, ref Gdk.Rectangle dockArea)
284
int base_x = dockArea.X + 15;
287
Element current = State [State.CurrentPane];
290
text = State.GetPaneQuery (State.CurrentPane);
291
else if (current is ITextItem)
292
text = (current as ITextItem).Text;
296
if (string.IsNullOrEmpty (text))
299
text = GLib.Markup.EscapeText (text);
301
double text_scale = (DockPreferences.IconSize / 64.0);
302
int text_height = Math.Max (11, (int) (15 * text_scale));
304
Pango.Color color = new Pango.Color ();
305
color.Blue = color.Red = color.Green = ushort.MaxValue;
307
Gdk.Rectangle rect = TextUtility.RenderLayoutText (cr, text, base_x,
308
dockArea.Y + (int) (15 * text_scale),
309
(dockArea.X + dockArea.Width) - (base_x + 15), text_height,
310
color, Pango.Alignment.Left, Pango.EllipsizeMode.None);
312
cr.Rectangle (rect.X, rect.Y, 2, rect.Height);
313
cr.Color = new Cairo.Color (1, 1, 1);
317
void RenderTextModeText (Context cr, ref Gdk.Rectangle dockArea)
319
int base_x = dockArea.X + 15;
322
Element current = State [State.CurrentPane];
325
text = State.GetPaneQuery (State.CurrentPane);
326
else if (current is ITextItem)
327
text = (current as ITextItem).Text;
331
if (string.IsNullOrEmpty (text))
334
text = GLib.Markup.EscapeText (text);
336
double text_scale = (DockPreferences.IconSize / 64.0);
337
int text_height = Math.Max (11, (int) (15 * text_scale));
339
Pango.Color color = new Pango.Color ();
340
color.Blue = color.Red = color.Green = ushort.MaxValue;
342
TextUtility.RenderLayoutText (cr, text, base_x + TextOffset,
343
dockArea.Y + (int) (15 * text_scale), (dockArea.X + dockArea.Width) - (base_x + TextOffset + 40),
344
text_height, color, Pango.Alignment.Left, Pango.EllipsizeMode.None);
347
void RenderText (Context cr, string text, ref Gdk.Rectangle dockArea)
349
int base_x = dockArea.X + 15;
351
double text_scale = (DockPreferences.IconSize / 64.0);
353
int text_height = (int) (20 * text_scale);
355
Pango.Color color = new Pango.Color ();
356
color.Blue = color.Red = color.Green = ushort.MaxValue;
358
TextUtility.RenderLayoutText (cr, text, base_x + TextOffset,
359
dockArea.Y + (int) (15 * text_scale), (dockArea.X + dockArea.Width) - (base_x + TextOffset + 40),
360
text_height, color, Pango.Alignment.Left, Pango.EllipsizeMode.End);
363
void RenderAddButton (Context cr, ref Gdk.Rectangle dockArea, ref Gdk.Point cursor)
365
Gdk.Point buttonCenter = GetButtonCenter (ref dockArea);
367
int x = buttonCenter.X - IconSize / 2;
368
int y = buttonCenter.Y - IconSize / 2;
370
cr.SetRoundedRectanglePath (x, y, IconSize, IconSize, IconSize / 2);
373
cr.Color = new Cairo.Color (1, 1, 1);
376
cr.MoveTo (x + IconSize / 2, y + 4);
377
cr.LineTo (x + IconSize / 2, y + (IconSize - 4));
378
cr.MoveTo (x + 4, y + IconSize / 2);
379
cr.LineTo (x + (IconSize - 4), y + IconSize / 2);
383
void GetXForPane (ref Gdk.Rectangle dockArea, Pane pane, out int left_x, out double zoom)
385
int base_x = dockArea.X + 15;
386
double zoom_value = .3;
387
double slide_state = Math.Min (1, (DateTime.UtcNow - State.CurrentPaneTime).TotalMilliseconds / DockArea.BaseAnimationTime.TotalMilliseconds);
389
double growing_zoom = zoom_value + slide_state * (1 - zoom_value);
390
double shrinking_zoom = zoom_value + (1 - slide_state) * (1 - zoom_value);
394
if (State.CurrentPane == Pane.First && (State.PreviousPane == Pane.Second || State.PreviousPane == Pane.Third)) {
396
} else if (State.PreviousPane == Pane.First && (State.CurrentPane == Pane.Second || State.CurrentPane == Pane.Third)) {
397
zoom = shrinking_zoom;
403
if (State.PreviousPane == Pane.Second && State.CurrentPane == Pane.First) {
404
zoom = shrinking_zoom;
405
left_x = base_x + (int) ((DockPreferences.IconSize * 2) * (growing_zoom));
406
} else if (State.PreviousPane == Pane.Second && State.CurrentPane == Pane.Third) {
407
zoom = shrinking_zoom;
408
left_x = base_x + (int) (DockPreferences.IconSize * 2 * zoom_value);
409
} else if (State.PreviousPane == Pane.First && State.CurrentPane == Pane.Second) {
411
left_x = base_x + (int) ((DockPreferences.IconSize * 2) * (shrinking_zoom));
412
} else if (State.PreviousPane == Pane.First && State.CurrentPane == Pane.Third) {
414
left_x = base_x + (int) ((DockPreferences.IconSize * 2) * (shrinking_zoom));
415
} else if (State.PreviousPane == Pane.Third && State.CurrentPane == Pane.First) {
417
left_x = base_x + (int) ((DockPreferences.IconSize * 2) * (growing_zoom));
418
} else {// (State.PreviousPane == Pane.Third && State.CurrentPane == Pane.Second) {
420
left_x = base_x + (int) (DockPreferences.IconSize * 2 * zoom_value);
424
if (State.PreviousPane == Pane.Second && State.CurrentPane == Pane.First) {
426
left_x = base_x + (int) (DockPreferences.IconSize * 2 * (1 + zoom_value));
427
} else if (State.PreviousPane == Pane.Second && State.CurrentPane == Pane.Third) {
429
left_x = base_x + (int) (DockPreferences.IconSize * 2 * zoom_value) + (int) ((DockPreferences.IconSize * 2) * (shrinking_zoom));
430
} else if (State.PreviousPane == Pane.First && State.CurrentPane == Pane.Second) {
432
left_x = base_x + (int) (DockPreferences.IconSize * 2 * (1 + zoom_value));
433
} else if (State.PreviousPane == Pane.First && State.CurrentPane == Pane.Third) {
435
left_x = base_x + (int) (DockPreferences.IconSize * 2 * zoom_value) + (int) ((DockPreferences.IconSize * 2) * (shrinking_zoom));
436
} else if (State.PreviousPane == Pane.Third && State.CurrentPane == Pane.First) {
437
zoom = shrinking_zoom;
438
left_x = base_x + (int) (DockPreferences.IconSize * 2 * zoom_value) + (int) ((DockPreferences.IconSize * 2) * (growing_zoom));
439
} else {// (State.PreviousPane == Pane.Third && State.CurrentPane == Pane.Second) {
440
zoom = shrinking_zoom;
441
left_x = base_x + (int) (DockPreferences.IconSize * 2 * zoom_value) + (int) ((DockPreferences.IconSize * 2) * (growing_zoom));
445
double offset_scale = 1;
446
left_x = (int) (left_x * offset_scale + base_x * (1 - offset_scale));
449
DrawState PaneDrawState (Pane pane)
451
if (pane != State.CurrentPane && (State.GetTextModeType (State.CurrentPane) == TextModeType.Explicit))
452
return DrawState.None;
454
if (pane == Pane.Third && !State.ThirdPaneVisible)
455
return DrawState.None;
457
if (State.GetTextModeType (pane) == TextModeType.Explicit)
458
return DrawState.ExplicitText;
460
if (State.GetTextMode (pane))
461
return DrawState.Text;
463
if (State.GetPaneItem (pane) != null)
464
return DrawState.Normal;
466
if (!string.IsNullOrEmpty (State.GetPaneQuery (pane))) {
467
return DrawState.NoResult;
470
return DrawState.None;
473
public void Dispose ()
476
TextUtility.Dispose ();