rework the autohiding mechanis for headerbars

ui
Manuel Genovés 2019-12-09 02:16:13 +01:00
parent 151809ae9b
commit 97e809a576
2 changed files with 93 additions and 82 deletions

View File

@ -6,7 +6,6 @@
<object class="GtkImage" id="edit-find-replace"> <object class="GtkImage" id="edit-find-replace">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="xpad">12</property>
<property name="icon_name">edit-find-replace-symbolic</property> <property name="icon_name">edit-find-replace-symbolic</property>
</object> </object>
<object class="GtkImage" id="go-up"> <object class="GtkImage" id="go-up">
@ -30,12 +29,12 @@
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="stock">gtk-spell-check</property> <property name="stock">gtk-spell-check</property>
</object> </object>
<object class="GtkOverlay" id="FullscreenOverlay"> <object class="GtkOverlay" id="AppOverlay">
<property name="name">FullscreenOverlay</property> <property name="name">FullscreenOverlay</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<child> <child>
<object class="GtkGrid" id="grid1"> <object class="GtkGrid" id="app_grid">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<child> <child>
@ -71,10 +70,9 @@
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="homogeneous">True</property> <property name="homogeneous">True</property>
<child> <child>
<object class="GtkBox" id="editor"> <object class="GtkOverlay" id="editor">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child> <child>
<object class="GtkScrolledWindow" id="editor_scrolledwindow"> <object class="GtkScrolledWindow" id="editor_scrolledwindow">
<property name="visible">True</property> <property name="visible">True</property>
@ -87,15 +85,15 @@
</child> </child>
</object> </object>
<packing> <packing>
<property name="expand">False</property> <property name="index">-1</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing> </packing>
</child> </child>
<child> <child type="overlay">
<object class="GtkRevealer" id="editor_stats_revealer"> <object class="GtkRevealer" id="editor_stats_revealer">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="events">GDK_ENTER_NOTIFY_MASK | GDK_STRUCTURE_MASK</property>
<property name="valign">end</property>
<property name="transition_type">crossfade</property> <property name="transition_type">crossfade</property>
<property name="transition_duration">750</property> <property name="transition_duration">750</property>
<property name="reveal_child">True</property> <property name="reveal_child">True</property>
@ -116,11 +114,6 @@
</object> </object>
</child> </child>
</object> </object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child> </child>
</object> </object>
<packing> <packing>
@ -236,6 +229,7 @@
<object class="GtkBox" id="searchtools_box"> <object class="GtkBox" id="searchtools_box">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="homogeneous">True</property>
<child> <child>
<object class="GtkToggleButton" id="case_sensitive"> <object class="GtkToggleButton" id="case_sensitive">
<property name="label" translatable="yes">aA</property> <property name="label" translatable="yes">aA</property>
@ -416,10 +410,28 @@
<property name="height_request">1</property> <property name="height_request">1</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="valign">start</property> <property name="valign">start</property>
<property name="visible_window">False</property>
<property name="above_child">True</property>
<child> <child>
<placeholder/> <placeholder/>
</child> </child>
</object> </object>
</child> </child>
<child type="overlay">
<object class="GtkEventBox" id="HeaderbarEventbox">
<property name="height_request">60</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">start</property>
<property name="visible_window">False</property>
<property name="above_child">True</property>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="index">1</property>
</packing>
</child>
</object> </object>
</interface> </interface>

View File

@ -74,7 +74,7 @@ class MainWindow(StyledWindow):
builder = Gtk.Builder() builder = Gtk.Builder()
builder.add_from_resource( builder.add_from_resource(
"/de/wolfvollprecht/UberWriter/ui/Window.ui") "/de/wolfvollprecht/UberWriter/ui/Window.ui")
root = builder.get_object("FullscreenOverlay") root = builder.get_object("AppOverlay")
self.connect("delete-event", self.on_delete_called) self.connect("delete-event", self.on_delete_called)
self.add(root) self.add(root)
@ -102,11 +102,6 @@ class MainWindow(StyledWindow):
self.title_end = " UberWriter" self.title_end = " UberWriter"
self.set_headerbar_title("New File" + self.title_end) self.set_headerbar_title("New File" + self.title_end)
self.timestamp_last_mouse_motion = 0
if self.settings.get_value("poll-motion"):
self.connect("motion-notify-event", self.on_motion_notify)
GObject.timeout_add(3000, self.poll_for_motion)
self.accel_group = Gtk.AccelGroup() self.accel_group = Gtk.AccelGroup()
self.add_accel_group(self.accel_group) self.add_accel_group(self.accel_group)
@ -131,9 +126,10 @@ class MainWindow(StyledWindow):
editor = builder.get_object('editor') editor = builder.get_object('editor')
self.preview_handler = PreviewHandler(self, content, editor, self.text_view) self.preview_handler = PreviewHandler(self, content, editor, self.text_view)
# Setup header/stats bar hide after 3 seconds # Setup header/stats bar
self.top_bottom_bars_visible = True self.headerbar_visible = True
self.was_motion = True self.bottombar_visible = True
self.previewbars_visible = True
self.buffer_modified_for_status_bar = False self.buffer_modified_for_status_bar = False
# some people seems to have performance problems with the overlay. # some people seems to have performance problems with the overlay.
@ -163,6 +159,14 @@ class MainWindow(StyledWindow):
### ###
self.searchreplace = SearchAndReplace(self, self.text_view, builder) self.searchreplace = SearchAndReplace(self, self.text_view, builder)
# EventBoxes
self.headerbar_eventbox = builder.get_object("HeaderbarEventbox")
self.headerbar_eventbox.connect('enter_notify_event',
self.reveal_headerbar_bottombar)
self.stats_revealer.connect('enter_notify_event', self.reveal_bottombar)
def header_size_allocate(self, widget, allocation): def header_size_allocate(self, widget, allocation):
""" When the main hb starts to shrink its size, add that size """ When the main hb starts to shrink its size, add that size
to the textview margin, so it stays in place to the textview margin, so it stays in place
@ -192,6 +196,8 @@ class MainWindow(StyledWindow):
self.set_headerbar_title("* " + title) self.set_headerbar_title("* " + title)
self.buffer_modified_for_status_bar = True self.buffer_modified_for_status_bar = True
if self.settings.get_value("autohide-headerbar"):
self.hide_headerbar_bottombar()
def set_fullscreen(self, state): def set_fullscreen(self, state):
"""Puts the application in fullscreen mode and show/hides """Puts the application in fullscreen mode and show/hides
@ -555,72 +561,62 @@ class MainWindow(StyledWindow):
return return
self.load_file(data) self.load_file(data)
def poll_for_motion(self):
"""check if the user has moved the cursor to show the headerbar
Returns:
True -- Gtk things
"""
if (not self.was_motion
and self.buffer_modified_for_status_bar
and self.text_view.props.has_focus):
self.reveal_top_bottom_bars(False)
self.was_motion = False
return True
def on_motion_notify(self, _widget, event, _data=None):
"""check the motion of the mouse to fade in the headerbar
"""
now = event.get_time()
if now - self.timestamp_last_mouse_motion > 150:
# filter out accidental motions
self.timestamp_last_mouse_motion = now
return
if now - self.timestamp_last_mouse_motion < 100:
# filter out accidental motion
return
if now - self.timestamp_last_mouse_motion > 100:
# react on motion by fading in headerbar and statusbar
self.reveal_top_bottom_bars(True)
self.was_motion = True
def focus_out(self, _widget, _data=None): def focus_out(self, _widget, _data=None):
"""events called when the window losses focus """events called when the window losses focus
""" """
self.reveal_top_bottom_bars(True) self.reveal_headerbar_bottombar()
def reveal_top_bottom_bars(self, reveal): def reveal_headerbar_bottombar(self, _widget=None, _data=None):
"""handles (in conjunction with header_size_allocate)
the fading in and out of the headerbar
"""
# The logic may seem confusing because similar things are
# handled in headerbars.py, but for convenience (adding classes
# to the main window, and delayed calls) some functions are split
# between here and there
# TODO: rework this logic? def __reveal_hb():
def reveal_hb():
self.headerbar.hb_revealer.set_reveal_child(True) self.headerbar.hb_revealer.set_reveal_child(True)
self.get_style_context().remove_class("focus") self.get_style_context().remove_class("focus")
return False return False
if self.top_bottom_bars_visible != reveal: self.reveal_bottombar()
if reveal:
self.dm_headerbar.hide_dm_hb() if not self.headerbar_visible:
GLib.timeout_add(400, reveal_hb) self.dm_headerbar.hide_dm_hb()
else: GLib.timeout_add(400, __reveal_hb)
self.headerbar.hb_revealer.set_reveal_child(False)
self.dm_headerbar.show_dm_hb() self.headerbar_visible = True
self.get_style_context().add_class("focus")
if not self.previewbars_visible:
self.stats_revealer.set_reveal_child(reveal)
for revealer in self.preview_handler.get_top_bottom_bar_revealers(): for revealer in self.preview_handler.get_top_bottom_bar_revealers():
revealer.set_reveal_child(reveal) revealer.set_reveal_child(True)
self.top_bottom_bars_visible = reveal
self.buffer_modified_for_status_bar = reveal self.previewbars_visible = True
def reveal_bottombar(self, _widget=None, _data=None):
if not self.bottombar_visible:
self.stats_revealer.set_reveal_child(True)
self.bottombar_visible = True
self.buffer_modified_for_status_bar = True
def hide_headerbar_bottombar(self):
if self.headerbar_visible:
self.headerbar.hb_revealer.set_reveal_child(False)
self.dm_headerbar.show_dm_hb()
self.get_style_context().add_class("focus")
self.headerbar_visible = False
if self.bottombar_visible:
self.stats_revealer.set_reveal_child(False)
self.bottombar_visible = False
if self.previewbars_visible:
for revealer in self.preview_handler.get_top_bottom_bar_revealers():
revealer.set_reveal_child(False)
self.previewbars_visible = False
self.buffer_modified_for_status_bar = False
def draw_gradient(self, _widget, cr): def draw_gradient(self, _widget, cr):
"""draw fading gradient over the top and the bottom of the """draw fading gradient over the top and the bottom of the
@ -668,13 +664,16 @@ class MainWindow(StyledWindow):
self.destroy() self.destroy()
return return
def set_headerbar_title(self, title, subtitle=""): def set_headerbar_title(self, title, subtitle=None):
"""set the desired headerbar title """set the desired headerbar title
""" """
self.headerbar.hb.props.title = title self.headerbar.hb.props.title = title
self.dm_headerbar.hb.props.title = title
self.fs_headerbar.hb.props.title = title self.fs_headerbar.hb.props.title = title
self.headerbar.hb.props.subtitle = subtitle if subtitle:
self.fs_headerbar.hb.props.subtitle = subtitle self.headerbar.hb.props.subtitle = subtitle
self.dm_headerbar.hb.props.subtitle = subtitle
self.fs_headerbar.hb.props.subtitle = subtitle
self.set_title(title) self.set_title(title)
def set_filename(self, filename=None): def set_filename(self, filename=None):