~and471/+junk/do-with-docky

« back to all changes in this revision

Viewing changes to Do.Interface.Linux.Docky/src/Docky.Interface/Docky.Interface.Items/AbstractDockItem.cs

  • Committer: rugby471 at gmail
  • Date: 2010-10-15 16:08:38 UTC
  • Revision ID: rugby471@gmail.com-20101015160838-z9m3utbf7bxzb5ty
reverted to before docky removal

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// AbstractDockItem.cs
 
2
// 
 
3
// Copyright (C) 2008 GNOME Do
 
4
//
 
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.
 
9
//
 
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.
 
14
//
 
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/>.
 
17
//
 
18
 
 
19
using System;
 
20
using System.Collections.Generic;
 
21
using System.Threading;
 
22
 
 
23
using Cairo;
 
24
using Gdk;
 
25
using Gtk;
 
26
 
 
27
using Do.Interface;
 
28
using Do.Interface.CairoUtils;
 
29
using Do.Interface.Wink;
 
30
using Do.Platform;
 
31
 
 
32
using Docky.Utilities;
 
33
 
 
34
namespace Docky.Interface
 
35
{
 
36
 
 
37
        
 
38
        public abstract class AbstractDockItem : IDisposable, IEquatable<AbstractDockItem>
 
39
        {
 
40
                public event UpdateRequestHandler UpdateNeeded;
 
41
                
 
42
                Surface text_surface, resize_buffer;
 
43
                DockOrientation current_orientation;
 
44
                uint size_changed_timer, redraw_timer;
 
45
                bool needs_attention;
 
46
                
 
47
                bool time_since_click_overdue;
 
48
                
 
49
                Cairo.Color? average_color;
 
50
                
 
51
                protected int current_size;
 
52
 
 
53
                protected virtual Surface IconSurface { get; set; }
 
54
                
 
55
                Surface SecondaryIconSurface { get; set; }
 
56
                
 
57
                public string Description { get; private set; }
 
58
                
 
59
                public bool Disposed { get; private set; }
 
60
                
 
61
                public Gdk.Rectangle TextSurfaceSize { get; private set; }
 
62
                
 
63
                /// <value>
 
64
                /// The currently requested animation type
 
65
                /// </value>
 
66
                public virtual ClickAnimationType AnimationType { get; protected set; }
 
67
 
 
68
                /// <value>
 
69
                /// The time at which the NeedsAttention flag was set true
 
70
                /// </value>
 
71
                public virtual DateTime AttentionRequestStartTime { get; protected set; }
 
72
 
 
73
                /// <value>
 
74
                /// When this item was added to the Dock
 
75
                /// </value>
 
76
                public virtual DateTime DockAddItem { get; set; }
 
77
 
 
78
                /// <value>
 
79
                /// The last time this icon was "clicked" that required an animation
 
80
                /// </value>
 
81
                public virtual DateTime LastClick { get; private set; }
 
82
                
 
83
                public int Position { get; set; }
 
84
                
 
85
                public virtual bool ContainsFocusedWindow {
 
86
                        get { return false; }
 
87
                }
 
88
                
 
89
                public virtual bool ContainsMinimizedWindow {
 
90
                        get { return false; }
 
91
                }
 
92
 
 
93
                /// <value>
 
94
                /// Determines if drop actions will be passed on to the icon
 
95
                /// </value>
 
96
                public virtual bool IsAcceptingDrops { 
 
97
                        get { return false; } 
 
98
                }
 
99
                
 
100
                /// <value>
 
101
                /// Determines the type of indicator drawn under the item
 
102
                /// </value>
 
103
                public virtual bool NeedsAttention { 
 
104
                        get {
 
105
                                return needs_attention;
 
106
                        }
 
107
                        protected set {
 
108
                                if (value == needs_attention)
 
109
                                        return;
 
110
                                needs_attention = value;
 
111
                                if (needs_attention)
 
112
                                        AttentionRequestStartTime = DateTime.UtcNow;
 
113
                        }
 
114
                }
 
115
                
 
116
                /// <value>
 
117
                /// The Widget of the icon.
 
118
                /// </value>
 
119
                public virtual int Width {
 
120
                        get { return DockPreferences.IconSize; }
 
121
                }
 
122
                
 
123
                /// <value>
 
124
                /// The Height of the icon.
 
125
                /// </value>
 
126
                public virtual int Height {
 
127
                        get { return DockPreferences.IconSize; }
 
128
                }
 
129
                
 
130
                public virtual ScalingType ScalingType {
 
131
                        get { return ScalingType.Downscaled; }
 
132
                }
 
133
                
 
134
                protected virtual string Icon {
 
135
                        get { return null; }
 
136
                }
 
137
                
 
138
                /// <value>
 
139
                /// Whether or not to draw an application present indicator
 
140
                /// </value>
 
141
                public virtual int WindowCount {
 
142
                        get { return 0; }
 
143
                }
 
144
                
 
145
                public TimeSpan TimeSinceClick {
 
146
                        get { 
 
147
                                if (time_since_click_overdue)
 
148
                                        return new TimeSpan (1, 0, 0);
 
149
                                
 
150
                                TimeSpan result = DockArea.RenderTime - LastClick;
 
151
                                
 
152
                                if (result.TotalMilliseconds > 1000)
 
153
                                        time_since_click_overdue = true;
 
154
                                
 
155
                                return result;
 
156
                        }
 
157
                }
 
158
                
 
159
                public TimeSpan TimeSinceAdd {
 
160
                        get { return DockArea.RenderTime - DockAddItem; }
 
161
                }
 
162
                
 
163
                public AbstractDockItem ()
 
164
                {
 
165
                        NeedsAttention = false;
 
166
                        Description = "";
 
167
                        AttentionRequestStartTime = LastClick = new DateTime (0);
 
168
                        
 
169
                        DockPreferences.IconSizeChanged += OnIconSizeChanged;
 
170
                        DockWindow.Window.StyleSet += HandleStyleSet; 
 
171
                }
 
172
 
 
173
                void HandleStyleSet(object o, StyleSetArgs args)
 
174
                {
 
175
                        ResetSurfaces ();
 
176
                }
 
177
                
 
178
                public Cairo.Color AverageColor ()
 
179
                {
 
180
                        if (IconSurface == null)
 
181
                                return new Cairo.Color (1, 1, 1, 1);
 
182
                        
 
183
                        if (average_color.HasValue)
 
184
                                return average_color.Value;
 
185
                                
 
186
                        ImageSurface sr = new ImageSurface (Format.ARGB32, current_size, current_size);
 
187
                        using (Context cr = new Context (sr)) {
 
188
                                cr.Operator = Operator.Source;
 
189
                                IconSurface.Show (cr, 0, 0);
 
190
                        }
 
191
                        
 
192
                        sr.Flush ();
 
193
                        
 
194
                        byte [] data;
 
195
                        try {
 
196
                                data = sr.Data;
 
197
                        } catch {
 
198
                                return new Cairo.Color (1, 1, 1, 1);
 
199
                        }
 
200
                        byte r, g, b;
 
201
                        
 
202
                        double rTotal = 0;
 
203
                        double gTotal = 0;
 
204
                        double bTotal = 0;
 
205
                        
 
206
                        for (int i=0; i < data.Length - 3; i += 4) {
 
207
                                b = data [i + 0];
 
208
                                g = data [i + 1];
 
209
                                r = data [i + 2];
 
210
                                
 
211
                                byte max = Math.Max (r, Math.Max (g, b));
 
212
                                byte min = Math.Min (r, Math.Min (g, b));
 
213
                                double delta = max - min;
 
214
                                
 
215
                                double sat;
 
216
                                if (delta == 0) {
 
217
                                        sat = 0;
 
218
                                } else {
 
219
                                        sat = delta / max;
 
220
                                }
 
221
                                double score = .2 + .8 * sat;
 
222
                                
 
223
                                rTotal += r * score;
 
224
                                gTotal += g * score;
 
225
                                bTotal += b * score;
 
226
                        }
 
227
                        double pixelCount = current_size * current_size * byte.MaxValue;
 
228
                        
 
229
                        r = (byte) (byte.MaxValue * (rTotal / pixelCount));
 
230
                        g = (byte) (byte.MaxValue * (gTotal / pixelCount));
 
231
                        b = (byte) (byte.MaxValue * (bTotal / pixelCount));
 
232
                        
 
233
                        double h, s, v;
 
234
                        Do.Interface.Util.Appearance.RGBToHSV (r, g, b, out h, out s, out v);
 
235
                        v = 100;
 
236
                        s = Math.Min (100, s * 1.3);
 
237
                        Do.Interface.Util.Appearance.HSVToRGB (h, s, v, out r, out g, out b);
 
238
                        
 
239
                        Cairo.Color color = new Cairo.Color ((double) r / byte.MaxValue, (double) g / byte.MaxValue, (double) b / byte.MaxValue);
 
240
                        
 
241
                        sr.Destroy ();
 
242
                        
 
243
                        average_color = color;
 
244
                        return average_color.Value;
 
245
                }
 
246
 
 
247
                protected virtual Pixbuf GetSurfacePixbuf (int size)
 
248
                {
 
249
                        if (Icon == null)
 
250
                                return null;
 
251
                        
 
252
                        Gdk.Pixbuf pbuf = IconProvider.PixbufFromIconName (Icon, size);
 
253
                        if (pbuf.Height != size && pbuf.Width != size) {
 
254
                                double scale = (double)DockPreferences.FullIconSize / Math.Max (pbuf.Width, pbuf.Height);
 
255
                                Gdk.Pixbuf temp = pbuf.ScaleSimple ((int) (pbuf.Width * scale), (int) (pbuf.Height * scale), InterpType.Bilinear);
 
256
                                pbuf.Dispose ();
 
257
                                pbuf = temp;
 
258
                        }
 
259
                        
 
260
                        return pbuf;
 
261
                }
 
262
 
 
263
                /// <summary>
 
264
                /// Called whenever the icon receives a click event
 
265
                /// </summary>
 
266
                /// <param name="button">
 
267
                /// A <see cref="System.UInt32"/>
 
268
                /// </param>
 
269
                /// <param name="controller">
 
270
                /// A <see cref="IDoController"/>
 
271
                /// </param>
 
272
                public virtual void Clicked (uint button, ModifierType state, PointD position)
 
273
                {
 
274
                        SetLastClick ();
 
275
                }
 
276
                
 
277
                protected void SetLastClick ()
 
278
                {
 
279
                        LastClick = DateTime.UtcNow;
 
280
                        time_since_click_overdue = false;
 
281
                }
 
282
                
 
283
                public virtual void Scrolled (Gdk.ScrollDirection direction)
 
284
                {
 
285
                }
 
286
 
 
287
                Surface CopySurface (Surface source, int width, int height)
 
288
                {
 
289
                        Surface sr = source.CreateSimilar (Cairo.Content.ColorAlpha, width, height);
 
290
                        using (Context cr = new Context (sr)) {
 
291
                                source.Show (cr, 0, 0);
 
292
                        }
 
293
                        return sr;
 
294
                }
 
295
 
 
296
                public virtual Pixbuf GetDragPixbuf ()
 
297
                {
 
298
                        Gdk.Pixbuf pbuf = null;
 
299
                        try {
 
300
                                pbuf = GetSurfacePixbuf (DockPreferences.FullIconSize);
 
301
                        } catch {
 
302
                                // null it is
 
303
                        }
 
304
                        if (pbuf == null && IconSurface != null) {
 
305
                                // now we do something stupid
 
306
                                string tmp = System.IO.Path.GetTempFileName ();
 
307
                                IconSurface.WriteToPng (tmp);
 
308
                                pbuf = new Pixbuf (tmp);
 
309
                                System.IO.File.Delete (tmp);
 
310
                        }
 
311
                        
 
312
                        return pbuf;
 
313
                }
 
314
 
 
315
                public virtual Surface GetIconSurface (Surface similar, int targetSize, out int actualSize)
 
316
                {
 
317
                        Surface sr;
 
318
                        do {
 
319
                                switch (ScalingType) {
 
320
                                case ScalingType.HighLow:
 
321
                                        if (targetSize == DockPreferences.IconSize) {
 
322
                                                actualSize = DockPreferences.IconSize;
 
323
                                                if (SecondaryIconSurface == null) {
 
324
                                                        SecondaryIconSurface = MakeIconSurface (similar, actualSize);
 
325
                                                        current_size = actualSize;
 
326
                                                }
 
327
                                                sr = SecondaryIconSurface;
 
328
                                                continue;
 
329
                                        }
 
330
                                        actualSize = DockPreferences.FullIconSize;
 
331
                                        break;
 
332
                                case ScalingType.Downscaled:
 
333
                                        actualSize = DockPreferences.FullIconSize;
 
334
                                        break;
 
335
                                case ScalingType.Upscaled:
 
336
                                case ScalingType.None:
 
337
                                default:
 
338
                                        actualSize = DockPreferences.IconSize;
 
339
                                        break;
 
340
                                }
 
341
                                if (IconSurface == null) {
 
342
                                        IconSurface = MakeIconSurface (similar, actualSize);
 
343
                                        current_size = actualSize;
 
344
                                }
 
345
                                sr = IconSurface;
 
346
                        } while (false);
 
347
                        
 
348
                        return sr;
 
349
                }
 
350
 
 
351
                /// <summary>
 
352
                /// Gets a surface that is useful for display by the Dock based on the Description
 
353
                /// </summary>
 
354
                /// <param name="similar">
 
355
                /// A <see cref="Surface"/>
 
356
                /// </param>
 
357
                /// <returns>
 
358
                /// A <see cref="Surface"/>
 
359
                /// </returns>
 
360
                public virtual Surface GetTextSurface (Surface similar)
 
361
                {
 
362
                        if (string.IsNullOrEmpty (Description))
 
363
                                return null;
 
364
                        
 
365
                        if (text_surface == null || DockPreferences.Orientation != current_orientation) {
 
366
                                if (text_surface != null)
 
367
                                        text_surface.Destroy ();
 
368
                                
 
369
                                current_orientation = DockPreferences.Orientation;
 
370
                                Gdk.Rectangle rect;
 
371
                                text_surface = Util.GetBorderedTextSurface (GLib.Markup.EscapeText (Description), 
 
372
                                                                            DockPreferences.TextWidth, 
 
373
                                                                            similar, 
 
374
                                                                            current_orientation,
 
375
                                                                            out rect);
 
376
                                TextSurfaceSize = rect;
 
377
                        }
 
378
                        return text_surface;
 
379
                }
 
380
 
 
381
                protected virtual Surface MakeIconSurface (Surface similar, int size)
 
382
                {
 
383
                        current_size = size;
 
384
                        Surface tmp_surface = similar.CreateSimilar (Cairo.Content.ColorAlpha, size, size);
 
385
                        Context cr = new Context (tmp_surface);
 
386
                        
 
387
                        Gdk.Pixbuf pbuf = GetSurfacePixbuf (size);
 
388
                        if (pbuf != null) {
 
389
                                if (pbuf.Width != size || pbuf.Height != size) {
 
390
                                        double scale = (double)size / Math.Max (pbuf.Width, pbuf.Height);
 
391
                                        Gdk.Pixbuf temp = pbuf.ScaleSimple ((int) (pbuf.Width * scale), (int) (pbuf.Height * scale), Gdk.InterpType.Bilinear);
 
392
                                        pbuf.Dispose ();
 
393
                                        pbuf = temp;
 
394
                                }
 
395
                        
 
396
                                Gdk.CairoHelper.SetSourcePixbuf (cr, 
 
397
                                                                 pbuf, 
 
398
                                                                 (size - pbuf.Width) / 2,
 
399
                                                                 (size - pbuf.Height) / 2);
 
400
                                cr.Paint ();
 
401
                        
 
402
                                pbuf.Dispose ();
 
403
                        }
 
404
                        (cr as IDisposable).Dispose ();
 
405
                        
 
406
                        return tmp_surface;
 
407
                }
 
408
 
 
409
                void OnIconSizeChanged ()
 
410
                {
 
411
                        if (size_changed_timer > 0)
 
412
                                GLib.Source.Remove (size_changed_timer);
 
413
                        
 
414
                        if (ScalingType == ScalingType.HighLow) {
 
415
                                ResetSurfaces ();
 
416
                        } else if (IconSurface != null) {
 
417
                                if (resize_buffer == null)
 
418
                                        resize_buffer = CopySurface (IconSurface, current_size, current_size);
 
419
                                
 
420
                                Surface new_surface = resize_buffer.CreateSimilar (Cairo.Content.ColorAlpha, 
 
421
                                                                                  DockPreferences.FullIconSize, 
 
422
                                                                                  DockPreferences.FullIconSize);
 
423
                                using (Context cr = new Context (new_surface)) {
 
424
                                        double scale;
 
425
                                        if (ScalingType == ScalingType.Downscaled)
 
426
                                                scale = (double) DockPreferences.FullIconSize / (double) current_size;
 
427
                                        else
 
428
                                                scale = (double) DockPreferences.IconSize / (double) current_size;
 
429
                                        cr.Scale (scale, scale);
 
430
                                        resize_buffer.Show (cr, 0, 0);
 
431
                                }
 
432
                                IconSurface.Destroy ();
 
433
                                IconSurface = new_surface;
 
434
                        }
 
435
                        
 
436
                        size_changed_timer = GLib.Timeout.Add (150, delegate {
 
437
                                ResetSurfaces ();
 
438
                                size_changed_timer = 0;
 
439
                                return false;
 
440
                        });
 
441
                }
 
442
 
 
443
                protected void OnUpdateNeeded (UpdateRequestArgs args) 
 
444
                {
 
445
                        if (UpdateNeeded != null)
 
446
                                UpdateNeeded (this, args);
 
447
                }
 
448
 
 
449
                public virtual bool ReceiveItem (string item) 
 
450
                {
 
451
                        return false;
 
452
                }
 
453
 
 
454
                protected void RedrawIcon ()
 
455
                {
 
456
                        if (size_changed_timer > 0 || redraw_timer > 0)
 
457
                                return;
 
458
                        if (IconSurface != null) {
 
459
                                redraw_timer = GLib.Idle.Add (delegate {
 
460
                                        Surface similar = IconSurface;
 
461
                                        Surface second = SecondaryIconSurface;
 
462
                                        IconSurface = null;
 
463
                                        SecondaryIconSurface = null;
 
464
                                        
 
465
                                        if (similar != null && ((similar.Status & Cairo.Status.SurfaceFinished) != Cairo.Status.SurfaceFinished)) {
 
466
                                                switch (ScalingType) {
 
467
                                                case ScalingType.HighLow:
 
468
                                                        IconSurface = MakeIconSurface (similar, DockPreferences.FullIconSize);
 
469
                                                        SecondaryIconSurface = MakeIconSurface (similar, DockPreferences.IconSize);
 
470
                                                        break;
 
471
                                                case ScalingType.Downscaled:
 
472
                                                        IconSurface = MakeIconSurface (similar, DockPreferences.FullIconSize);
 
473
                                                        break;
 
474
                                                case ScalingType.Upscaled:
 
475
                                                case ScalingType.None:
 
476
                                                default:
 
477
                                                        IconSurface = MakeIconSurface (similar, DockPreferences.IconSize);
 
478
                                                        break;
 
479
                                                }
 
480
                                        }
 
481
                                        
 
482
                                        if (similar != null)
 
483
                                                similar.Destroy ();
 
484
                                        if (second != null)
 
485
                                                second.Destroy ();
 
486
                                        
 
487
                                        OnUpdateNeeded (new UpdateRequestArgs (this, UpdateRequestType.IconChanged));
 
488
                                        redraw_timer = 0;
 
489
                                        return false;
 
490
                                });
 
491
                        } else {
 
492
                                ResetIconSurface ();
 
493
                                OnUpdateNeeded (new UpdateRequestArgs (this, UpdateRequestType.IconChanged));
 
494
                        }
 
495
                }
 
496
                
 
497
                void ResetBufferSurface ()
 
498
                {
 
499
                        if (resize_buffer != null) {
 
500
                                resize_buffer.Destroy ();
 
501
                                resize_buffer = null;
 
502
                        }
 
503
                }
 
504
 
 
505
                void ResetIconSurface ()
 
506
                {
 
507
                        if (IconSurface != null) {
 
508
                                IconSurface.Destroy ();
 
509
                                IconSurface = null;
 
510
                        }
 
511
                        
 
512
                        if (SecondaryIconSurface != null) {
 
513
                                SecondaryIconSurface.Destroy ();
 
514
                                SecondaryIconSurface = null;
 
515
                        }
 
516
                }
 
517
 
 
518
                protected virtual void ResetSurfaces ()
 
519
                {
 
520
                        ResetTextSurface ();
 
521
                        ResetBufferSurface ();
 
522
                        ResetIconSurface ();
 
523
                        average_color = null;
 
524
                }
 
525
 
 
526
                void ResetTextSurface ()
 
527
                {
 
528
                        if (text_surface != null) {
 
529
                                text_surface.Destroy ();
 
530
                                text_surface = null;
 
531
                        }
 
532
                }
 
533
                
 
534
                public virtual void HotSeatRequested ()
 
535
                {
 
536
                }
 
537
 
 
538
                /// <summary>
 
539
                /// Called whenever an icon get repositioned, so it can update its child applications icon regions
 
540
                /// </summary>
 
541
                public virtual void SetIconRegion (Gdk.Rectangle region)
 
542
                {
 
543
                }
 
544
 
 
545
                protected void SetText (string text)
 
546
                {
 
547
                        Description = text;
 
548
                        ResetTextSurface ();
 
549
                }
 
550
 
 
551
                #region IDisposable implementation 
 
552
                
 
553
                public virtual void Dispose ()
 
554
                {
 
555
                        Disposed = true;
 
556
                        DockPreferences.IconSizeChanged -= OnIconSizeChanged;
 
557
                        if (DockWindow.Window != null)
 
558
                                DockWindow.Window.StyleSet -= HandleStyleSet;
 
559
                        ResetSurfaces ();
 
560
                }
 
561
                
 
562
                #endregion 
 
563
                
 
564
                public virtual bool Equals (AbstractDockItem other)
 
565
                {
 
566
                        return other == this;
 
567
                }
 
568
        }
 
569
}