~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to src/core/Mono.Texteditor/Mono.TextEditor.Theatrics/BounceFadePopupWindow.cs

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
90
90
 
91
91
                public virtual void Popup ()
92
92
                {
 
93
                        if (editor.GdkWindow == null){
 
94
                                editor.Realized += HandleRealized;
 
95
                                return;
 
96
                        }
93
97
                        editor.GdkWindow.GetOrigin (out x, out y);
94
98
                        bounds = CalculateInitialBounds ();
95
99
                        x = x + bounds.X - (int)(ExpandWidth / 2);
107
111
                        Show ();
108
112
                }
109
113
 
 
114
                void HandleRealized (object sender, EventArgs e)
 
115
                {
 
116
                        editor.Realized -= HandleRealized;
 
117
                        Popup ();
 
118
                }
 
119
 
 
120
                Gtk.Adjustment vAdjustment;
 
121
                Gtk.Adjustment hAdjustment;
110
122
                protected void ListenToEvents ()
111
123
                {
112
 
                        editor.VAdjustment.ValueChanged += HandleEditorVAdjustmentValueChanged;
113
 
                        editor.HAdjustment.ValueChanged += HandleEditorHAdjustmentValueChanged;
114
 
                        vValue = editor.VAdjustment.Value;
115
 
                        hValue = editor.HAdjustment.Value;
 
124
                        if (vAdjustment == null) {
 
125
                                vAdjustment = editor.VAdjustment;
 
126
                                hAdjustment = editor.HAdjustment;
 
127
 
 
128
                                vAdjustment.ValueChanged += HandleEditorVAdjustmentValueChanged;
 
129
                                hAdjustment.ValueChanged += HandleEditorHAdjustmentValueChanged;
 
130
                        }
 
131
                        vValue = vAdjustment.Value;
 
132
                        hValue = hAdjustment.Value;
116
133
                }
117
134
 
118
135
                protected override void OnShown ()
122
139
                
123
140
                protected void DetachEvents ()
124
141
                {
125
 
                        editor.VAdjustment.ValueChanged -= HandleEditorVAdjustmentValueChanged;
126
 
                        editor.HAdjustment.ValueChanged -= HandleEditorHAdjustmentValueChanged;
 
142
                        if (vAdjustment == null)
 
143
                                return;
 
144
                        vAdjustment.ValueChanged -= HandleEditorVAdjustmentValueChanged;
 
145
                        hAdjustment.ValueChanged -= HandleEditorHAdjustmentValueChanged;
 
146
                        vAdjustment = null;
 
147
                        hAdjustment = null;
127
148
                }
128
149
 
129
150
                protected override void OnHidden ()
198
219
                
199
220
                
200
221
        }
 
222
 
 
223
        /// <summary>
 
224
        /// Tooltip that "bounces", then fades away.
 
225
        /// </summary>
 
226
        public abstract class BounceFadePopupWidget : Gtk.Widget
 
227
        {
 
228
                Stage<BounceFadePopupWidget> stage = new Stage<BounceFadePopupWidget> ();
 
229
                Gdk.Pixbuf textImage = null;
 
230
                TextEditor editor;
 
231
                
 
232
                protected double scale = 0.0;
 
233
                protected double opacity = 1.0;
 
234
                
 
235
                public BounceFadePopupWidget (TextEditor editor)
 
236
                {
 
237
                        if (!IsComposited)
 
238
                                throw new InvalidOperationException ("Only works with composited screen. Check Widget.IsComposited.");
 
239
                        if (editor == null)
 
240
                                throw new ArgumentNullException ("Editor");
 
241
                        WidgetFlags |= Gtk.WidgetFlags.NoWindow;
 
242
                        this.editor = editor;
 
243
                        Events = EventMask.ExposureMask;
 
244
                        Duration = 500;
 
245
                        ExpandWidth = 12;
 
246
                        ExpandHeight = 2;
 
247
                        BounceEasing = Easing.Sine;
 
248
                        
 
249
                        var rgbaColormap = Screen.RgbaColormap;
 
250
                        if (rgbaColormap == null)
 
251
                                return;
 
252
                        Colormap = rgbaColormap;
 
253
 
 
254
                        stage.ActorStep += OnAnimationActorStep;
 
255
                        stage.Iteration += OnAnimationIteration;
 
256
                        stage.UpdateFrequency = 10;
 
257
                }
 
258
                
 
259
                protected TextEditor Editor { get { return editor; } }
 
260
                
 
261
                /// <summary>Duration of the animation, in milliseconds.</summary>
 
262
                public uint Duration { get; set; }
 
263
                
 
264
                /// <summary>The number of pixels by which the window's width will expand</summary>
 
265
                public uint ExpandWidth { get; set; }
 
266
                
 
267
                /// <summary>The number of pixels by which the window's height will expand</summary>
 
268
                public uint ExpandHeight { get; set; }
 
269
 
 
270
                /// <summary>The easing used for the bounce part of the animation.</summary>
 
271
                public Easing BounceEasing { get; set; }
 
272
 
 
273
                int xExpandedOffset, yExpandedOffset;
 
274
                Cairo.Rectangle userspaceArea;
 
275
                Cairo.Rectangle bounds;
 
276
 
 
277
                public virtual void Popup ()
 
278
                {
 
279
                        if (editor.GdkWindow == null){
 
280
                                editor.Realized += HandleRealized;
 
281
                                return;
 
282
                        }
 
283
 
 
284
                        bounds = CalculateInitialBounds ();
 
285
 
 
286
                        //GTK uses integer position coords, so round fractions down, we'll add them back later as draw offsets
 
287
                        int x = (int) System.Math.Floor (bounds.X);
 
288
                        int y = (int) System.Math.Floor (bounds.Y);
 
289
 
 
290
                        //capture any lost fractions to pass as an offset to Draw
 
291
                        userspaceArea = new Cairo.Rectangle (bounds.X - x, bounds.Y - y, bounds.Width, bounds.Height);
 
292
 
 
293
                        //lose half-pixels on the expansion, it's not a big deal
 
294
                        xExpandedOffset = (int) (System.Math.Floor (ExpandWidth / 2d));
 
295
                        yExpandedOffset = (int) (System.Math.Floor (ExpandHeight / 2d));
 
296
 
 
297
                        //round the width/height up to make sure we have room for restored fractions
 
298
                        int width = System.Math.Max (1, (int) (System.Math.Ceiling (bounds.Width) + ExpandWidth));
 
299
                        int height = System.Math.Max (1, (int) (System.Math.Ceiling (bounds.Height) + ExpandHeight));
 
300
                        this.SetSizeRequest (width, height);
 
301
                        editor.TextArea.AddTopLevelWidget (this, x - xExpandedOffset, y - yExpandedOffset);
 
302
 
 
303
                        stage.AddOrReset (this, Duration);
 
304
                        stage.Play ();
 
305
                        Show ();
 
306
                }
 
307
 
 
308
                void HandleRealized (object sender, EventArgs e)
 
309
                {
 
310
                        editor.Realized -= HandleRealized;
 
311
                        Popup ();
 
312
                }
 
313
 
 
314
                void OnAnimationIteration (object sender, EventArgs args)
 
315
                {
 
316
                        QueueDraw ();
 
317
                }
 
318
                
 
319
                protected virtual bool OnAnimationActorStep (Actor<BounceFadePopupWidget> actor)
 
320
                {
 
321
                        if (actor.Expired) {
 
322
                                OnAnimationCompleted ();
 
323
                                return false;
 
324
                        }
 
325
                        
 
326
                        // for the first half, use an easing
 
327
                        if (actor.Percent < 0.5) {
 
328
                                scale = Choreographer.Compose (actor.Percent * 2, BounceEasing);
 
329
                                opacity = 1.0;
 
330
                        }
 
331
                        //for the second half, vary opacity linearly from 1 to 0.
 
332
                        else {
 
333
                                scale = Choreographer.Compose (1.0, BounceEasing);
 
334
                                opacity = 1 - 2 * (actor.Percent - 0.5);
 
335
                        }
 
336
                        return true;
 
337
                }
 
338
 
 
339
                protected override bool OnExposeEvent (EventExpose evnt)
 
340
                {
 
341
                        try {
 
342
                                var alloc = Allocation;
 
343
                                using (var cr = CairoHelper.Create (evnt.Window)) {
 
344
                                        cr.Translate (alloc.X, alloc.Y);
 
345
                                        cr.Translate (xExpandedOffset * (1 - scale), yExpandedOffset * (1 - scale));
 
346
                                        var scaleX = (alloc.Width / userspaceArea.Width - 1) * scale + 1;
 
347
                                        var scaleY = (alloc.Height / userspaceArea.Height - 1) * scale + 1;
 
348
                                        cr.Scale (scaleX, scaleY);
 
349
                                        Draw (cr, userspaceArea);
 
350
                                }
 
351
                        } catch (Exception e) {
 
352
                                Console.WriteLine ("Exception in animation:" + e);
 
353
                        }
 
354
                        return true;
 
355
                }
 
356
 
 
357
                protected abstract void Draw (Cairo.Context context, Cairo.Rectangle area);
 
358
 
 
359
                protected virtual void OnAnimationCompleted ()
 
360
                {
 
361
                        StopPlaying ();
 
362
                }
 
363
                
 
364
                protected override void OnDestroyed ()
 
365
                {
 
366
                        base.OnDestroyed ();
 
367
                        StopPlaying ();
 
368
                }
 
369
                
 
370
                internal virtual void StopPlaying ()
 
371
                {
 
372
                        stage.Playing = false;
 
373
                        
 
374
                        if (textImage != null) {
 
375
                                textImage.Dispose ();
 
376
                                textImage = null;
 
377
                        }
 
378
                }
 
379
 
 
380
                protected abstract Cairo.Rectangle CalculateInitialBounds ();
 
381
        }
201
382
}