Merge lp:~elementary-dev-community/granite/fix-1084911 into lp:~elementary-pantheon/granite/granite

Proposed by Julián Unrrein
Status: Merged
Approved by: David Gomes
Approved revision: 614
Merged at revision: 612
Proposed branch: lp:~elementary-dev-community/granite/fix-1084911
Merge into: lp:~elementary-pantheon/granite/granite
Diff against target: 258 lines (+216/-2)
3 files modified
demo/main.vala (+12/-2)
lib/CMakeLists.txt (+1/-0)
lib/Widgets/OverlayBar.vala (+203/-0)
To merge this branch: bzr merge lp:~elementary-dev-community/granite/fix-1084911
Reviewer Review Type Date Requested Status
Danielle Foré Approve
David Gomes (community) Approve
Julián Unrrein (community) Approve
ammonkey code licensing Pending
Review via email: mp+180644@code.launchpad.net

Commit message

Added the Overlay Bar widget (from Pantheon Files), fixing bug #1084911.

Description of the change

Move Files' Overlay Bar to Granite.

Please refer to the source documentation to see details.

This branch also moves code from the GPLv3 to the LGPLv3, and as such, it needs to be approved by the copyright holder - ammonkey.

I also developed Files and Midori branches where this widget is used, to help testing:
lp:~elementary-dev-community/pantheon-files/granite-overlaybar
lp:~junrrein/midori/granite-overlaybar

And also, the example from source documentation:
lp:~junrrein/junk/granite-overlaybar-example

To post a comment you must log in.
Revision history for this message
David Gomes (davidgomes) wrote :

Line 59 mis-indentation.

review: Needs Fixing
610. By Julián Unrrein

Replace tabs with spaces.

611. By Julián Unrrein

Correct spelling mistakes.

Revision history for this message
Julián Unrrein (junrrein) wrote :

Applied David's suggestions.

612. By David Gomes

demo: Added OverlayBar example to granite demo.

Revision history for this message
David Gomes (davidgomes) wrote :

I approve it.

I added junrrein as reviewer, he can review the code I wrote for the demo.

Finally, also added Daniel as a reviewer so he can review the place where I put the OverlayBar in the demo design-wise.

review: Approve
Revision history for this message
Julián Unrrein (junrrein) wrote :

It turns out it's not necessary to pack a Gtk.Overlay inside a Gtk.Box before using it.

Therefore remove diff lines 33-34 and 111-112. Update diff line 36 to "return overlay", and line 114 to "this.add (overlay)".

review: Needs Fixing
613. By David Gomes

Fixed the overlay in a box issue.

614. By Julián Unrrein

Use a label instead of an icon view in the overlay bar examples.

Revision history for this message
Julián Unrrein (junrrein) wrote :

Looks good to me.

In the example and in granite-demo, I replaced the icon view with a label: "Try to touch the Overlay Bar!".

Now waiting for Dan's review.

review: Approve
Revision history for this message
David Gomes (davidgomes) wrote :

I love cooperation.

review: Approve
Revision history for this message
Danielle Foré (danrabbit) wrote :

Yay overlaybar. Works here

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'demo/main.vala'
2--- demo/main.vala 2013-07-20 12:04:09 +0000
3+++ demo/main.vala 2013-08-19 23:11:47 +0000
4@@ -191,7 +191,7 @@
5 var pageone = new Gtk.Label ("Page 1");
6
7 staticnotebook.append_page (new Gtk.Label ("Page 1"), pageone);
8- staticnotebook.append_page (new Gtk.Label ("Page 2"), new Gtk.Label ("Page 2"));
9+ staticnotebook.append_page (get_overlay_bar_widget (), new Gtk.Label ("Overlay Bar"));
10 staticnotebook.append_page (new Gtk.Label ("Page 3"), new Gtk.Label ("Page 3"));
11
12 staticnotebook.page_changed.connect (() => {
13@@ -377,7 +377,6 @@
14 }
15
16 private Granite.Widgets.DynamicNotebook create_dynamic_notebook () {
17-
18 int i = 3;
19
20 var dynamic_notebook = new Granite.Widgets.DynamicNotebook ();
21@@ -436,6 +435,17 @@
22 return dynamic_notebook;
23 }
24
25+ private Gtk.Widget get_overlay_bar_widget () {
26+ // OverlayBar (inside StaticNotebook)
27+ var overlay = new Gtk.Overlay ();
28+ overlay.add (new Gtk.Label ("Try to touch the Overlay Bar!"));
29+
30+ var overlay_bar = new Granite.Widgets.OverlayBar (overlay);
31+ overlay_bar.status = "Overlay Bar Example";
32+
33+ return overlay;
34+ }
35+
36 public static int main (string[] args) {
37 new Granite.Demo ().run (args);
38 Gtk.main ();
39
40=== modified file 'lib/CMakeLists.txt'
41--- lib/CMakeLists.txt 2013-06-08 20:38:28 +0000
42+++ lib/CMakeLists.txt 2013-08-19 23:11:47 +0000
43@@ -44,6 +44,7 @@
44 Widgets/CellRendererExpander.vala
45 Widgets/CellRendererBadge.vala
46 Widgets/ThinPaned.vala
47+ Widgets/OverlayBar.vala
48 )
49
50 set (C_SOURCES
51
52=== added file 'lib/Widgets/OverlayBar.vala'
53--- lib/Widgets/OverlayBar.vala 1970-01-01 00:00:00 +0000
54+++ lib/Widgets/OverlayBar.vala 2013-08-19 23:11:47 +0000
55@@ -0,0 +1,203 @@
56+/***
57+ Copyright (C) 2012 ammonkey <am.monkeyd@gmail.com>
58+ Copyright (C) 2013 Julián Unrrein <junrrein@gmail.com>
59+
60+ This program or library is free software; you can redistribute it
61+ and/or modify it under the terms of the GNU Lesser General Public
62+ License as published by the Free Software Foundation; either
63+ version 3 of the License, or (at your option) any later version.
64+
65+ This library is distributed in the hope that it will be useful,
66+ but WITHOUT ANY WARRANTY; without even the implied warranty of
67+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
68+ Lesser General Public License for more details.
69+
70+ You should have received a copy of the GNU Lesser General
71+ Public License along with this library; if not, write to the
72+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
73+ Boston, MA 02110-1301 USA.
74+***/
75+
76+/**
77+ * A floating status bar that displays a single line of text.
78+ *
79+ * This widget is intended to be used as an overlay for a {@link Gtk.Overlay} and is placed in the
80+ * bottom-right corner by default. You can change its position like you would do for any overlay
81+ * widget used in a {@link Gtk.Overlay}.
82+ *
83+ * The Overlay Bar displays a single line of text that can be changed using the "status" property.
84+ *
85+ * This widget tries to avoid getting in front of the content being displayed inside the {@link Gtk.Overlay}
86+ * by moving itself horizontally to the opposite side from the current one when the mouse pointer enters
87+ * the widget.
88+ *
89+ * For this widget to function correctly, the event {@link Gdk.EventMask.ENTER_NOTIFY_MASK} must be set
90+ * for the parent {@link Gtk.Overlay}. Overlay Bar's constructor takes care of this automatically,
91+ * but you have to be careful not to unset the event for the {@link Gtk.Overlay} at a later stage.
92+ *
93+ * ''Example'' <<BR>>
94+ *
95+ * public class OverlayBarExample : Gtk.Window {{{
96+ *
97+ * public OverlayBarExample () {{{
98+ * this.title = "Overlay Bar Example";
99+ * this.window_position = Gtk.WindowPosition.CENTER;
100+ * this.set_default_size (400, 300);
101+ *
102+ * var overlay = new Gtk.Overlay ();
103+ * overlay.add (new Gtk.Label ("Try to touch the Overlay Bar!"));
104+ *
105+ * var overlaybar = new Granite.Widgets.OverlayBar (overlay);
106+ * overlaybar.status = "Overlay Bar Example";
107+ *
108+ * this.add (overlay);
109+ * }}}
110+ *
111+ * public static int main (string[] args) {{{
112+ * Gtk.init (ref args);
113+ *
114+ * var window = new OverlayBarExample ();
115+ * window.destroy.connect (Gtk.main_quit);
116+ * window.show_all ();
117+ *
118+ * Gtk.main ();
119+ * return 0;
120+ * }}}
121+ * }}}
122+ *
123+ * valac --pkg gtk+-3.0 --pkg granite OverlayBarExample.vala
124+ *
125+ * @see Gtk.Overlay
126+ */
127+public class Granite.Widgets.OverlayBar : Gtk.EventBox {
128+
129+ private const string FALLBACK_THEME = """
130+ .granite-overlay-bar {
131+ background-color: @bg_color;
132+ border-radius: 3px;
133+ padding: 3px 6px;
134+ margin: 3px;
135+ border-style: solid;
136+ border-width: 1px;
137+ border-color: darker (@bg_color);
138+ }""";
139+
140+ private Gtk.Label status_label;
141+
142+ /**
143+ * Status text displayed inside the Overlay Bar.
144+ */
145+ public string status {
146+ set {
147+ status_label.label = value;
148+ }
149+
150+ get {
151+ return status_label.label;
152+ }
153+ }
154+
155+ /**
156+ * Create a new Overlay Bar, and add it to the {@link Gtk.Overlay}.
157+ */
158+ public OverlayBar (Gtk.Overlay overlay) {
159+ visible_window = false;
160+
161+ status_label = new Gtk.Label (null);
162+ status_label.set_ellipsize (Pango.EllipsizeMode.END);
163+ add (status_label);
164+ status_label.show ();
165+
166+ set_halign (Gtk.Align.END);
167+ set_valign (Gtk.Align.END);
168+
169+ set_default_style ();
170+
171+ var ctx = get_style_context ();
172+ ctx.changed.connect (update_spacing);
173+ ctx.changed.connect_after (queue_resize);
174+
175+ update_spacing ();
176+
177+ overlay.add_events (Gdk.EventMask.ENTER_NOTIFY_MASK);
178+ overlay.add_overlay (this);
179+ }
180+
181+ public override void parent_set (Gtk.Widget? old_parent) {
182+ Gtk.Widget parent = get_parent ();
183+
184+ if (old_parent != null)
185+ old_parent.enter_notify_event.disconnect (enter_notify_callback);
186+ if (parent != null)
187+ parent.enter_notify_event.connect (enter_notify_callback);
188+ }
189+
190+ public override bool draw (Cairo.Context cr) {
191+ var ctx = get_style_context ();
192+ ctx.render_background (cr, 0, 0, get_allocated_width (), get_allocated_height ());
193+ ctx.render_frame (cr, 0, 0, get_allocated_width (), get_allocated_height ());
194+ return base.draw (cr);
195+ }
196+
197+ public override Gtk.SizeRequestMode get_request_mode () {
198+ return Gtk.SizeRequestMode.HEIGHT_FOR_WIDTH;
199+ }
200+
201+ public override void get_preferred_width (out int minimum_width, out int natural_width) {
202+ Gtk.Requisition label_min_size, label_natural_size;
203+ status_label.get_preferred_size (out label_min_size, out label_natural_size);
204+
205+ var ctx = get_style_context ();
206+ var state = ctx.get_state ();
207+ var border = ctx.get_border (state);
208+
209+ int extra_allocation = border.left + border.right;
210+ minimum_width = extra_allocation + label_min_size.width;
211+ natural_width = extra_allocation + label_natural_size.width;
212+ }
213+
214+ public override void get_preferred_height_for_width (int width, out int minimum_height,
215+ out int natural_height) {
216+ Gtk.Requisition label_min_size, label_natural_size;
217+ status_label.get_preferred_size (out label_min_size, out label_natural_size);
218+
219+ var ctx = get_style_context ();
220+ var state = ctx.get_state ();
221+ var border = ctx.get_border (state);
222+
223+ int extra_allocation = border.top + border.bottom;
224+ minimum_height = extra_allocation + label_min_size.height;
225+ natural_height = extra_allocation + label_natural_size.height;
226+ }
227+
228+ private void update_spacing () {
229+ var ctx = get_style_context ();
230+ var state = ctx.get_state ();
231+
232+ var padding = ctx.get_padding (state);
233+ status_label.margin_top = padding.top;
234+ status_label.margin_bottom = padding.bottom;
235+ status_label.margin_left = padding.left;
236+ status_label.margin_right = padding.right;
237+
238+ var margin = ctx.get_margin (state);
239+ margin_top = margin.top;
240+ margin_bottom = margin.bottom;
241+ margin_left = margin.left;
242+ margin_right = margin.right;
243+ }
244+
245+ private void set_default_style () {
246+ int priority = Gtk.STYLE_PROVIDER_PRIORITY_FALLBACK;
247+ Granite.Widgets.Utils.set_theming (this, FALLBACK_THEME, "granite-overlay-bar", priority);
248+ }
249+
250+ private bool enter_notify_callback (Gdk.EventCrossing event) {
251+ if (get_halign () == Gtk.Align.START)
252+ set_halign (Gtk.Align.END);
253+ else
254+ set_halign (Gtk.Align.START);
255+
256+ return false;
257+ }
258+}

Subscribers

People subscribed via source and target branches