~do-win/do/test-paths

« back to all changes in this revision

Viewing changes to Do.Interface.Windows.AnimationBase/src/Do.Interface/Do.Interface.AnimationBase/BezelResultsDrawingArea.cs

  • Committer: Hardeep S
  • Date: 2009-06-23 04:22:47 UTC
  • Revision ID: ootz0rz@gmail.com-20090623042247-ciyax78ykbtlx4ee
added Do.Interface.Windows.AnimationBase and Do.Interface.Windows.Classic

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// BezelResultsDrawingArea.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.Universe;
 
29
 
 
30
namespace Do.Interface.AnimationBase
 
31
{
 
32
        
 
33
        
 
34
        public class BezelResultsDrawingArea : Gtk.DrawingArea
 
35
        {
 
36
                
 
37
                const int SurfaceHeight = 20;
 
38
                const int IconSize = 16;
 
39
                const int FadeTime = 100;
 
40
                
 
41
                int num_results;
 
42
                int width, height;
 
43
                Dictionary <Do.Universe.Item, Surface> surface_buffer;
 
44
                Surface highlight_surface, backbuffer, child_inout_surface, triplebuffer;
 
45
                
 
46
                DateTime delta_time;
 
47
                double scroll_offset, highlight_offset, child_scroll_offset;
 
48
                int cursor, prev_cursor, delta;
 
49
                uint timer, delta_reset;
 
50
                
 
51
                Cairo.Color odd_color, even_color;
 
52
                
 
53
                Do.Universe.Item[] results;
 
54
                
 
55
                
 
56
                public Do.Universe.Item[] Results {
 
57
                        get {
 
58
                                return results;
 
59
                        }
 
60
                        set {
 
61
                                if (results != null && value != null && results.GetHashCode () == value.GetHashCode ())
 
62
                                        return;
 
63
                                results = value;
 
64
                                scroll_offset = 0;
 
65
                                highlight_offset = 0;
 
66
                        }
 
67
                }
 
68
                
 
69
                public int Cursor {
 
70
                        get {
 
71
                                return cursor;
 
72
                        }
 
73
                        set {
 
74
                                if (cursor == value)
 
75
                                        return;
 
76
                                
 
77
                                int oldStart = StartResult;
 
78
                                prev_cursor = cursor;
 
79
                                cursor = value;
 
80
                                if (oldStart == StartResult) {
 
81
                                        highlight_offset -= value-prev_cursor;
 
82
                                } else {
 
83
                                        scroll_offset += value-prev_cursor;
 
84
                                }
 
85
                                delta++;
 
86
                        }
 
87
                }
 
88
                
 
89
                private int StartResult {
 
90
                        get {
 
91
                                int result = Math.Max (Cursor - (num_results / 2), 0);
 
92
                                if (results == null)
 
93
                                        return 0;
 
94
                                while (result+num_results > results.Length && result > 1)
 
95
                                        result--;
 
96
                                return result;
 
97
                        }
 
98
                }
 
99
                
 
100
                private bool AnimationNeeded {
 
101
                        get {
 
102
                                return CursorMoveNeeded || ScrollNeeded || ChildScrollNeeded;
 
103
                        }
 
104
                }
 
105
                
 
106
                private bool CursorMoveNeeded {
 
107
                        get {
 
108
                                return highlight_offset != 0;
 
109
                        }
 
110
                }
 
111
                
 
112
                private bool ScrollNeeded {
 
113
                        get {
 
114
                                return scroll_offset != 0;
 
115
                        }
 
116
                }
 
117
                
 
118
                private bool ChildScrollNeeded {
 
119
                        get {
 
120
                                return child_scroll_offset != 0;
 
121
                        }
 
122
                }
 
123
                
 
124
                public BezelResultsDrawingArea(int numberResults, int width) : base ()
 
125
                {
 
126
                        num_results = numberResults;
 
127
                        surface_buffer = new Dictionary <Do.Universe.Item,Surface> ();
 
128
                        
 
129
                        this.width = width;
 
130
                        height = num_results * SurfaceHeight;
 
131
                        SetSizeRequest (width, height);
 
132
                        
 
133
                        odd_color       = new Cairo.Color (0.0, 0.0, 0.0, 0.0);
 
134
                        even_color      = new Cairo.Color (.2, .2, .2, .3);
 
135
                        
 
136
                        DoubleBuffered = false;
 
137
                }
 
138
                
 
139
                private void AnimatedDraw ()
 
140
                {
 
141
                        if (!IsDrawable || timer > 0) return;
 
142
                        
 
143
                        Paint ();
 
144
                        
 
145
                        if (!AnimationNeeded)
 
146
                                return;
 
147
                        
 
148
                        delta_time = DateTime.Now;
 
149
                        timer = GLib.Timeout.Add (20, delegate {
 
150
                                double change = DateTime.Now.Subtract (delta_time).TotalMilliseconds / FadeTime;
 
151
                                delta_time = DateTime.Now;
 
152
                                
 
153
                                double move = Math.Max (change*delta, change);
 
154
                                
 
155
                                if (ScrollNeeded) {
 
156
                                        if (scroll_offset > 0)
 
157
                                                scroll_offset = Math.Max (0, scroll_offset - move);
 
158
                                        else
 
159
                                                scroll_offset = Math.Min (0, scroll_offset + move);
 
160
                                }
 
161
                                
 
162
                                if (CursorMoveNeeded) {
 
163
                                        if (highlight_offset > 0)
 
164
                                                highlight_offset = Math.Max (0, highlight_offset - move);
 
165
                                        else
 
166
                                                highlight_offset = Math.Min (0, highlight_offset + move);
 
167
                                }
 
168
                                
 
169
                                if (ChildScrollNeeded) {
 
170
                                        if (child_scroll_offset > 0)
 
171
                                                child_scroll_offset = Math.Max (0, child_scroll_offset - change);
 
172
                                        else
 
173
                                                child_scroll_offset = Math.Min (0, child_scroll_offset + change);
 
174
                                }
 
175
                                
 
176
                                Paint ();
 
177
                                
 
178
                                if (!AnimationNeeded) {
 
179
                                        timer = 0;
 
180
                                        if (delta_reset > 0)
 
181
                                                GLib.Source.Remove (delta_reset);
 
182
                                        delta_reset = GLib.Timeout.Add (50, delegate {
 
183
                                                if (timer == 0)
 
184
                                                        delta = 0;
 
185
                                                delta_reset = 0;
 
186
                                                return false;
 
187
                                        });
 
188
                                        return false;
 
189
                                }
 
190
                                return true;
 
191
                        });
 
192
                }
 
193
                
 
194
                public void Clear ()
 
195
                {
 
196
                        Results = null;
 
197
                        Cursor = 0;
 
198
                        foreach (Surface s in surface_buffer.Values)
 
199
                                (s as IDisposable).Dispose ();
 
200
                        
 
201
                        surface_buffer = new Dictionary<Do.Universe.Item,Surface> ();
 
202
                }
 
203
                
 
204
                private void Paint ()
 
205
                {
 
206
                        if (!IsDrawable) return;
 
207
                        
 
208
                        Context cr = Gdk.CairoHelper.Create (GdkWindow);
 
209
                        
 
210
                        if (backbuffer == null) {
 
211
                                backbuffer = cr.Target.CreateSimilar (cr.Target.Content, width, height);
 
212
                        }
 
213
                        
 
214
                        
 
215
                        DrawContextOnSurface (backbuffer);
 
216
                        if (child_scroll_offset == 0) {
 
217
                                
 
218
                                cr.SetSource (backbuffer);
 
219
                                cr.Operator = Operator.Source;
 
220
                                cr.Paint ();
 
221
                        } else {
 
222
                                if (triplebuffer == null) {
 
223
                                        triplebuffer = cr.Target.CreateSimilar (cr.Target.Content, width, height);
 
224
                                }
 
225
                                
 
226
                                int old_x, new_x;
 
227
                                if (child_scroll_offset > 0) {
 
228
                                        old_x = (int)(-width*(1-child_scroll_offset));
 
229
                                        new_x = old_x+width;
 
230
                                } else {
 
231
                                        old_x = (int)(-width*(-1-child_scroll_offset));
 
232
                                        new_x = old_x-width;
 
233
                                }
 
234
                                
 
235
                                DrawSlideContexts (child_inout_surface, backbuffer, triplebuffer, old_x, new_x);
 
236
 
 
237
                                cr.SetSource (triplebuffer);
 
238
                                cr.Operator = Operator.Source;
 
239
                                cr.Paint ();
 
240
                        }
 
241
                        
 
242
                        (cr as IDisposable).Dispose ();
 
243
                }
 
244
                
 
245
                private void DrawSlideContexts (Surface old_surface, Surface new_surface, Surface target_surface,
 
246
                                                int old_x, int new_x)
 
247
                {
 
248
                        Context cr = new Context (target_surface);
 
249
                        
 
250
                        cr.Operator = Operator.Source;
 
251
                        cr.SetSource (old_surface, old_x, 0);
 
252
                        cr.Paint ();
 
253
                        
 
254
                        cr.Operator = Operator.Over;
 
255
                        cr.SetSource (new_surface, new_x, 0);
 
256
                        cr.Paint ();
 
257
                        
 
258
                        (cr as IDisposable).Dispose ();
 
259
                }
 
260
                
 
261
                private void DrawContextOnSurface (Surface sr)
 
262
                {
 
263
                        Context cr = new Context (sr);
 
264
                        cr.Operator = Operator.Source;
 
265
                        cr.Rectangle (0, 0, width, height);
 
266
                        cr.Color = new Cairo.Color (0, 0, 0, .9);
 
267
                        cr.Fill ();
 
268
                        cr.Operator = Operator.Over;
 
269
                        
 
270
                        if (Results != null) {
 
271
                                int start_result = StartResult-(int) Math.Ceiling (scroll_offset);
 
272
                                RenderHighlight (cr);
 
273
                                for (int i = start_result; i < start_result+num_results+1 && i < Results.Length; i++) {
 
274
                                        RenderItem (cr, i);
 
275
                                }
 
276
                        }
 
277
                        
 
278
                        (cr as IDisposable).Dispose ();
 
279
                }
 
280
                
 
281
                public void Draw ()
 
282
                {
 
283
                        AnimatedDraw ();
 
284
                }
 
285
                
 
286
                public void InitChildInAnimation ()
 
287
                {
 
288
                        if (child_inout_surface == null) {
 
289
                                Context cr = Gdk.CairoHelper.Create (GdkWindow);
 
290
                                child_inout_surface = cr.Target.CreateSimilar (cr.Target.Content, width, height);
 
291
                                (cr as IDisposable).Dispose ();
 
292
                        }
 
293
                        DrawContextOnSurface (child_inout_surface);
 
294
                        child_scroll_offset = 1;
 
295
                }
 
296
                
 
297
                public void InitChildOutAnimation ()
 
298
                {
 
299
                        if (child_inout_surface == null) {
 
300
                                Context cr = Gdk.CairoHelper.Create (GdkWindow);
 
301
                                child_inout_surface = cr.Target.CreateSimilar (cr.Target.Content, width, height);
 
302
                                (cr as IDisposable).Dispose ();
 
303
                        }
 
304
                        DrawContextOnSurface (child_inout_surface);
 
305
                        child_scroll_offset = -1;
 
306
                }
 
307
                
 
308
                protected override bool OnExposeEvent (EventExpose evnt)
 
309
                {
 
310
                        Draw ();
 
311
                        return base.OnExposeEvent (evnt);
 
312
                }
 
313
 
 
314
                void BufferItem (Do.Universe.Item item) 
 
315
                {
 
316
                        if (!IsDrawable)
 
317
                                return;
 
318
                        
 
319
                        Context cr = Gdk.CairoHelper.Create (GdkWindow);
 
320
                        Surface surface = cr.Target.CreateSimilar (cr.Target.Content, width, SurfaceHeight);
 
321
                        Context cr2 = new Context (surface);
 
322
                        cr2.Rectangle (0, 0, width, SurfaceHeight);
 
323
                        cr2.Color = new Cairo.Color (0, 0, 0, 0);
 
324
                        cr2.Operator = Operator.Source;
 
325
                        cr2.Fill ();
 
326
                        cr2.Operator = Operator.Over;
 
327
                        
 
328
                        Gdk.Pixbuf pixbuf = IconProvider.PixbufFromIconName (item.Icon, IconSize);
 
329
                        Gdk.CairoHelper.SetSourcePixbuf (cr2, pixbuf, 2, 2);
 
330
                        cr2.Paint ();
 
331
                                
 
332
                        Pango.Layout layout = new Pango.Layout (this.PangoContext);
 
333
                        layout.Width = Pango.Units.FromPixels (width - IconSize - 10);
 
334
                        layout.Ellipsize = Pango.EllipsizeMode.End;
 
335
                        layout.SetMarkup ("<span foreground=\"#ffffff\">"+item.Name+"</span>");
 
336
                        layout.FontDescription = Pango.FontDescription.FromString ("normal bold");
 
337
                        layout.FontDescription.AbsoluteSize = Pango.Units.FromPixels (10);
 
338
                                
 
339
                        cr2.MoveTo (IconSize + 6, 4);
 
340
                        Pango.CairoHelper.ShowLayout (cr2, layout);
 
341
                        
 
342
                        surface_buffer[item] = surface;
 
343
                        
 
344
                        layout.FontDescription.Dispose ();
 
345
                        (cr2 as IDisposable).Dispose ();
 
346
                        (cr as IDisposable).Dispose ();
 
347
                }
 
348
                
 
349
                Surface GetHighlightSource () 
 
350
                {
 
351
                        if (highlight_surface == null) {
 
352
                                Context cr = Gdk.CairoHelper.Create (GdkWindow);
 
353
                                highlight_surface = cr.Target.CreateSimilar (cr.Target.Content, width, SurfaceHeight);
 
354
                                
 
355
                                Context cr2 = new Context (highlight_surface);
 
356
                                LinearGradient grad = new LinearGradient (0, 0, 0, SurfaceHeight);
 
357
                                
 
358
                                grad.AddColorStop (0, new Cairo.Color (.2, .48, .81, 1));
 
359
                                grad.AddColorStop (1, new Cairo.Color (0, .21, .57, 1));
 
360
                                
 
361
                                cr2.Pattern = grad;
 
362
                                cr2.Rectangle (0, 0, width, SurfaceHeight);
 
363
                                cr2.Fill ();
 
364
                                
 
365
                                (cr as IDisposable).Dispose ();
 
366
                                (cr2 as IDisposable).Dispose ();
 
367
                        }
 
368
                        return highlight_surface;
 
369
                }
 
370
                
 
371
                void RenderItem (Context cr, int item)
 
372
                {
 
373
                        int offset = (int) (SurfaceHeight*scroll_offset);
 
374
                        if (!surface_buffer.ContainsKey (Results[item])) {
 
375
                                BufferItem (Results[item]);
 
376
                        }
 
377
                                
 
378
                        cr.Rectangle (0, offset+(item-StartResult)*SurfaceHeight, width, SurfaceHeight);
 
379
                        cr.Color = (item % 2 == 1) ? odd_color : even_color;
 
380
                        cr.Operator = Operator.DestOver;
 
381
                        cr.FillPreserve ();
 
382
                        
 
383
                        cr.Operator = Operator.Over;
 
384
                        
 
385
                        cr.SetSource (surface_buffer[Results[item]], 0, offset+(item-StartResult)*SurfaceHeight);
 
386
                        cr.Fill ();
 
387
                }
 
388
                
 
389
                void RenderHighlight (Context cr)
 
390
                {
 
391
                        int offset = (int) (SurfaceHeight*highlight_offset);
 
392
                        cr.Rectangle (0, offset+(Cursor-StartResult)*SurfaceHeight, width, SurfaceHeight);
 
393
                        cr.SetSource (GetHighlightSource (), 0, offset+(Cursor-StartResult)*SurfaceHeight);
 
394
                        cr.FillPreserve ();
 
395
                }
 
396
        }
 
397
}