diff --git a/data/de.wolfvollprecht.UberWriter.gschema.xml b/data/de.wolfvollprecht.UberWriter.gschema.xml index eccc8bf..7ac4dbd 100644 --- a/data/de.wolfvollprecht.UberWriter.gschema.xml +++ b/data/de.wolfvollprecht.UberWriter.gschema.xml @@ -76,6 +76,13 @@ Maximum number of characters per line within the editor. + + false + Side-by-side preview + + Show the preview side by side, instead of full-width. + + diff --git a/data/media/css/gtk/base.css b/data/media/css/gtk/base.css index f1707dc..41323d8 100644 --- a/data/media/css/gtk/base.css +++ b/data/media/css/gtk/base.css @@ -96,7 +96,7 @@ padding: 0; } -.stats-counter { +.stats-button { color: alpha(@theme_fg_color, 0.6); background-color: @theme_base_color; text-shadow: inherit; @@ -116,8 +116,8 @@ transition: 100ms ease-in; } -.stats-counter:hover, -.stats-counter:checked { +.stats-button :hover, +.stats-button :checked { color: @theme_fg_color; background-color: mix(@theme_base_color, @theme_bg_color, 0.5); } diff --git a/data/ui/Window.ui b/data/ui/Window.ui index bca48f4..fc9c411 100644 --- a/data/ui/Window.ui +++ b/data/ui/Window.ui @@ -8,32 +8,32 @@ 1 10 - + + True + False + edit-find-replace-symbolic + + True False go-up-symbolic - + True False go-down-symbolic - + + True + False + pan-down-symbolic + 2 + + True False gtk-spell-check - - - text/plain - text/x-markdown - - - - True - False - edit-find-replace-symbolic - FullscreenOverlay True @@ -43,10 +43,10 @@ True False - + True True - True + False 200 @@ -70,45 +70,17 @@ - + True False - True + True - + True False - crossfade - 750 - True - - - 0 Words - True - True - True - Show Statistics - end - - - - - 0 - 1 - - - - - True - False - True - True - natural - natural - none + vertical - 500 True True True @@ -119,16 +91,52 @@ + + False + True + 0 + + + + + True + False + crossfade + 750 + True + + + 0 Words + True + True + True + Show Statistics + end + pan-down + right + True + + + + + False + True + 1 + - 0 - 0 + False + True + 0 + + + - False + True False @@ -191,7 +199,7 @@ True True Previous Match - amunt + go-up False @@ -205,7 +213,7 @@ True True Next Match - avall + go_down False @@ -264,7 +272,7 @@ True True Open Replace - reemplaza + edit-find-replace False @@ -345,7 +353,7 @@ True True True - ortografia1 + spell-check False diff --git a/uberwriter/text_view.py b/uberwriter/text_view.py index f30e4ab..7c38176 100644 --- a/uberwriter/text_view.py +++ b/uberwriter/text_view.py @@ -12,6 +12,7 @@ gi.require_version('Gspell', '1') from gi.repository import Gtk, Gdk, GObject, GLib, Gspell import logging + LOGGER = logging.getLogger('uberwriter') @@ -53,8 +54,8 @@ class TextView(Gtk.TextView): # Text sizing self.props.halign = Gtk.Align.FILL - self.font_size = 16 self.line_chars = line_chars + self.font_size = 16 self.get_style_context().add_class('size16') # General behavior @@ -133,10 +134,8 @@ class TextView(Gtk.TextView): def on_parent_set(self, *_): parent = self.get_parent() if parent: + parent.set_size_request(self.get_min_width(), 500) self.scroller = TextViewScroller(self, parent) - # Request a size that fits the minimum font size comfortably. - parent.set_size_request( - self.pad_chars(self.font_sizes[-1]) * self.font_width(self.font_sizes[-1]), 500) else: self.scroller = None @@ -169,18 +168,17 @@ class TextView(Gtk.TextView): width = self.get_allocation().width # Ensure the appropriate font size is being used - for size in self.font_sizes: - min_width = (self.line_chars + self.pad_chars(size) + 1) * self.font_width(size) - 1 - if width >= min_width: - if size != self.font_size: - self.font_size = size - for s in self.font_sizes: - self.get_style_context().remove_class("size{}".format(s)) - self.get_style_context().add_class("size{}".format(size)) + for font_size in self.font_sizes: + if width >= self.get_min_width(font_size) or font_size == self.font_sizes[-1]: + if font_size != self.font_size: + self.font_size = font_size + for fs in self.font_sizes: + self.get_style_context().remove_class("size{}".format(fs)) + self.get_style_context().add_class("size{}".format(font_size)) break # Apply margin with the remaining space to allow for markup - line_width = (self.line_chars + 1) * int(self.font_width(self.font_size)) - 1 + line_width = (self.line_chars + 1) * int(self.get_char_width(self.font_size)) - 1 horizontal_margin = (width - line_width) / 2 self.props.left_margin = horizontal_margin self.props.right_margin = horizontal_margin @@ -224,15 +222,23 @@ class TextView(Gtk.TextView): mark = self.get_buffer().get_insert() GLib.idle_add(self.scroller.smooth_scroll_to_mark, mark, self.focus_mode) - def pad_chars(self, font_size): + def get_min_width(self, font_size=None): + """Returns the minimum width of this text view.""" + + if font_size is None: + font_size = self.font_sizes[-1] + return (self.line_chars + self.get_pad_chars(font_size) + 1) \ + * self.get_char_width(font_size) - 1 + + def get_pad_chars(self, font_size): """Returns the amount of character padding for font_size. - Markup can use up to 6 in normal conditions.""" + Markup can use up to 7 in normal conditions.""" return 8 * (1 + font_size - self.font_sizes[-1]) @staticmethod - def font_width(font_size): - """Returns the font width for a given size. Specific to Fira Mono.""" + def get_char_width(font_size): + """Returns the font width for a given size. Note: specific to Fira Mono!""" return font_size * 1 / 1.6 diff --git a/uberwriter/window.py b/uberwriter/window.py index c9e62a2..0ee9b59 100644 --- a/uberwriter/window.py +++ b/uberwriter/window.py @@ -101,29 +101,29 @@ class Window(Gtk.ApplicationWindow): self.accel_group = Gtk.AccelGroup() self.add_accel_group(self.accel_group) + self.content = self.builder.get_object('content') + + self.scrolled_window = self.builder.get_object('editor_scrolledwindow') + self.scrolled_window.get_style_context().add_class('uberwriter-scrolled-window') + # Setup text editor - self.text_view = TextView() - self.text_view.props.halign = Gtk.Align.CENTER + self.text_view = TextView(self.settings.get_int("characters-per-line")) 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() self.text_view.grab_focus() + self.scrolled_window.add(self.text_view) + + # Stats stats counter + self.stats_revealer = self.builder.get_object('editor_stats_revealer') + self.stats_button = self.builder.get_object('editor_stats_button') + self.stats_button.get_style_context().add_class('stats-button') + self.stats_handler = StatsHandler(self.stats_button, self.text_view) # Setup preview webview self.web_view = None self.web_view_scroller = None - self.scrolled_window = self.builder.get_object('editor_scrolledwindow') - self.scrolled_window.get_style_context().add_class('uberwriter-scrolled-window') - self.scrolled_window.add(self.text_view) - self.editor_viewport = self.builder.get_object('editor_viewport') - - # Stats counter - self.stats_counter_revealer = self.builder.get_object('stats_counter_revealer') - self.stats_button = self.builder.get_object('stats_counter') - self.stats_button.get_style_context().add_class('stats-counter') - self.stats_handler = StatsHandler(self.stats_button, self.text_view) - # Setup header/stats bar hide after 3 seconds self.top_bottom_bars_visible = True self.was_motion = True @@ -145,7 +145,7 @@ class Window(Gtk.ApplicationWindow): ### # Sidebar initialization test ### - self.paned_window = self.builder.get_object("main_pained") + self.paned_window = self.builder.get_object("main_paned") self.sidebar_box = self.builder.get_object("sidebar_box") self.sidebar = Sidebar(self) self.sidebar_box.hide() @@ -466,10 +466,14 @@ class Window(Gtk.ApplicationWindow): return True def show_text_editor(self): - # Swap web view with text view - self.scrolled_window.remove(self.scrolled_window.get_child()) - self.scrolled_window.add(self.text_view) - self.text_view.show() + # Remove web view + if self.settings.get_boolean("preview-side-by-side"): + self.set_size_request(-1, -1) + self.content.remove(self.web_view) + else: + self.scrolled_window.remove(self.scrolled_window.get_child()) + self.scrolled_window.add(self.text_view) + self.text_view.show() self.queue_draw() # Sync scroll between web view and text view @@ -485,9 +489,13 @@ class Window(Gtk.ApplicationWindow): # Sync scroll between text view and web view self.web_view_scroller.set_scroll_scale(self.text_view.get_scroll_scale()) - # Swap text view with web view - self.scrolled_window.remove(self.scrolled_window.get_child()) - self.scrolled_window.add(self.web_view) + # Show web view + if self.settings.get_boolean("preview-side-by-side"): + self.content.add(self.web_view) + self.set_size_request(self.text_view.get_min_width() * 2, -1) + else: + self.scrolled_window.remove(self.scrolled_window.get_child()) + self.scrolled_window.add(self.web_view) self.web_view.show() self.queue_draw() else: @@ -590,7 +598,7 @@ class Window(Gtk.ApplicationWindow): and self.buffer_modified_for_status_bar and self.text_view.props.has_focus): # pylint: disable=no-member # self.status_bar.set_state_flags(Gtk.StateFlags.INSENSITIVE, True) - self.stats_counter_revealer.set_reveal_child(False) + self.stats_revealer.set_reveal_child(False) self.headerbar.hb_revealer.set_reveal_child(False) self.top_bottom_bars_visible = False self.buffer_modified_for_status_bar = False @@ -612,7 +620,7 @@ class Window(Gtk.ApplicationWindow): if now - self.timestamp_last_mouse_motion > 100: # react on motion by fading in headerbar and statusbar if self.top_bottom_bars_visible is False: - self.stats_counter_revealer.set_reveal_child(True) + self.stats_revealer.set_reveal_child(True) self.headerbar.hb_revealer.set_reveal_child(True) self.headerbar.hb.props.opacity = 1 self.top_bottom_bars_visible = True @@ -624,7 +632,7 @@ class Window(Gtk.ApplicationWindow): """events called when the window losses focus """ if self.top_bottom_bars_visible is False: - self.stats_counter_revealer.set_reveal_child(True) + self.stats_revealer.set_reveal_child(True) self.headerbar.hb_revealer.set_reveal_child(True) self.headerbar.hb.props.opacity = 1 self.top_bottom_bars_visible = True