forked from Mirrors/apostrophe
Merge pull request #183 from UberWriter/ft.autohiding_headerbar
Rework of the headerbar and bottombar This PR: - Makes the textview to go all the way to the top and the bottom of the window, even behind the headerbar, so when it disappears any visible gap is left - Makes the headerbar and bottombar to disappear instantly when writing, and they reappear when moving the cursor to the top/bottom areas. If the cursor moves to the bottom area only the bottombar is shown, when moving the cursor to the top area both headerbar and bottombars are shownui
commit
2912baaa41
|
@ -1,8 +1,10 @@
|
|||
*.pyc
|
||||
__pycache__/
|
||||
_build/*
|
||||
build/
|
||||
*.*~
|
||||
.vscode/
|
||||
.idea/
|
||||
builddir/*
|
||||
build-aux/*
|
||||
build-aux/*
|
||||
flatpak/*
|
||||
|
|
|
@ -62,11 +62,11 @@
|
|||
Input format to use when previewing and exporting using Pandoc.
|
||||
</description>
|
||||
</key>
|
||||
<key name='poll-motion' type='b'>
|
||||
<key name='autohide-headerbar' type='b'>
|
||||
<default>true</default>
|
||||
<summary>Allow Uberwriter to poll cursor motion</summary>
|
||||
<summary>Autohide Headerbar</summary>
|
||||
<description>
|
||||
Hide the header and status bars if the cursor is not moving.
|
||||
Hide the header and status bars when typing.
|
||||
</description>
|
||||
</key>
|
||||
<key name='open-file-path' type='s'>
|
||||
|
|
|
@ -27,6 +27,19 @@
|
|||
caret-color: @theme_fg_color;
|
||||
}
|
||||
|
||||
.uberwriter-window.focus:not(.tiled):not(.tiled-top):not(.tiled-bottom):not(.tiled-left):not(.tiled-right):not(.maximized):not(.fullscreen) {
|
||||
border-top-left-radius: 8px;
|
||||
border-top-right-radius: 8px;
|
||||
}
|
||||
|
||||
.uberwriter-window.focus:not(.tiled):not(.tiled-top):not(.tiled-bottom):not(.tiled-left):not(.tiled-right):not(.maximized):not(.fullscreen):dir(ltr) scrollbar {
|
||||
border-top-right-radius: 8px;
|
||||
}
|
||||
|
||||
.uberwriter-window.focus:not(.tiled):not(.tiled-top):not(.tiled-bottom):not(.tiled-left):not(.tiled-right):not(.maximized):not(.fullscreen):dir(rtl) scrollbar {
|
||||
border-top-left-radius: 8px;
|
||||
}
|
||||
|
||||
#titlebar-revealer {
|
||||
padding: 0;
|
||||
}
|
||||
|
@ -94,6 +107,7 @@
|
|||
|
||||
.inline-button {
|
||||
color: alpha(@theme_fg_color, 0.6);
|
||||
background-color: alpha(@theme_base_color, 0.9);
|
||||
text-shadow: inherit;
|
||||
box-shadow: initial;
|
||||
background-clip: initial;
|
||||
|
|
|
@ -12,121 +12,132 @@
|
|||
<property name="can_focus">False</property>
|
||||
<property name="icon_name">system-search-symbolic</property>
|
||||
</object>
|
||||
<object class="GtkHeaderBar" id="Headerbar">
|
||||
<object class="GtkRevealer" id="titlebar_revealer">
|
||||
<property name="name">titlebar-revealer</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="show_close_button">True</property>
|
||||
<property name="valign">start</property>
|
||||
<property name="transition_type">slide-up</property>
|
||||
<property name="transition_duration">750</property>
|
||||
<property name="reveal_child">True</property>
|
||||
<signal name="size-allocate" handler="header_size_allocate" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="label" translatable="yes">New</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="action_name">app.new</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<object class="GtkHeaderBar" id="Headerbar">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="label" translatable="yes">Open</property>
|
||||
<property name="label" translatable="yes">New</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="action_name">app.open</property>
|
||||
<property name="action_name">app.new</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuButton" id="recents_button">
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="tooltip_text" translatable="yes">Open Recent</property>
|
||||
<property name="action_name">app.on_open_recent</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
<object class="GtkButton">
|
||||
<property name="label" translatable="yes">Open</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="action_name">app.open</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuButton" id="recents_button">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="tooltip_text" translatable="yes">Open Recent</property>
|
||||
<property name="action_name">app.on_open_recent</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<style>
|
||||
<class name="linked"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<style>
|
||||
<class name="linked"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="exit_fs_button">
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="no_show_all">True</property>
|
||||
<property name="action_name">app.fullscreen</property>
|
||||
<property name="image">exit_fs_icon</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="pack_type">end</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuButton" id="menu_button">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="tooltip_text" translatable="yes">Menu</property>
|
||||
<property name="icon_name">open-menu-symbolic</property>
|
||||
<object class="GtkButton" id="exit_fs_button">
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="no_show_all">True</property>
|
||||
<property name="action_name">app.fullscreen</property>
|
||||
<property name="image">exit_fs_icon</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="pack_type">end</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuButton" id="menu_button">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="tooltip_text" translatable="yes">Menu</property>
|
||||
<property name="icon_name">open-menu-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="pack_type">end</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="tooltip_text" translatable="yes">Find</property>
|
||||
<property name="action_name">app.search</property>
|
||||
<property name="image">search_icon</property>
|
||||
<property name="always_show_image">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="pack_type">end</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="label" translatable="yes">Save</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="action_name">app.save</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="pack_type">end</property>
|
||||
<property name="position">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="pack_type">end</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="tooltip_text" translatable="yes">Find</property>
|
||||
<property name="action_name">app.search</property>
|
||||
<property name="image">search_icon</property>
|
||||
<property name="always_show_image">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="pack_type">end</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="label" translatable="yes">Save</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="action_name">app.save</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="pack_type">end</property>
|
||||
<property name="position">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
|
|
|
@ -99,7 +99,7 @@
|
|||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="top_attach">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
|
@ -110,7 +110,7 @@
|
|||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="top_attach">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
|
@ -123,7 +123,7 @@
|
|||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">3</property>
|
||||
<property name="top_attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
|
@ -134,7 +134,7 @@
|
|||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="top_attach">3</property>
|
||||
<property name="top_attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
|
@ -147,7 +147,7 @@
|
|||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">4</property>
|
||||
<property name="top_attach">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
|
@ -158,7 +158,7 @@
|
|||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="top_attach">4</property>
|
||||
<property name="top_attach">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
|
@ -171,7 +171,7 @@
|
|||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">5</property>
|
||||
<property name="top_attach">6</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
|
@ -184,7 +184,7 @@
|
|||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="top_attach">5</property>
|
||||
<property name="top_attach">6</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
|
@ -196,9 +196,37 @@
|
|||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">5</property>
|
||||
<property name="top_attach">6</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="autohide_headerbar">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="tooltip_text" translatable="yes">Autohide header and statusbars while typing</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Autohide headerbar</property>
|
||||
<property name="justify">right</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSwitch" id="autohide_headerbar_switch">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="halign">end</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="top_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
<object class="GtkImage" id="edit-find-replace">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="xpad">12</property>
|
||||
<property name="icon_name">edit-find-replace-symbolic</property>
|
||||
</object>
|
||||
<object class="GtkImage" id="go-up">
|
||||
|
@ -30,12 +29,12 @@
|
|||
<property name="can_focus">False</property>
|
||||
<property name="stock">gtk-spell-check</property>
|
||||
</object>
|
||||
<object class="GtkOverlay" id="FullscreenOverlay">
|
||||
<object class="GtkOverlay" id="AppOverlay">
|
||||
<property name="name">FullscreenOverlay</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkGrid" id="grid1">
|
||||
<object class="GtkGrid" id="app_grid">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
|
@ -71,10 +70,9 @@
|
|||
<property name="can_focus">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="editor">
|
||||
<object class="GtkOverlay" id="editor">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow" id="editor_scrolledwindow">
|
||||
<property name="visible">True</property>
|
||||
|
@ -87,15 +85,15 @@
|
|||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
<property name="index">-1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<child type="overlay">
|
||||
<object class="GtkRevealer" id="editor_stats_revealer">
|
||||
<property name="visible">True</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_duration">750</property>
|
||||
<property name="reveal_child">True</property>
|
||||
|
@ -116,11 +114,6 @@
|
|||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
|
@ -236,6 +229,7 @@
|
|||
<object class="GtkBox" id="searchtools_box">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<child>
|
||||
<object class="GtkToggleButton" id="case_sensitive">
|
||||
<property name="label" translatable="yes">aA</property>
|
||||
|
@ -416,17 +410,28 @@
|
|||
<property name="height_request">1</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>
|
||||
<object class="GtkRevealer" id="FullscreenHbPlaceholder">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="valign">start</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
</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>
|
||||
</interface>
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@ class MainWindow(StyledWindow):
|
|||
builder = Gtk.Builder()
|
||||
builder.add_from_resource(
|
||||
"/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.add(root)
|
||||
|
||||
|
@ -84,18 +84,24 @@ 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)
|
||||
|
||||
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.add_accel_group(self.accel_group)
|
||||
|
||||
|
@ -103,6 +109,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()
|
||||
|
@ -119,9 +126,10 @@ class MainWindow(StyledWindow):
|
|||
editor = builder.get_object('editor')
|
||||
self.preview_handler = PreviewHandler(self, content, editor, self.text_view)
|
||||
|
||||
# Setup header/stats bar hide after 3 seconds
|
||||
self.top_bottom_bars_visible = True
|
||||
self.was_motion = True
|
||||
# Setup header/stats bar
|
||||
self.headerbar_visible = True
|
||||
self.bottombar_visible = True
|
||||
self.previewbars_visible = True
|
||||
self.buffer_modified_for_status_bar = False
|
||||
|
||||
# some people seems to have performance problems with the overlay.
|
||||
|
@ -151,6 +159,32 @@ class MainWindow(StyledWindow):
|
|||
###
|
||||
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):
|
||||
""" 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
|
||||
|
@ -162,6 +196,8 @@ class MainWindow(StyledWindow):
|
|||
self.set_headerbar_title("* " + title)
|
||||
|
||||
self.buffer_modified_for_status_bar = True
|
||||
if self.settings.get_value("autohide-headerbar"):
|
||||
self.hide_headerbar_bottombar()
|
||||
|
||||
def set_fullscreen(self, state):
|
||||
"""Puts the application in fullscreen mode and show/hides
|
||||
|
@ -183,7 +219,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,57 +555,68 @@ 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:
|
||||
return
|
||||
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):
|
||||
"""events called when the window losses focus
|
||||
"""
|
||||
self.reveal_top_bottom_bars(True)
|
||||
self.reveal_headerbar_bottombar()
|
||||
|
||||
def reveal_top_bottom_bars(self, reveal):
|
||||
if self.top_bottom_bars_visible != reveal:
|
||||
self.headerbar.hb_revealer.set_reveal_child(reveal)
|
||||
self.stats_revealer.set_reveal_child(reveal)
|
||||
def reveal_headerbar_bottombar(self, _widget=None, _data=None):
|
||||
|
||||
def __reveal_hb():
|
||||
self.headerbar.hb_revealer.set_reveal_child(True)
|
||||
self.get_style_context().remove_class("focus")
|
||||
return False
|
||||
|
||||
self.reveal_bottombar()
|
||||
|
||||
if not self.headerbar_visible:
|
||||
self.dm_headerbar.hide_dm_hb()
|
||||
GLib.timeout_add(400, __reveal_hb)
|
||||
|
||||
self.headerbar_visible = True
|
||||
|
||||
if not self.previewbars_visible:
|
||||
for revealer in self.preview_handler.get_top_bottom_bar_revealers():
|
||||
revealer.set_reveal_child(reveal)
|
||||
self.top_bottom_bars_visible = reveal
|
||||
self.buffer_modified_for_status_bar = reveal
|
||||
revealer.set_reveal_child(True)
|
||||
|
||||
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):
|
||||
"""draw fading gradient over the top and the bottom of the
|
||||
|
@ -617,13 +664,16 @@ class MainWindow(StyledWindow):
|
|||
self.destroy()
|
||||
return
|
||||
|
||||
def set_headerbar_title(self, title, subtitle=""):
|
||||
def set_headerbar_title(self, title, subtitle=None):
|
||||
"""set the desired headerbar title
|
||||
"""
|
||||
self.headerbar.hb.props.title = title
|
||||
self.dm_headerbar.hb.props.title = title
|
||||
self.fs_headerbar.hb.props.title = title
|
||||
self.headerbar.hb.props.subtitle = subtitle
|
||||
self.fs_headerbar.hb.props.subtitle = subtitle
|
||||
if 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)
|
||||
|
||||
def set_filename(self, filename=None):
|
||||
|
|
|
@ -75,6 +75,10 @@ class PreferencesDialog:
|
|||
self.dark_mode_switch.set_active(self.settings.get_value("dark-mode"))
|
||||
self.dark_mode_switch.connect("state-set", self.on_dark_mode)
|
||||
|
||||
self.autohide_headerbar_switch = self.builder.get_object("autohide_headerbar_switch")
|
||||
self.autohide_headerbar_switch.set_active(self.settings.get_value("autohide-headerbar"))
|
||||
self.autohide_headerbar_switch.connect("state-set", self.on_autohide_headerbar)
|
||||
|
||||
self.spellcheck_switch = self.builder.get_object("spellcheck_switch")
|
||||
self.spellcheck_switch.set_active(self.settings.get_value("spellcheck"))
|
||||
self.spellcheck_switch.connect("state-set", self.on_spellcheck)
|
||||
|
@ -123,6 +127,10 @@ class PreferencesDialog:
|
|||
self.dark_mode_auto_switch.set_active(GLib.Variant.new_boolean(False))
|
||||
return False
|
||||
|
||||
def on_autohide_headerbar(self, _, state):
|
||||
self.settings.set_boolean("autohide-headerbar", state)
|
||||
return False
|
||||
|
||||
def on_spellcheck(self, _, state):
|
||||
self.settings.set_boolean("spellcheck", state)
|
||||
return False
|
||||
|
|
|
@ -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):
|
||||
|
|
Loading…
Reference in New Issue