Merge lp:~tintou/granite/granite-headerbar into lp:~elementary-pantheon/granite/granite

Proposed by David Gomes
Status: Rejected
Rejected by: Corentin Noël
Proposed branch: lp:~tintou/granite/granite-headerbar
Merge into: lp:~elementary-pantheon/granite/granite
Diff against target: 702 lines (+454/-54)
8 files modified
CMakeLists.txt (+1/-1)
cmake/FindGirCompiler.cmake (+56/-0)
cmake/Tests.cmake (+5/-0)
cmake/Translations.cmake (+2/-1)
cmake/ValaPrecompile.cmake (+41/-6)
demo/GraniteDemo.vala (+30/-35)
lib/CMakeLists.txt (+5/-11)
lib/Widgets/HeaderBar.vala (+314/-0)
To merge this branch: bzr merge lp:~tintou/granite/granite-headerbar
Reviewer Review Type Date Requested Status
Danielle Foré Pending
elementary Pantheon team Pending
Review via email: mp+199914@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Danielle Foré (danrabbit) wrote :

After some discussion, I think we need to first decide if we intend to ship with gtk 3.12 or backport any features of gtk 3.12 (like max and min buttons) which would make this branch obsolete.

IMO, the latest improvements to headerbar would be worth it.

Unmerged revisions

665. By Corentin Noël

Added valadoc

664. By Corentin Noël

Do not reparent widgets if they are already on the right container, check if the window is resizeable to show the maximize button

663. By Corentin Noël

Now fully working

662. By Corentin Noël

New HeaderBar widget

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2013-11-15 15:01:20 +0000
3+++ CMakeLists.txt 2013-12-22 03:34:36 +0000
4@@ -9,7 +9,7 @@
5 set (API_VERSION 1.0)
6
7 # Used to create GObject introspection files
8-set (PKG_GIR_NAME Granite)
9+set (PKG_GIR_NAME Granite-${PKG_VERSION})
10
11 list (APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/)
12
13
14=== added file 'cmake/FindGirCompiler.cmake'
15--- cmake/FindGirCompiler.cmake 1970-01-01 00:00:00 +0000
16+++ cmake/FindGirCompiler.cmake 2013-12-22 03:34:36 +0000
17@@ -0,0 +1,56 @@
18+##
19+# Copyright 2009-2010 Jakob Westhoff. All rights reserved.
20+#
21+# Redistribution and use in source and binary forms, with or without
22+# modification, are permitted provided that the following conditions are met:
23+#
24+# 1. Redistributions of source code must retain the above copyright notice,
25+# this list of conditions and the following disclaimer.
26+#
27+# 2. Redistributions in binary form must reproduce the above copyright notice,
28+# this list of conditions and the following disclaimer in the documentation
29+# and/or other materials provided with the distribution.
30+#
31+# THIS SOFTWARE IS PROVIDED BY JAKOB WESTHOFF ``AS IS'' AND ANY EXPRESS OR
32+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
33+# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
34+# EVENT SHALL JAKOB WESTHOFF OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
35+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
36+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
37+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
38+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
39+# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
40+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41+#
42+# The views and conclusions contained in the software and documentation are those
43+# of the authors and should not be interpreted as representing official policies,
44+# either expressed or implied, of Jakob Westhoff
45+##
46+
47+##
48+# Find module for the Gir compiler (g-ir-compiler)
49+#
50+# This module determines wheter a Gir compiler is installed on the current
51+# system and where its executable is.
52+#
53+# Call the module using "find_package(GirCompiler) from within your CMakeLists.txt.
54+#
55+# The following variables will be set after an invocation:
56+#
57+# G_IR_COMPILER_FOUND Whether the g-ir-compiler compiler has been found or not
58+# G_IR_COMPILER_EXECUTABLE Full path to the g-ir-compiler executable if it has been found
59+##
60+
61+
62+# Search for the g-ir-compiler executable in the usual system paths.
63+find_program (G_IR_COMPILER_EXECUTABLE
64+ NAMES g-ir-compiler)
65+
66+# Handle the QUIETLY and REQUIRED arguments, which may be given to the find call.
67+# Furthermore set G_IR_COMPILER_FOUND to TRUE if the g-ir-compiler has been found (aka.
68+# G_IR_COMPILER_EXECUTABLE is set)
69+
70+include (FindPackageHandleStandardArgs)
71+find_package_handle_standard_args (GirCompiler DEFAULT_MSG G_IR_COMPILER_EXECUTABLE)
72+
73+mark_as_advanced (G_IR_COMPILER_EXECUTABLE)
74
75=== added file 'cmake/Tests.cmake'
76--- cmake/Tests.cmake 1970-01-01 00:00:00 +0000
77+++ cmake/Tests.cmake 2013-12-22 03:34:36 +0000
78@@ -0,0 +1,5 @@
79+# Test macros for Marlin, feel free to re-use them.
80+
81+macro(add_test_executable EXE_NAME)
82+ add_test(${EXE_NAME} gtester ${CMAKE_CURRENT_BINARY_DIR}/${EXE_NAME})
83+endmacro()
84
85=== modified file 'cmake/Translations.cmake' (properties changed: -x to +x)
86--- cmake/Translations.cmake 2012-06-05 05:05:44 +0000
87+++ cmake/Translations.cmake 2013-12-22 03:34:36 +0000
88@@ -36,6 +36,7 @@
89
90 add_custom_command (TARGET pot COMMAND
91 ${XGETTEXT_EXECUTABLE} -d ${NLS_PACKAGE} -o ${CMAKE_CURRENT_SOURCE_DIR}/${NLS_PACKAGE}.pot
92- ${VALA_SOURCE} ${C_SOURCE} --keyword="_" --keyword="N_" --from-code=UTF-8
93+ ${VALA_SOURCE} ${C_SOURCE} --add-comments="/" --keyword="_" --keyword="N_" --keyword="C_:1c,2"
94+ --keyword="NC_:1c,2" --keyword="ngettext:1,2" --keyword="N_" --keyword="Q_:1g" --from-code=UTF-8
95 )
96 endmacro()
97
98=== modified file 'cmake/ValaPrecompile.cmake'
99--- cmake/ValaPrecompile.cmake 2012-11-28 02:35:13 +0000
100+++ cmake/ValaPrecompile.cmake 2013-12-22 03:34:36 +0000
101@@ -1,5 +1,6 @@
102 ##
103 # Copyright 2009-2010 Jakob Westhoff. All rights reserved.
104+# Copyright 2012 elementary.
105 #
106 # Redistribution and use in source and binary forms, with or without
107 # modification, are permitted provided that the following conditions are met:
108@@ -130,20 +131,37 @@
109 set(out_files "")
110 set(out_files_display "")
111 set(${output} "")
112+
113 foreach(src ${ARGS_DEFAULT_ARGS})
114- list(APPEND in_files "${CMAKE_CURRENT_SOURCE_DIR}/${src}")
115+ string(REGEX MATCH "^/" IS_MATCHED ${src})
116+ if(${IS_MATCHED} MATCHES "/")
117+ set(src_file_path ${src})
118+ else()
119+ set(src_file_path ${CMAKE_CURRENT_SOURCE_DIR}/${src})
120+ endif()
121+ list(APPEND in_files ${src_file_path})
122 string(REPLACE ".vala" ".c" src ${src})
123 string(REPLACE ".gs" ".c" src ${src})
124- set(out_file "${DIRECTORY}/${src}")
125- list(APPEND out_files "${DIRECTORY}/${src}")
126+ if(${IS_MATCHED} MATCHES "/")
127+ get_filename_component(VALA_FILE_NAME ${src} NAME)
128+ set(out_file "${CMAKE_CURRENT_BINARY_DIR}/${VALA_FILE_NAME}")
129+ list(APPEND out_files "${CMAKE_CURRENT_BINARY_DIR}/${VALA_FILE_NAME}")
130+ else()
131+ set(out_file "${DIRECTORY}/${src}")
132+ list(APPEND out_files "${DIRECTORY}/${src}")
133+ endif()
134+ list(APPEND ${output} ${out_file})
135 list(APPEND out_files_display "${src}")
136- list(APPEND ${output} ${out_file})
137 endforeach(src ${ARGS_DEFAULT_ARGS})
138
139 set(custom_vapi_arguments "")
140 if(ARGS_CUSTOM_VAPIS)
141 foreach(vapi ${ARGS_CUSTOM_VAPIS})
142- list(APPEND custom_vapi_arguments ${vapi})
143+ if(${vapi} MATCHES ${CMAKE_SOURCE_DIR} OR ${vapi} MATCHES ${CMAKE_BINARY_DIR})
144+ list(APPEND custom_vapi_arguments ${vapi})
145+ else (${vapi} MATCHES ${CMAKE_SOURCE_DIR} OR ${vapi} MATCHES ${CMAKE_BINARY_DIR})
146+ list(APPEND custom_vapi_arguments ${CMAKE_CURRENT_SOURCE_DIR}/${vapi})
147+ endif(${vapi} MATCHES ${CMAKE_SOURCE_DIR} OR ${vapi} MATCHES ${CMAKE_BINARY_DIR})
148 endforeach(vapi ${ARGS_CUSTOM_VAPIS})
149 endif(ARGS_CUSTOM_VAPIS)
150
151@@ -152,6 +170,11 @@
152 list(APPEND out_files "${DIRECTORY}/${ARGS_GENERATE_VAPI}.vapi")
153 list(APPEND out_files_display "${ARGS_GENERATE_VAPI}.vapi")
154 set(vapi_arguments "--library=${ARGS_GENERATE_VAPI}" "--vapi=${ARGS_GENERATE_VAPI}.vapi")
155+
156+ # Header and internal header is needed to generate internal vapi
157+ if (NOT ARGS_GENERATE_HEADER)
158+ set(ARGS_GENERATE_HEADER ${ARGS_GENERATE_VAPI})
159+ endif(NOT ARGS_GENERATE_HEADER)
160 endif(ARGS_GENERATE_VAPI)
161
162 set(header_arguments "")
163@@ -162,10 +185,21 @@
164 endif(ARGS_GENERATE_HEADER)
165
166 set(gir_arguments "")
167+ set(gircomp_command "")
168 if(ARGS_GENERATE_GIR)
169 list(APPEND out_files "${DIRECTORY}/${ARGS_GENERATE_GIR}.gir")
170 list(APPEND out_files_display "${ARGS_GENERATE_GIR}.gir")
171 set(gir_arguments "--gir=${ARGS_GENERATE_GIR}.gir")
172+
173+ include (FindGirCompiler)
174+ find_package(GirCompiler REQUIRED)
175+
176+ set(gircomp_command
177+ COMMAND
178+ ${G_IR_COMPILER_EXECUTABLE}
179+ ARGS
180+ "${DIRECTORY}/${ARGS_GENERATE_GIR}.gir"
181+ -o "${DIRECTORY}/${ARGS_GENERATE_GIR}.typelib")
182 endif(ARGS_GENERATE_GIR)
183
184 set(symbols_arguments "")
185@@ -178,7 +212,7 @@
186 # Workaround for a bug that would make valac run twice. This file is written
187 # after the vala compiler generates C source code.
188 set(OUTPUT_STAMP ${CMAKE_CURRENT_BINARY_DIR}/${target_name}_valac.stamp)
189-
190+
191 add_custom_command(
192 OUTPUT
193 ${OUTPUT_STAMP}
194@@ -205,6 +239,7 @@
195 ${ARGS_CUSTOM_VAPIS}
196 COMMENT
197 "Generating ${out_files_display}"
198+ ${gircomp_command}
199 )
200
201 # This command will be run twice for some reason (pass a non-empty string to COMMENT
202
203=== modified file 'demo/GraniteDemo.vala'
204--- demo/GraniteDemo.vala 2013-12-15 12:41:49 +0000
205+++ demo/GraniteDemo.vala 2013-12-22 03:34:36 +0000
206@@ -84,6 +84,7 @@
207 private Gtk.Grid main_layout; // outer-most container
208 private Granite.Widgets.ModeButton mode_button;
209 private int dark_mode_index;
210+ private bool fullscreen = false;
211
212 /**
213 * Basic app information for Granite.Application. This is used by the About dialog.
214@@ -125,10 +126,8 @@
215
216 this.add_window (window);
217
218- var main_toolbar = new Gtk.Toolbar ();
219- main_toolbar.get_style_context ().add_class (Gtk.STYLE_CLASS_PRIMARY_TOOLBAR);
220- main_toolbar.hexpand = true;
221- main_toolbar.vexpand = false;
222+ var main_toolbar = new Granite.Widgets.HeaderBar (window);
223+ main_toolbar.set_title ("Demo");
224
225 // SourceList
226 var sidebar = new Granite.Widgets.SourceList ();
227@@ -169,7 +168,7 @@
228 main_layout = new Gtk.Grid ();
229 main_layout.expand = true;
230 main_layout.orientation = Gtk.Orientation.VERTICAL;
231- main_layout.add (main_toolbar);
232+ main_layout.add (main_toolbar.get_revealer ());
233 main_layout.add (sidebar_paned);
234 main_layout.add (statusbar);
235
236@@ -185,14 +184,12 @@
237 sidebar.selected = welcome_item;
238
239 // Light window
240- var light_window_icon = new Gtk.Image.from_icon_name ("document-new", Gtk.IconSize.LARGE_TOOLBAR);
241- var light_window_item = new Gtk.ToolButton (light_window_icon, "Show LightWindow");
242- light_window_item.icon_name = "document-new";
243+ var light_window_item = new Gtk.Button.from_icon_name ("document-new", Gtk.IconSize.LARGE_TOOLBAR);
244 light_window_item.tooltip_text = "Show Light Window";
245 light_window_item.halign = light_window_item.valign = Gtk.Align.CENTER;
246 light_window_item.clicked.connect (show_light_window);
247
248- main_toolbar.insert (light_window_item, -1);
249+ main_toolbar.pack_start (light_window_item);
250
251 // StaticNotebook
252 var staticnotebook = new Granite.Widgets.StaticNotebook ();
253@@ -224,11 +221,7 @@
254
255 mode_button.mode_changed.connect (on_theme_mode_button_changed);
256
257- var mode_button_item = new Gtk.ToolItem ();
258- mode_button_item.add (mode_button);
259- main_toolbar.insert (mode_button_item, -1);
260-
261- mode_button_item.halign = mode_button_item.valign = Gtk.Align.CENTER;
262+ main_toolbar.pack_start (mode_button);
263
264 // PopOvers
265 var popover_statusbar_item = new Gtk.Button ();
266@@ -263,19 +256,14 @@
267 });
268
269 // Date widget
270- var calendar_tool_item = new Gtk.ToolItem ();
271- calendar_tool_item.margin_left = 12;
272 var date_button = new Granite.Widgets.DatePicker.with_format ("%d-%m-%y");
273- calendar_tool_item.add (date_button);
274- main_toolbar.insert (calendar_tool_item, -1);
275+ date_button.margin_left = 12;
276+ main_toolbar.pack_start (date_button);
277
278 // Time widget
279- var time_tool_item = new Gtk.ToolItem ();
280- time_tool_item.margin_left = 12;
281- time_tool_item.valign = Gtk.Align.CENTER;
282 var time_button = new Granite.Widgets.TimePicker ();
283- time_tool_item.add (time_button);
284- main_toolbar.insert (time_tool_item, -1);
285+ time_button.margin_left = 12;
286+ main_toolbar.pack_start (time_button);
287
288 // Dynamic notebook
289 var dynamic_notebook = create_dynamic_notebook ();
290@@ -283,22 +271,29 @@
291 widgets_category.add (dynamic_notebook_item);
292 dynamic_notebook_item.page_num = page_switcher.append_page (dynamic_notebook, null);
293
294- var right_sep = new Gtk.SeparatorToolItem ();
295- right_sep.draw = false;
296- right_sep.set_expand (true);
297- main_toolbar.insert (right_sep, -1);
298-
299 // Search Entry
300 var search_entry = new Granite.Widgets.SearchBar ("Search");
301- var search_item = new Gtk.ToolItem ();
302- search_item.add (search_entry);
303- search_item.margin_left = 12;
304- main_toolbar.insert (search_item, -1);
305+ search_entry.margin_left = 12;
306+ main_toolbar.pack_end (search_entry);
307
308 // App Menu (this gives access to the About dialog)
309- var main_menu = create_appmenu (new Gtk.Menu ());
310+ var menu = new Gtk.Menu ();
311+ var fullscreen_item = new Gtk.MenuItem.with_label ("Fullscreen");
312+ fullscreen_item.activate.connect (() => {
313+ if (fullscreen == false) {
314+ window.fullscreen ();
315+ fullscreen = true;
316+ } else {
317+ window.unfullscreen ();
318+ fullscreen = false;
319+ }
320+
321+ });
322+ menu.add (fullscreen_item);
323+
324+ var main_menu = create_appmenu (menu);
325 main_menu.margin_left = 12;
326- main_toolbar.insert (main_menu, -1);
327+ main_toolbar.pack_end (main_menu);
328
329 window.set_default_size (800, 550);
330 window.show_all ();
331@@ -464,4 +459,4 @@
332
333 return application.run (args);
334 }
335-}
336+}
337\ No newline at end of file
338
339=== modified file 'lib/CMakeLists.txt'
340--- lib/CMakeLists.txt 2013-07-16 23:31:04 +0000
341+++ lib/CMakeLists.txt 2013-12-22 03:34:36 +0000
342@@ -31,6 +31,7 @@
343 Widgets/DynamicNotebook.vala
344 Widgets/CompositedWindow.vala
345 Widgets/AppMenu.vala
346+ Widgets/HeaderBar.vala
347 Widgets/Welcome.vala
348 Widgets/ToolButtonWithMenu.vala
349 Widgets/PopOver.vala
350@@ -84,6 +85,8 @@
351 ${PKG_NAME}
352 GENERATE_VAPI
353 ${PKG_NAME}
354+GENERATE_GIR
355+ ${PKG_GIR_NAME}
356 CUSTOM_VAPIS
357 ${CMAKE_CURRENT_SOURCE_DIR}/config.vapi
358 OPTIONS
359@@ -94,6 +97,8 @@
360 install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/${PKG_NAME}.deps DESTINATION ${CMAKE_INSTALL_PREFIX}/share/vala/vapi)
361 install (FILES ${CMAKE_CURRENT_BINARY_DIR}/${PKG_NAME}.h DESTINATION ${CMAKE_INSTALL_PREFIX}/include/${PKG_NAME})
362 install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/Widgets/widgets-utils.h DESTINATION ${CMAKE_INSTALL_PREFIX}/include/${PKG_NAME})
363+install (FILES ${CMAKE_CURRENT_BINARY_DIR}/${PKG_GIR_NAME}.gir DESTINATION ${CMAKE_INSTALL_PREFIX}/share/gir-1.0/)
364+install (FILES ${CMAKE_CURRENT_BINARY_DIR}/${PKG_GIR_NAME}.typelib DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/girepository-1.0/)
365
366 set (LIB_FILES ${C_SOURCES} ${VALA_C})
367
368@@ -106,14 +111,3 @@
369 SOVERSION ${PKG_SOVERSION})
370
371 install (TARGETS ${PKG_NAME} DESTINATION ${LIB_INSTALL_DIR})
372-
373-###########################
374-# GObject Introspection
375-###########################
376-
377-include (FindGObjectIntrospection)
378-
379-if (INTROSPECTION_FOUND)
380- include (GObjectIntrospectionMacros)
381- add_target_gir (${PKG_NAME} ${PKG_GIR_NAME} ${PKG_NAME}.h "${VALA_C}" "${DEPS_CFLAGS}" ${API_VERSION} ${GI_PKG_DEPS})
382-endif ()
383
384=== added file 'lib/Widgets/HeaderBar.vala'
385--- lib/Widgets/HeaderBar.vala 1970-01-01 00:00:00 +0000
386+++ lib/Widgets/HeaderBar.vala 2013-12-22 03:34:36 +0000
387@@ -0,0 +1,314 @@
388+/***
389+ Copyright (C) 2011-2013 Granite Developers
390+
391+ This program or library is free software; you can redistribute it
392+ and/or modify it under the terms of the GNU Lesser General Public
393+ License as published by the Free Software Foundation; either
394+ version 3 of the License, or (at your option) any later version.
395+
396+ This library is distributed in the hope that it will be useful,
397+ but WITHOUT ANY WARRANTY; without even the implied warranty of
398+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
399+ Lesser General Public License for more details.
400+
401+ You should have received a copy of the GNU Lesser General
402+ Public License along with this library; if not, write to the
403+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
404+ Boston, MA 02110-1301 USA.
405+
406+ Authored by: Corentin Noël <tintou@mailoo.org>
407+***/
408+
409+namespace Granite.Widgets {
410+
411+ /**
412+ * This class is a standard header bar.
413+ */
414+ public class HeaderBar : Gtk.HeaderBar {
415+
416+ // Same value as int the Gtk+3 source
417+ private const int DEFAULT_SPACING = 6;
418+
419+ private Gtk.Revealer revealer;
420+ private Gtk.Window window;
421+ private Gtk.Toolbar toolbar;
422+ private Gee.HashMap<int, unowned Gtk.Widget> widgets_left;
423+ private Gee.HashMap<int, unowned Gtk.Widget> widgets_right;
424+ private int left_size = 0;
425+ private int right_size = 0;
426+ private Gtk.Grid left_grid_toolbar;
427+ private Gtk.Grid right_grid_toolbar;
428+ private Gtk.Grid widget_grid_toolbar;
429+ private Gtk.Grid left_grid_header;
430+ private Gtk.Grid right_grid_header;
431+ private Gtk.Grid widget_grid_header;
432+ private Gtk.Button resize_button;
433+ private Gtk.Widget header_center_widget;
434+
435+ private bool toolbar_shown = false;
436+ private bool widgets_on_toolbar = false;
437+
438+ /**
439+ * This method sets an HeaderBar to the window
440+ *
441+ * @param window window to set the HeaderBar
442+ * @since 0.3
443+ */
444+ public HeaderBar (Gtk.Window window) {
445+
446+ widgets_left = new Gee.HashMap<int, unowned Gtk.Widget> ();
447+ widgets_right = new Gee.HashMap<int, unowned Gtk.Widget> ();
448+
449+ show_close_button = true;
450+
451+ this.window = window;
452+ window.set_titlebar (this);
453+ this.get_style_context ().add_class ("header-bar");
454+ this.get_style_context ().add_class (Gtk.STYLE_CLASS_HORIZONTAL);
455+
456+ revealer = new Gtk.Revealer ();
457+ toolbar = new Gtk.Toolbar ();
458+ toolbar.get_style_context ().add_class ("header-bar");
459+ toolbar.hexpand = true;
460+ toolbar.vexpand = false;
461+
462+ left_grid_toolbar = new Gtk.Grid ();
463+ left_grid_toolbar.get_style_context ().add_class ("header-bar");
464+ left_grid_toolbar.column_spacing = DEFAULT_SPACING;
465+ right_grid_toolbar = new Gtk.Grid ();
466+ right_grid_toolbar.get_style_context ().add_class ("header-bar");
467+ right_grid_toolbar.column_spacing = DEFAULT_SPACING;
468+
469+ widget_grid_toolbar = new Gtk.Grid ();
470+ header_center_widget = custom_title;
471+ widget_grid_header = new Gtk.Grid ();
472+
473+ left_grid_header = new Gtk.Grid ();
474+ left_grid_header.expand = true;
475+ left_grid_header.get_style_context ().add_class ("header-bar");
476+ left_grid_header.column_spacing = DEFAULT_SPACING;
477+ base.pack_start (left_grid_header);
478+ right_grid_header = new Gtk.Grid ();
479+ right_grid_header.expand = true;
480+ right_grid_header.get_style_context ().add_class ("header-bar");
481+ right_grid_header.column_spacing = DEFAULT_SPACING;
482+ base.pack_end (right_grid_header);
483+
484+ get_resize_button ();
485+
486+ var left_toolitem = new Gtk.ToolItem ();
487+ left_toolitem.add (left_grid_toolbar);
488+
489+ var widget_toolitem = new Gtk.ToolItem ();
490+ widget_toolitem.add (widget_grid_toolbar);
491+
492+ var right_toolitem = new Gtk.ToolItem ();
493+ right_toolitem.add (right_grid_toolbar);
494+
495+ var fake_toolitem = new Gtk.ToolItem ();
496+ fake_toolitem.set_expand (true);
497+ fake_toolitem.hexpand = false;
498+
499+ var fake2_toolitem = new Gtk.ToolItem ();
500+ fake2_toolitem.set_expand (true);
501+ fake2_toolitem.hexpand = false;
502+
503+ toolbar.insert (fake_toolitem, 0);
504+ toolbar.insert (widget_toolitem, 0);
505+ toolbar.insert (fake2_toolitem, 0);
506+ toolbar.insert (left_toolitem, 0);
507+ toolbar.insert (right_toolitem, -1);
508+
509+ revealer.add (toolbar);
510+
511+ window.add_events (Gdk.EventMask.STRUCTURE_MASK);
512+ window.add_events (Gdk.EventMask.POINTER_MOTION_MASK);
513+
514+ window.motion_notify_event.connect (update_pointer_position);
515+ window.window_state_event.connect (got_window_state_event);
516+ }
517+
518+ private bool got_window_state_event (Gdk.EventWindowState event) {
519+ if (toolbar_shown == true &&
520+ (((window.get_window ().get_state () & Gdk.WindowState.FULLSCREEN) != 0) == false)) {
521+ hide_revealer ();
522+ revealer.hide ();
523+ }
524+ if ((((window.get_window ().get_state () & Gdk.WindowState.FULLSCREEN) != 0) == false) &&
525+ ((window.get_window ().get_state () & Gdk.WindowState.MAXIMIZED) != 0)) {
526+ toggle_maximized_button (true);
527+ } else if ((((window.get_window ().get_state () & Gdk.WindowState.FULLSCREEN) != 0) == false) &&
528+ (((window.get_window ().get_state () & Gdk.WindowState.MAXIMIZED) != 0)) == false) {
529+ toggle_maximized_button (false);
530+ }
531+ return false;
532+ }
533+
534+ private void get_resize_button () {
535+ bool maximized = ((window.get_window ().get_state () & Gdk.WindowState.MAXIMIZED) != 0);
536+
537+ var icon_name = maximized ? "window-restore-symbolic" : "window-maximize-symbolic";
538+ resize_button = new Gtk.Button.from_icon_name (icon_name, Gtk.IconSize.MENU);
539+ resize_button.get_style_context ().add_class ("titlebutton");
540+ resize_button.set_can_focus (false);
541+ resize_button.clicked.connect (toggle_maximized);
542+ resize_button.set_valign (Gtk.Align.CENTER);
543+
544+ if (window.resizable == true) {
545+ resize_button.show ();
546+ } else {
547+ resize_button.hide ();
548+ }
549+
550+ base.pack_end (resize_button);
551+ }
552+
553+ private void toggle_maximized () {
554+ if (((window.get_window ().get_state () & Gdk.WindowState.MAXIMIZED) != 0)) {
555+ window.unmaximize ();
556+ } else {
557+ window.maximize ();
558+ }
559+ }
560+
561+ private void toggle_maximized_button (bool maximized) {
562+
563+ if (window.resizable == true) {
564+ resize_button.show ();
565+ } else {
566+ resize_button.hide ();
567+ }
568+
569+ if (maximized) {
570+ resize_button.set_image (new Gtk.Image.from_icon_name ("window-restore-symbolic", Gtk.IconSize.MENU));
571+ } else {
572+ resize_button.set_image (new Gtk.Image.from_icon_name ("window-maximize-symbolic", Gtk.IconSize.MENU));
573+ }
574+ }
575+
576+ private bool update_pointer_position (Gdk.EventMotion event) {
577+ int size = 5;
578+ if (toolbar_shown == true) {
579+ int minimum_height = 0;
580+ int natural_height = 0;
581+ toolbar.get_preferred_height (out minimum_height, out natural_height);
582+ size = natural_height;
583+ if (size < 5)
584+ size = 5;
585+ }
586+
587+ if (toolbar_shown == false && event.y <= size &&
588+ ((window.get_window ().get_state () & Gdk.WindowState.FULLSCREEN) != 0)) {
589+ revealer.show ();
590+ show_revealer ();
591+ } else if (toolbar_shown == true && event.y > size &&
592+ ((window.get_window ().get_state () & Gdk.WindowState.FULLSCREEN) != 0)) {
593+ revealer.show ();
594+ hide_revealer ();
595+ } else if (toolbar_shown == true &&
596+ (((window.get_window ().get_state () & Gdk.WindowState.FULLSCREEN) != 0) == false)) {
597+ hide_revealer ();
598+ revealer.hide ();
599+ }
600+ return false;
601+ }
602+
603+ private void show_revealer () {
604+ if (widgets_on_toolbar == false) {
605+ foreach (var entry in widgets_left.entries) {
606+ if (entry.value == null)
607+ continue;
608+ entry.value.reparent (left_grid_toolbar);
609+ }
610+ foreach (var entry in widgets_right.entries) {
611+ if (entry.value == null)
612+ continue;
613+ entry.value.reparent (right_grid_toolbar);
614+ }
615+ if (header_center_widget != null)
616+ header_center_widget.reparent (widget_grid_toolbar);
617+ widgets_on_toolbar = true;
618+ }
619+ revealer.set_transition_type (Gtk.RevealerTransitionType.SLIDE_DOWN);
620+ toolbar_shown = true;
621+ revealer.set_reveal_child (true);
622+ }
623+
624+ private void hide_revealer () {
625+ if (widgets_on_toolbar == true) {
626+ foreach (var entry in widgets_left.entries) {
627+ if (entry.value == null)
628+ continue;
629+ entry.value.reparent (left_grid_header);
630+ }
631+ foreach (var entry in widgets_right.entries) {
632+ if (entry.value == null)
633+ continue;
634+ entry.value.reparent (right_grid_header);
635+ }
636+ if (header_center_widget != null)
637+ header_center_widget.reparent (widget_grid_header);
638+ widgets_on_toolbar = false;
639+ }
640+ revealer.set_transition_type (Gtk.RevealerTransitionType.SLIDE_UP);
641+ toolbar_shown = false;
642+ revealer.set_reveal_child (false);
643+ }
644+
645+ /**
646+ * Get the Toolbar that will be shown in fullscreen mode.
647+ *
648+ * @return A {@link Gtk.Revealer} that should be set in the top of the window, expanded horizontally.
649+ * @since 0.3
650+ */
651+ public Gtk.Revealer get_revealer () {
652+ return revealer;
653+ }
654+
655+ /**
656+ * {@inheritDoc}
657+ * @since 0.3
658+ */
659+ public new weak Gtk.Widget get_custom_title () {
660+ return header_center_widget;
661+ }
662+
663+ /**
664+ * {@inheritDoc}
665+ * @since 0.3
666+ */
667+ public new void set_custom_title (Gtk.Widget title_widget) {
668+ widget_grid_header = new Gtk.Grid ();
669+ widget_grid_header.add (title_widget);
670+ header_center_widget = title_widget;
671+ if (title_widget == null)
672+ base.set_custom_title (null);
673+ else
674+ base.set_custom_title (widget_grid_header);
675+ }
676+
677+ /**
678+ * {@inheritDoc}
679+ * @since 0.3
680+ */
681+ public new void pack_end (Gtk.Widget child) {
682+ widgets_right.set (right_size, child);
683+ child.valign = Gtk.Align.CENTER;
684+ child.vexpand = true;
685+ right_grid_header.attach (child, right_size, 0, 1, 1);
686+ right_size++;
687+ }
688+
689+ /**
690+ * {@inheritDoc}
691+ * @since 0.3
692+ */
693+ public new void pack_start (Gtk.Widget child) {
694+ widgets_left.set (left_size, child);
695+ child.valign = Gtk.Align.CENTER;
696+ child.vexpand = true;
697+ left_grid_header.attach (child, left_size, 0, 1, 1);
698+ left_size++;
699+ }
700+ }
701+}
702\ No newline at end of file

Subscribers

People subscribed via source and target branches