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

« back to all changes in this revision

Viewing changes to src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/ButtonBar.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:
 
1
// 
 
2
// ButtonBar.cs
 
3
//  
 
4
// Author:
 
5
//       Mike KrĆ¼ger <mkrueger@xamarin.com>
 
6
// 
 
7
// Copyright (c) 2012 Xamarin Inc. (http://xamarin.com)
 
8
// 
 
9
// Permission is hereby granted, free of charge, to any person obtaining a copy
 
10
// of this software and associated documentation files (the "Software"), to deal
 
11
// in the Software without restriction, including without limitation the rights
 
12
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 
13
// copies of the Software, and to permit persons to whom the Software is
 
14
// furnished to do so, subject to the following conditions:
 
15
// 
 
16
// The above copyright notice and this permission notice shall be included in
 
17
// all copies or substantial portions of the Software.
 
18
// 
 
19
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
20
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
21
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 
22
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
23
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 
24
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
25
// THE SOFTWARE.
 
26
using System;
 
27
using Gtk;
 
28
using Gdk;
 
29
using System.Collections.Generic;
 
30
using MonoDevelop.Components;
 
31
using Cairo;
 
32
using System.Linq;
 
33
using MonoDevelop.Components.Commands;
 
34
using MonoDevelop.Ide;
 
35
using MonoDevelop.Core;
 
36
 
 
37
namespace MonoDevelop.Components.MainToolbar
 
38
{
 
39
        class ButtonBar : EventBox, ICommandBar
 
40
        {
 
41
                const int SeparatorSpacing = 6;
 
42
                List<ButtonBarButton> buttons = new List<ButtonBarButton> ();
 
43
                ButtonBarButton[] visibleButtons;
 
44
 
 
45
                Gdk.Pixbuf[] btnNormalOriginal;
 
46
                Gdk.Pixbuf[] btnPressedOriginal;
 
47
                Gdk.Pixbuf[] btnNormal;
 
48
                Gdk.Pixbuf[] btnPressed;
 
49
 
 
50
                ButtonBarButton pushedButton;
 
51
                object lastCommandTarget;
 
52
                int currentImagesHeight;
 
53
 
 
54
                public ButtonBar ()
 
55
                {
 
56
                        WidgetFlags |= Gtk.WidgetFlags.AppPaintable;
 
57
                        VisibleWindow = false;
 
58
                        Events |= EventMask.ButtonPressMask | EventMask.ButtonReleaseMask;
 
59
 
 
60
                        btnNormalOriginal = new Gdk.Pixbuf[] {
 
61
                                Gdk.Pixbuf.LoadFromResource ("btDebugBase-LeftCap-Normal.png"),
 
62
                                Gdk.Pixbuf.LoadFromResource ("btDebugBase-MidCap-Normal.png"),
 
63
                                Gdk.Pixbuf.LoadFromResource ("btDebugBase-RightCap-Normal.png")
 
64
                        };
 
65
 
 
66
                        btnPressedOriginal = new Gdk.Pixbuf[] {
 
67
                                Gdk.Pixbuf.LoadFromResource ("btDebugBase-LeftCap-Pressed.png"),
 
68
                                Gdk.Pixbuf.LoadFromResource ("btDebugBase-MidCap-Pressed.png"),
 
69
                                Gdk.Pixbuf.LoadFromResource ("btDebugBase-RightCap-Pressed.png")
 
70
                        };
 
71
                        btnNormal = new Pixbuf[btnNormalOriginal.Length];
 
72
                        btnPressed = new Pixbuf[btnNormalOriginal.Length];
 
73
                        HasTooltip = true;
 
74
                }
 
75
 
 
76
                void ScaleImages (int newHeight)
 
77
                {
 
78
                        if (currentImagesHeight == newHeight)
 
79
                                return;
 
80
 
 
81
                        currentImagesHeight = newHeight;
 
82
                        for (int n=0; n<btnNormalOriginal.Length; n++) {
 
83
                                if (btnNormal[n] != null)
 
84
                                        btnNormal[n].Dispose ();
 
85
                                btnNormal[n] = ExpandImageVertically (btnNormalOriginal[n], newHeight);
 
86
                        }
 
87
                        for (int n=0; n<btnPressedOriginal.Length; n++) {
 
88
                                if (btnPressed[n] != null)
 
89
                                        btnPressed[n].Dispose ();
 
90
                                btnPressed[n] = ExpandImageVertically (btnPressedOriginal[n], newHeight);
 
91
                        }
 
92
                }
 
93
 
 
94
                ButtonBarButton[] VisibleButtons {
 
95
                        get {
 
96
                                if (visibleButtons == null)
 
97
                                        visibleButtons = buttons.Where (b => b.Visible || b.IsSeparator).ToArray ();
 
98
                                return visibleButtons;
 
99
                        }
 
100
                }
 
101
 
 
102
                StateType leaveState = StateType.Normal;
 
103
                protected override bool OnEnterNotifyEvent (EventCrossing evnt)
 
104
                {
 
105
                        State = leaveState;
 
106
                        return base.OnEnterNotifyEvent (evnt);
 
107
                }
 
108
 
 
109
                protected override bool OnLeaveNotifyEvent (EventCrossing evnt)
 
110
                {
 
111
                        leaveState = State;
 
112
                        State = StateType.Normal;
 
113
                        return base.OnLeaveNotifyEvent (evnt);
 
114
                }
 
115
 
 
116
                protected override bool OnButtonPressEvent (EventButton evnt)
 
117
                {
 
118
                        if (evnt.Button == 1) {
 
119
                                pushedButton = VisibleButtons.FirstOrDefault (b => b.Allocation.Contains (Allocation.X + (int)evnt.X, Allocation.Y + (int)evnt.Y));
 
120
                                if (pushedButton != null && pushedButton.Enabled)
 
121
                                        State = StateType.Selected;
 
122
                        }
 
123
                        return true;
 
124
                }
 
125
 
 
126
                protected override bool OnButtonReleaseEvent (EventButton evnt)
 
127
                {
 
128
                        if (State == StateType.Selected && pushedButton != null)
 
129
                                IdeApp.CommandService.DispatchCommand (pushedButton.CommandId, null, lastCommandTarget, CommandSource.MainToolbar);
 
130
                        State = StateType.Prelight;
 
131
                        leaveState = StateType.Normal;
 
132
                        pushedButton = null;
 
133
                        return true;
 
134
                }
 
135
 
 
136
                protected override bool OnQueryTooltip (int x, int y, bool keyboard_tooltip, Tooltip tooltip)
 
137
                {
 
138
                        var button = VisibleButtons.FirstOrDefault (b => b.Allocation.Contains (Allocation.X + (int)x, Allocation.Y + (int)y));
 
139
                        if (button != null) {
 
140
                                tooltip.Text = button.Tooltip;
 
141
                                var rect = button.Allocation;
 
142
                                rect.Offset (-Allocation.X, -Allocation.Y);
 
143
                                tooltip.TipArea = rect;
 
144
                                return true;
 
145
                        } else {
 
146
                                return false;
 
147
                        }
 
148
                }
 
149
 
 
150
                public void Clear ()
 
151
                {
 
152
                        buttons.Clear ();
 
153
                        visibleButtons = null;
 
154
                        pushedButton = null;
 
155
                        QueueResize ();
 
156
                }
 
157
 
 
158
                public void Add (string commandId)
 
159
                {
 
160
                        ButtonBarButton b = new ButtonBarButton (commandId);
 
161
                        var ci = IdeApp.CommandService.GetCommandInfo (commandId, new CommandTargetRoute (lastCommandTarget));
 
162
                        if (ci != null)
 
163
                                UpdateButton (b, ci);
 
164
                        buttons.Add (b);
 
165
                        visibleButtons = null;
 
166
                        QueueResize ();
 
167
                }
 
168
 
 
169
                public void AddSeparator ()
 
170
                {
 
171
                        buttons.Add (new ButtonBarButton (null));
 
172
                        visibleButtons = null;
 
173
                        QueueResize ();
 
174
                }
 
175
 
 
176
                protected override void OnSizeRequested (ref Requisition requisition)
 
177
                {
 
178
                        base.OnSizeRequested (ref requisition);
 
179
                        requisition.Width = VisibleButtons.Sum (b => b.Visible ? (!b.IsSeparator ? btnNormalOriginal[0].Width : SeparatorSpacing) : 0);
 
180
                        requisition.Height = btnNormalOriginal[0].Height;
 
181
                }
 
182
 
 
183
                protected override bool OnExposeEvent (EventExpose evnt)
 
184
                {
 
185
                        ScaleImages (Allocation.Height);
 
186
 
 
187
                        using (var context = Gdk.CairoHelper.Create (evnt.Window)) {
 
188
                                double x = Allocation.X, y = Allocation.Y;
 
189
                                for (int i = 0; i < VisibleButtons.Length; i++) {
 
190
                                        bool nextIsSeparator = (i < VisibleButtons.Length - 1 && VisibleButtons[i + 1].IsSeparator) || i == visibleButtons.Length - 1;
 
191
                                        bool lastWasSeparator = (i > 0 && VisibleButtons[i - 1].IsSeparator) || i == 0;
 
192
                                        ButtonBarButton button = VisibleButtons [i];
 
193
                                        if (button.IsSeparator) {
 
194
                                                if (!lastWasSeparator)
 
195
                                                        x += SeparatorSpacing;
 
196
                                                continue;
 
197
                                        }
 
198
                                        Gdk.Pixbuf[] images = State == StateType.Selected && pushedButton == button ? btnPressed : btnNormal;
 
199
                                        Gdk.Pixbuf img = images [lastWasSeparator ? 0 : nextIsSeparator ? 2 : 1];
 
200
                                        Gdk.CairoHelper.SetSourcePixbuf (context, img, x, y);
 
201
                                        context.Paint ();
 
202
 
 
203
                                        button.Allocation = new Gdk.Rectangle ((int)x, (int)y, img.Width, img.Height);
 
204
 
 
205
                                        var icon = ImageService.GetPixbuf (button.Image, IconSize.Menu);
 
206
                                        var iconCopy = icon;
 
207
                                        if (!Sensitive || !button.Enabled)
 
208
                                                iconCopy = ImageService.MakeTransparent (icon, 0.4);
 
209
                                        Gdk.CairoHelper.SetSourcePixbuf (context, iconCopy, x + (img.Width - icon.Width) / 2, y + (img.Height - icon.Height) / 2);
 
210
                                        context.Paint ();
 
211
                                        if (iconCopy != icon)
 
212
                                                iconCopy.Dispose ();
 
213
                                        x += img.Width;
 
214
                                }
 
215
                        }
 
216
                        return base.OnExposeEvent (evnt);
 
217
                }
 
218
 
 
219
                Gdk.Pixbuf ExpandImageVertically (Gdk.Pixbuf img, int newHeight)
 
220
                {
 
221
                        if (newHeight <= img.Height)
 
222
                                return img.Copy ();
 
223
                        var res = new Gdk.Pixbuf (img.Colorspace, img.HasAlpha, img.BitsPerSample, img.Width, newHeight);
 
224
                        var h1 = img.Height / 2;
 
225
                        var h2 = img.Height - h1;
 
226
                        res.Fill (0xff000000);
 
227
                        img.Composite (res, 0, h1, res.Width, newHeight - img.Height, 0, 0, 1, (double)newHeight / (double)img.Height, InterpType.Bilinear, 255);
 
228
                        img.Composite (res, 0, 0, img.Width, h1, 0, 0, 1, 1, InterpType.Bilinear, 255);
 
229
                        img.Composite (res, 0, newHeight - h2, img.Width, h2, 0, newHeight - img.Height, 1, 1, InterpType.Bilinear, 255);
 
230
                        return res;
 
231
                }
 
232
 
 
233
                public sealed class ClickEventArgs : EventArgs
 
234
                {
 
235
                        public int Button { get; private set; }
 
236
 
 
237
                        public ClickEventArgs (int button)
 
238
                        {
 
239
                                this.Button = button;
 
240
                        }
 
241
                }
 
242
 
 
243
                #region ICommandBar implementation
 
244
                void ICommandBar.Update (object activeTarget)
 
245
                {
 
246
                        lastCommandTarget = activeTarget;
 
247
                        foreach (var b in buttons.Where (bu => !bu.IsSeparator)) {
 
248
                                var ci = IdeApp.CommandService.GetCommandInfo (b.CommandId, new CommandTargetRoute (activeTarget));
 
249
                                UpdateButton (b, ci);
 
250
                        }
 
251
                }
 
252
 
 
253
                void UpdateButton (ButtonBarButton b, CommandInfo ci)
 
254
                {
 
255
                        if (ci.Icon != b.Image) {
 
256
                                b.Image = ci.Icon;
 
257
                                QueueDraw ();
 
258
                        }
 
259
                        if (ci.Visible != b.Visible) {
 
260
                                b.Visible = ci.Visible;
 
261
                                visibleButtons = null;
 
262
                                QueueResize ();
 
263
                        }
 
264
                        if (ci.Enabled != b.Enabled) {
 
265
                                b.Enabled = ci.Enabled;
 
266
                                QueueDraw ();
 
267
                        }
 
268
                        if (ci.Description != b.Tooltip)
 
269
                                b.Tooltip = ci.Description;
 
270
                }
 
271
 
 
272
                void ICommandBar.SetEnabled (bool enabled)
 
273
                {
 
274
                        Sensitive = enabled;
 
275
                }
 
276
                #endregion
 
277
        }
 
278
 
 
279
        class ButtonBarButton
 
280
        {
 
281
                public ButtonBarButton (string commandId)
 
282
                {
 
283
                        this.CommandId = commandId;
 
284
                }
 
285
 
 
286
                public IconId Image { get; set; }
 
287
                public string CommandId { get; set; }
 
288
                internal bool Enabled { get; set; }
 
289
                internal bool Visible { get; set; }
 
290
                public string Tooltip { get; set; }
 
291
 
 
292
                public Gdk.Rectangle Allocation;
 
293
 
 
294
                public bool IsSeparator {
 
295
                        get { return CommandId == null; }
 
296
                }
 
297
        }
 
298
}
 
299