diff --git a/data/ui/Window.ui b/data/ui/Window.ui
index 16fd925..466d1b3 100644
--- a/data/ui/Window.ui
+++ b/data/ui/Window.ui
@@ -417,14 +417,7 @@
False
start
-
+
diff --git a/uberwriter/headerbars.py b/uberwriter/headerbars.py
index 19991ae..ba81346 100644
--- a/uberwriter/headerbars.py
+++ b/uberwriter/headerbars.py
@@ -16,46 +16,121 @@
"""Manage all the headerbars related stuff
"""
-from collections import namedtuple
-from gettext import gettext as _
-
import gi
gi.require_version('Gtk', '3.0')
-from gi.repository import Gtk
+from gi.repository import Gtk, GLib
from uberwriter.helpers import get_descendant
-class MainHeaderbar: #pylint: disable=too-few-public-methods
+class BaseHeaderbar:
+ """Base class for all headerbars
+ """
+ def __init__(self, app):
+
+ self.builder = Gtk.Builder()
+ self.builder.add_from_resource(
+ "/de/wolfvollprecht/UberWriter/ui/Headerbar.ui")
+
+ self.hb = self.builder.get_object("Headerbar")
+ self.hb_revealer = self.builder.get_object("titlebar_revealer")
+
+ self.menu_button = self.builder.get_object("menu_button")
+ self.recents_button = self.builder.get_object("recents_button")
+
+
+class MainHeaderbar(BaseHeaderbar): # pylint: disable=too-few-public-methods
"""Sets up the main application headerbar
"""
def __init__(self, app):
- builder = Gtk.Builder()
- builder.add_from_resource(
- "/de/wolfvollprecht/UberWriter/ui/Headerbar.ui")
+ BaseHeaderbar.__init__(self, app)
- self.hb = builder.get_object("Headerbar")
-
- self.menu_button = builder.get_object("menu_button")
- self.recents_button = builder.get_object("recents_button")
+ self.hb.set_show_close_button(True)
add_menus(self, app)
- self.hb_revealer = Gtk.Revealer(name='titlebar-revealer')
- self.hb_revealer.add(self.hb)
- self.hb_revealer.props.transition_duration = 750
- self.hb_revealer.props.transition_type = Gtk.RevealerTransitionType.CROSSFADE
- self.hb_revealer.show()
+ self.hb_revealer.props.transition_duration = 0
+
+
+class FullscreenHeaderbar(BaseHeaderbar):
+ """Sets up and manages the fullscreen headerbar and his events
+ """
+
+ def __init__(self, fs_builder, app):
+
+ BaseHeaderbar.__init__(self, app)
+
+ self.hb.set_show_close_button(False)
+
+ self.exit_fs_button = self.builder.get_object("exit_fs_button")
+ self.exit_fs_button.set_visible(True)
+
+ add_menus(self, app)
+
+ self.events = fs_builder.get_object("FullscreenEventbox")
+ self.events.add(self.hb_revealer)
+
+ # this is a little tricky
+ # we show hb when the cursor enters an area of 1px at the top
+ # as the hb is shown the height of the eventbox grows to accomodate it
+ self.events.connect('enter_notify_event', self.show_fs_hb)
+ self.events.connect('leave_notify_event', self.hide_fs_hb)
+ self.menu_button.get_popover().connect('closed', self.hide_fs_hb)
+
+ def show_fs_hb(self, _widget, _data=None):
+ """show headerbar of the fullscreen mode
+ """
self.hb_revealer.set_reveal_child(True)
- self.hb_container = Gtk.Frame(name='titlebar-container')
- self.hb_container.set_shadow_type(Gtk.ShadowType.NONE)
- self.hb_container.add(self.hb_revealer)
- self.hb_container.show()
+ def hide_fs_hb(self, _widget, _data=None):
+ """hide headerbar of the fullscreen mode
+ """
+ if self.menu_button.get_active():
+ pass
+ else:
+ self.hb_revealer.set_reveal_child(False)
- self.hb.show_all()
+
+class DummyHeaderbar(BaseHeaderbar):
+ """Sets up and manages the dummy headerbar wich fades away when entering
+ the free-distracting mode
+ """
+
+ def __init__(self, app):
+
+ BaseHeaderbar.__init__(self, app)
+
+ self.hb.set_show_close_button(True)
+ self.hb_revealer.set_transition_type(
+ Gtk.RevealerTransitionType.CROSSFADE)
+ self.hb_revealer.set_reveal_child(False)
+
+ self.menu_button.set_sensitive(True)
+ self.recents_button.set_sensitive(True)
+
+ def show_dm_hb(self):
+ """show dummy headerbar:
+ It appears instantly to inmediatly fade away
+ """
+ self.hb_revealer.set_transition_duration(0)
+ self.hb_revealer.set_reveal_child(True)
+ self.hb_revealer.set_transition_duration(600)
+ self.hb_revealer.set_reveal_child(False)
+
+ def hide_dm_hb(self):
+ """hide dummy headerbar
+ It appears slowly to inmediatly dissapear
+ """
+ self.hb_revealer.set_transition_duration(400)
+ self.hb_revealer.set_reveal_child(True)
+ GLib.timeout_add(400, self.hide_dm_hb_with_wait)
+
+ def hide_dm_hb_with_wait(self):
+ self.hb_revealer.set_transition_duration(0)
+ self.hb_revealer.set_reveal_child(False)
+ return False
class PreviewHeaderbar:
@@ -67,10 +142,11 @@ class PreviewHeaderbar:
self.hb.props.show_close_button = True
self.hb.get_style_context().add_class("titlebar")
- self.hb_revealer = Gtk.Revealer(name="titlebar-revealer")
+ self.hb_revealer = Gtk.Revealer(name="titlebar-revealer-pv")
self.hb_revealer.add(self.hb)
self.hb_revealer.props.transition_duration = 750
- self.hb_revealer.props.transition_type = Gtk.RevealerTransitionType.CROSSFADE
+ self.hb_revealer.set_transition_type(
+ Gtk.RevealerTransitionType.CROSSFADE)
self.hb_revealer.show()
self.hb_revealer.set_reveal_child(True)
@@ -82,55 +158,9 @@ class PreviewHeaderbar:
self.hb.show_all()
-class FullscreenHeaderbar:
- """Sets up and manages the fullscreen headerbar and his events
- """
-
- def __init__(self, fs_builder, app):
-
- builder = Gtk.Builder()
- builder.add_from_resource(
- "/de/wolfvollprecht/UberWriter/ui/Headerbar.ui")
-
- self.hb = builder.get_object("Headerbar")
- self.hb.set_show_close_button(False)
- self.hb.show_all()
-
- self.menu_button = builder.get_object("menu_button")
- self.recents_button = builder.get_object("recents_button")
-
- self.exit_fs_button = builder.get_object("exit_fs_button")
- self.exit_fs_button.set_visible(True)
-
- add_menus(self, app)
-
- self.events = fs_builder.get_object("FullscreenEventbox")
- self.revealer = fs_builder.get_object(
- "FullscreenHbPlaceholder")
- self.revealer.add(self.hb)
-
- # this is a little tricky
- # we show hb when the cursor enters an area of 1 px at the top of the window
- # as the hb is shown the height of the eventbox grows to accomodate it
- self.events.connect('enter_notify_event', self.show_fs_hb)
- self.events.connect('leave_notify_event', self.hide_fs_hb)
- self.menu_button.get_popover().connect('closed', self.hide_fs_hb)
-
- def show_fs_hb(self, _widget, _data=None):
- """show headerbar of the fullscreen mode
- """
- self.revealer.set_reveal_child(True)
-
- def hide_fs_hb(self, _widget, _data=None):
- """hide headerbar of the fullscreen mode
- """
- if self.menu_button.get_active():
- pass
- else:
- self.revealer.set_reveal_child(False)
-
-
def add_menus(headerbar, app):
+ """ Add menu models to hb buttons
+ """
# Add menu model to the menu button
diff --git a/uberwriter/main_window.py b/uberwriter/main_window.py
index 5ac71f1..55646f6 100644
--- a/uberwriter/main_window.py
+++ b/uberwriter/main_window.py
@@ -84,10 +84,21 @@ class MainWindow(StyledWindow):
self.settings = Settings.new()
# Headerbars
+ self.last_height = 0
self.headerbar = headerbars.MainHeaderbar(app)
- self.set_titlebar(self.headerbar.hb_container)
+ self.headerbar.hb_revealer.connect(
+ "size_allocate", self.header_size_allocate)
+ self.set_titlebar(self.headerbar.hb_revealer)
+
self.fs_headerbar = headerbars.FullscreenHeaderbar(builder, app)
+ # The dummy headerbar is a cosmetic hack to be able to
+ # crossfade the hb on top of the window
+ self.dm_headerbar = headerbars.DummyHeaderbar(app)
+ root.add_overlay(self.dm_headerbar.hb_revealer)
+ root.reorder_overlay(self.dm_headerbar.hb_revealer, 0)
+ root.set_overlay_pass_through(self.dm_headerbar.hb_revealer, True)
+
self.title_end = " – UberWriter"
self.set_headerbar_title("New File" + self.title_end)
@@ -103,6 +114,7 @@ class MainWindow(StyledWindow):
# Setup text editor
self.text_view = TextView(self.settings.get_int("characters-per-line"))
+ self.text_view.set_top_margin(80)
self.text_view.connect('focus-out-event', self.focus_out)
self.text_view.get_buffer().connect('changed', self.on_text_changed)
self.text_view.show()
@@ -151,6 +163,24 @@ class MainWindow(StyledWindow):
###
self.searchreplace = SearchAndReplace(self, self.text_view, builder)
+ def header_size_allocate(self, widget, allocation):
+ """ When the main hb starts to shrink its size, add that size
+ to the textview margin, so it stays in place
+ """
+
+ # prevent 1px jumps
+ if allocation.height == 1 and not widget.get_child_revealed():
+ allocation.height = 0
+
+ height = self.headerbar.hb.get_allocated_height() - allocation.height
+ if height == self.last_height:
+ return
+
+ self.last_height = height
+
+ self.text_view.update_vertical_margin(height)
+ self.text_view.queue_draw()
+
def on_text_changed(self, *_args):
"""called when the text changes, sets the self.did_change to true and
updates the title and the counters to reflect that
@@ -183,7 +213,7 @@ class MainWindow(StyledWindow):
"""toggle focusmode
"""
- self.text_view.set_focus_mode(state.get_boolean())
+ self.text_view.set_focus_mode(state.get_boolean(), self.headerbar.hb.get_allocated_height())
self.text_view.grab_focus()
def set_hemingway_mode(self, state):
@@ -519,7 +549,6 @@ class MainWindow(StyledWindow):
def open_recent(self, _widget, data=None):
"""open the given recent document
"""
- print("open")
if data:
if self.check_change() == Gtk.ResponseType.CANCEL:
@@ -563,8 +592,30 @@ class MainWindow(StyledWindow):
self.reveal_top_bottom_bars(True)
def reveal_top_bottom_bars(self, reveal):
+ """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():
+ self.headerbar.hb_revealer.set_reveal_child(True)
+ self.get_style_context().remove_class("focus")
+ return False
+
if self.top_bottom_bars_visible != reveal:
- self.headerbar.hb_revealer.set_reveal_child(reveal)
+ if reveal:
+ self.dm_headerbar.hide_dm_hb()
+ GLib.timeout_add(400, reveal_hb)
+ else:
+ self.headerbar.hb_revealer.set_reveal_child(False)
+ self.dm_headerbar.show_dm_hb()
+ self.get_style_context().add_class("focus")
+
self.stats_revealer.set_reveal_child(reveal)
for revealer in self.preview_handler.get_top_bottom_bar_revealers():
revealer.set_reveal_child(reveal)
diff --git a/uberwriter/text_view.py b/uberwriter/text_view.py
index 1c4e9bc..87cabce 100644
--- a/uberwriter/text_view.py
+++ b/uberwriter/text_view.py
@@ -54,6 +54,9 @@ class TextView(Gtk.TextView):
self.set_pixels_inside_wrap(8)
self.get_style_context().add_class('uberwriter-editor')
+ self.set_margin_left(8)
+ self.set_margin_right(8)
+
# Text sizing
self.props.halign = Gtk.Align.FILL
self.line_chars = line_chars
@@ -144,7 +147,6 @@ class TextView(Gtk.TextView):
def on_size_allocate(self, *_):
self.update_horizontal_margin()
- self.update_vertical_margin()
self.markup.update_margins_indents()
self.queue_draw()
@@ -192,14 +194,14 @@ class TextView(Gtk.TextView):
self.frozen_scroll_scale = None
self.queue_draw()
- def set_focus_mode(self, focus_mode):
+ def set_focus_mode(self, focus_mode, hb_height):
"""Toggle focus mode.
When in focus mode, the cursor sits in the middle of the text view,
and the surrounding text is greyed out."""
self.focus_mode = focus_mode
- self.update_vertical_margin()
+ self.update_vertical_margin(hb_size=hb_height)
self.markup.apply()
self.smooth_scroll_to()
self.set_spellcheck(self.spellcheck)
@@ -227,13 +229,14 @@ class TextView(Gtk.TextView):
self.props.left_margin = horizontal_margin
self.props.right_margin = horizontal_margin
- def update_vertical_margin(self):
+ def update_vertical_margin(self, top_margin=0, hb_size=0):
if self.focus_mode:
- height = self.get_allocation().height
- self.props.top_margin = height / 2
- self.props.bottom_margin = height / 2
+ height = self.get_allocation().height + top_margin + hb_size
+
+ self.props.top_margin = height / 2 + top_margin
+ self.props.bottom_margin = height / 2 - top_margin
else:
- self.props.top_margin = 80
+ self.props.top_margin = 80 + top_margin
self.props.bottom_margin = 64
def set_hemingway_mode(self, hemingway_mode):