[gedit-plugins] [commander] Use overlay for entry



commit 48a9b7c453eefe367bae75bb14c6699361a10d23
Author: Jesse van den Kieboom <jessevdk gmail com>
Date:   Thu Sep 4 15:06:40 2014 +0200

    [commander] Use overlay for entry

 plugins/commander/commander/entry.py             |  346 ++++++++++++----------
 plugins/commander/commander/info.py              |    7 +-
 plugins/commander/commander/windowactivatable.py |    2 +-
 3 files changed, 193 insertions(+), 162 deletions(-)
---
diff --git a/plugins/commander/commander/entry.py b/plugins/commander/commander/entry.py
index faf27b4..710fb70 100644
--- a/plugins/commander/commander/entry.py
+++ b/plugins/commander/commander/entry.py
@@ -40,25 +40,49 @@ from info import Info
 from xml.sax import saxutils
 import traceback
 
-class Entry(Gtk.EventBox):
+class Entry(Gtk.Box):
     __gtype_name__ = "CommanderEntry"
 
+    def remove(self):
+        self._reveal.set_reveal_child(False)
+
     def __init__(self, view):
-        Gtk.EventBox.__init__(self)
+        Gtk.Box.__init__(self)
+
         self._view = view
 
-        self.set_visible_window(False)
+        self._history = History(os.path.join(GLib.get_user_config_dir(), 'gedit/commander/history'))
+        self._history_prefix = None
 
-        hbox = Gtk.Box.new(Gtk.Orientation.HORIZONTAL, 3)
-        hbox.show()
-        hbox.set_border_width(3)
+        self._prompt_text = None
+        self._accel_group = None
 
-        # context for the view
-        self._entry = Gtk.Entry()
-        self._entry.set_has_frame(False)
-        self._entry.set_name('gedit-commander-entry')
-        self._entry.show()
+        self._wait_timeout = 0
+        self._info_window = None
+
+        self._suspended = None
+
+        self._handlers = [
+            [0, Gdk.KEY_Up, self._on_history_move, -1],
+            [0, Gdk.KEY_Down, self._on_history_move, 1],
+            [None, Gdk.KEY_Return, self._on_execute, None],
+            [None, Gdk.KEY_KP_Enter, self._on_execute, None],
+            [0, Gdk.KEY_Tab, self._on_complete, None],
+            [0, Gdk.KEY_ISO_Left_Tab, self._on_complete, None]
+        ]
+
+        self._re_complete = re.compile('("((?:\\\\"|[^"])*)"?|\'((?:\\\\\'|[^\'])*)\'?|[^\s]+)')
+        self._command_state = commands.Commands.State()
 
+        self._build_ui()
+        self._setup_keybindings()
+
+        self._attach()
+
+    def view(self):
+        return self._view
+
+    def _setup_keybindings(self):
         css = Gtk.CssProvider()
         css.load_from_data(bytes("""
 @binding-set terminal-like-bindings {
@@ -85,125 +109,144 @@ GtkEntry#gedit-commander-entry {
 }
 """, 'utf-8'))
 
-        # FIXME: remove hardcopy of 600 (GTK_STYLE_PROVIDER_PRIORITY_APPLICATION)
-        # https://bugzilla.gnome.org/show_bug.cgi?id=646860
-        self._entry.get_style_context().add_provider(css, 600)
+        self._entry.get_style_context().add_provider(css, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
 
-        self._prompt_label = Gtk.Label(label='<b>&gt;&gt;&gt;</b>', use_markup=True)
-        self._prompt_label.show()
+    def _find_overlay(self, view):
+        parent = view.get_parent()
 
-        self._entry.connect('focus-out-event', self.on_entry_focus_out)
-        self._entry.connect('key-press-event', self.on_entry_key_press)
+        while not isinstance(parent, Gtk.Overlay):
+            parent = parent.get_parent()
 
-        self._history = History(os.path.join(GLib.get_user_config_dir(), 'gedit/commander/history'))
-        self._prompt = None
+        return parent
 
-        self._accel_group = None
+    def _build_ui(self):
+        self.set_orientation(Gtk.Orientation.HORIZONTAL)
+        self.set_spacing(6)
 
-        hbox.pack_start(self._prompt_label, False, False, 0)
-        hbox.pack_start(self._entry, True, True, 0)
+        self._overlay = self._find_overlay(self._view)
 
-        self.copy_style_from_view()
-        self.view_style_updated_id = self._view.connect('style-updated', self.on_view_style_updated)
+        self._prompt_label = Gtk.Label(label='<b>&gt;&gt;&gt;</b>', use_markup=True)
+        self._prompt_label.set_margin_top(3)
+        self._prompt_label.set_margin_bottom(3)
+        self._prompt_label.set_margin_start(3)
 
-        self.add(hbox)
-        self.attach()
-        self._entry.grab_focus()
+        self._prompt_label.show()
+        self.add(self._prompt_label)
 
-        self._wait_timeout = 0
-        self._info_window = None
+        self._entry = Gtk.Entry()
+        self._entry.set_has_frame(False)
+        self._entry.set_name('gedit-commander-entry')
+        self._entry.set_hexpand(True)
+        self._entry.set_margin_top(3)
+        self._entry.set_margin_bottom(3)
+        self._entry.set_margin_end(3)
 
-        self.connect('destroy', self.on_destroy)
-        self.connect_after('size-allocate', self.on_size_allocate)
-        self.view_draw_id = self._view.connect_after('draw', self.on_draw)
+        self._entry.connect('focus-out-event', self._on_entry_focus_out)
+        self._entry.connect('key-press-event', self._on_entry_key_press)
 
-        self._history_prefix = None
-        self._suspended = None
-        self._handlers = [
-            [0, Gdk.KEY_Up, self.on_history_move, -1],
-            [0, Gdk.KEY_Down, self.on_history_move, 1],
-            [None, Gdk.KEY_Return, self.on_execute, None],
-            [None, Gdk.KEY_KP_Enter, self.on_execute, None],
-            [0, Gdk.KEY_Tab, self.on_complete, None],
-            [0, Gdk.KEY_ISO_Left_Tab, self.on_complete, None]
-        ]
+        self._entry.show()
+        self.add(self._entry)
 
-        self._re_complete = re.compile('("((?:\\\\"|[^"])*)"?|\'((?:\\\\\'|[^\'])*)\'?|[^\s]+)')
-        self._command_state = commands.Commands.State()
+        self._copy_style_from_view()
+        self._view_style_updated_id = self._view.connect('style-updated', self._on_view_style_updated)
 
-    def on_view_style_updated(self, widget):
-        self.copy_style_from_view()
+    def _on_view_style_updated(self, widget):
+        self._copy_style_from_view()
 
-    def get_border_color(self):
-        color = self.get_background_color().copy()
-        color.red = 1 - color.red
-        color.green = 1 - color.green
-        color.blue = 1 - color.blue
-        color.alpha = 0.5
+    @property
+    def _border_color(self):
+        style = self._view.get_buffer().get_style_scheme().get_style('right-margin')
+
+        if style.props.foreground_set:
+            color = Gdk.RGBA()
+            color.parse(style.props.foreground)
+        else:
+            color = self.background_color.copy()
+            color.red = 1 - color.red
+            color.green = 1 - color.green
+            color.blue = 1 - color.blue
 
+        color.alpha = 0.5
         return color
 
-    def get_background_color(self):
+    @property
+    def background_color(self):
         context = self._view.get_style_context()
-        return context.get_background_color(Gtk.StateFlags.NORMAL)
-    
-    def get_foreground_color(self):
+
+        context.save()
+
+        context.add_class('bottom')
+        ret = context.get_background_color(Gtk.StateFlags.NORMAL)
+
+        context.restore()
+
+        return ret
+
+    @property
+    def foreground_color(self):
         context = self._view.get_style_context()
-        return context.get_color(Gtk.StateFlags.NORMAL)
 
-    def get_font(self):
+        context.save()
+
+        context.add_class('bottom')
+        ret = context.get_color(Gtk.StateFlags.NORMAL)
+
+        context.restore()
+
+        return ret
+
+    @property
+    def font(self):
         context = self._view.get_style_context()
         return context.get_font(Gtk.StateFlags.NORMAL)
 
-    def copy_style_from_view(self, widget=None):
-        if widget != None:
-            context = self._view.get_style_context()
-            font = context.get_font(Gtk.StateFlags.NORMAL)
+    def _copy_style_from_view(self):
+        font = self.font
+        fg = self.foreground_color
+        bg = self.background_color
 
-            widget.override_color(Gtk.StateFlags.NORMAL, self.get_foreground_color())
-            widget.override_font(self.get_font())
-        else:
-            if self._entry:
-                self.copy_style_from_view(self._entry)
+        cursor = Gdk.RGBA.from_color(self._view.style_get_property('cursor-color'))
+        second = Gdk.RGBA.from_color(self._view.style_get_property('secondary-cursor-color'))
 
-            if self._prompt_label:
-                self.copy_style_from_view(self._prompt_label)
+        for widget in (self, self._entry, self._prompt_label):
+            widget.override_color(Gtk.StateFlags.NORMAL, fg)
+            widget.override_color(Gtk.StateFlags.SELECTED, bg)
 
-    def view(self):
-        return self._view
+            widget.override_background_color(Gtk.StateFlags.NORMAL, bg)
+            widget.override_background_color(Gtk.StateFlags.SELECTED, fg)
 
-    def on_size_allocate(self, widget, alloc):
-        alloc = self.get_allocation()
-        self._view.set_border_window_size(Gtk.TextWindowType.BOTTOM, alloc.height)
+            widget.override_font(font)
+            widget.override_cursor(cursor, second)
 
-        win = self._view.get_window(Gtk.TextWindowType.BOTTOM)
-        self.set_size_request(win.get_width(), -1)
+    def _attach(self):
+        reveal = Gtk.Revealer()
+        reveal.add(self)
+        self.show()
 
-        # NOTE: we need to do this explicitly somehow, otherwise the window
-        # size will not be updated unless something else happens, not exactly
-        # sure what. This might be caused by the multi notebook, or custom
-        # animation layouting?
-        self._view.get_parent().resize_children()
+        reveal.set_transition_type(Gtk.RevealerTransitionType.SLIDE_UP)
+        reveal.set_transition_duration(200)
 
-    def attach(self):
-        # Attach ourselves in the text view, and position just above the
-        # text window
-        win = self._view.get_window(Gtk.TextWindowType.TEXT)
-        alloc = self.get_allocation()
+        reveal.set_valign(Gtk.Align.END)
+        reveal.set_halign(Gtk.Align.FILL)
 
-        self._view.set_border_window_size(Gtk.TextWindowType.BOTTOM, max(alloc.height, 1))
-        self._view.add_child_in_window(self, Gtk.TextWindowType.BOTTOM, 0, 0)
+        self._overlay.add_overlay(reveal)
+        reveal.show()
 
-        win = self._view.get_window(Gtk.TextWindowType.BOTTOM)
+        reveal.set_reveal_child(True)
+        self._reveal = reveal
 
-        self.show()
-        self.set_size_request(win.get_width(), -1)
+        reveal.connect('notify::child-revealed', self._on_child_revealed)
+        self._entry.grab_focus()
 
-    def on_entry_focus_out(self, widget, evnt):
-        if self._entry.get_sensitive():
+    def _on_child_revealed(self, widget, spec):
+        if not self._reveal.get_child_revealed():
             self.destroy()
 
-    def on_entry_key_press(self, widget, evnt):
+    def _on_entry_focus_out(self, widget, evnt):
+        if self._entry.get_sensitive():
+            self._reveal.set_reveal_child(False)
+
+    def _on_entry_key_press(self, widget, evnt):
         state = evnt.state & Gtk.accelerator_get_default_mod_mask()
         text = self._entry.get_text()
 
@@ -223,15 +266,15 @@ GtkEntry#gedit-commander-entry {
                     self._entry.set_editable(True)
                     self._accel_group = None
 
-                self.prompt()
+                self._prompt()
             elif text:
                 self._entry.set_text('')
             elif self._command_state:
                 self._command_state.clear()
-                self.prompt()
+                self._prompt()
             else:
                 self._view.grab_focus()
-                self.destroy()
+                self._reveal.set_reveal_child(False)
 
             return True
 
@@ -248,12 +291,12 @@ GtkEntry#gedit-commander-entry {
                 self._accel_group = accel
                 self._entry.set_text('')
                 self._entry.set_editable(False)
-                self.prompt()
+                self._prompt()
 
                 return True
             elif isinstance(accel, commands.accel_group.AccelCallback):
                 self._entry.set_editable(True)
-                self.run_command(lambda: accel.activate(self._command_state, self))
+                self._run_command(lambda: accel.activate(self._command_state, self))
                 return True
 
         if not self._entry.get_editable():
@@ -269,7 +312,7 @@ GtkEntry#gedit-commander-entry {
         self._history_prefix = None
         return False
 
-    def on_history_move(self, direction, modifier):
+    def _on_history_move(self, direction, modifier):
         pos = self._entry.get_position()
 
         self._history.update(self._entry.get_text())
@@ -293,8 +336,8 @@ GtkEntry#gedit-commander-entry {
 
         return True
 
-    def prompt(self, pr=''):
-        self._prompt = pr
+    def _prompt(self, pr=''):
+        self._prompt_text = pr
 
         if self._accel_group != None:
             pr = '<i>%s</i>' % (saxutils.escape(self._accel_group.full_name()),)
@@ -306,34 +349,34 @@ GtkEntry#gedit-commander-entry {
 
         self._prompt_label.set_markup('<b>&gt;&gt;&gt;</b>%s' % pr)
 
-    def make_info(self):
+    def _make_info(self):
         if self._info_window == None:
             self._info_window = Info(self)
             self._info_window.show()
 
-            self._info_window.connect('destroy', self.on_info_window_destroy)
+            self._info_window.connect('destroy', self._on_info_window_destroy)
 
-    def on_info_window_destroy(self, widget):
+    def _on_info_window_destroy(self, widget):
         self._info_window = None
 
     def info_show(self, text='', use_markup=False):
-        self.make_info()
+        self._make_info()
         self._info_window.add_lines(text, use_markup)
 
     def info_status(self, text):
-        self.make_info()
+        self._make_info()
         self._info_window.status(text)
 
-    def info_add_action(self, stock, callback, data=None):
-        self.make_info()
+    def _info_add_action(self, stock, callback, data=None):
+        self._make_info()
         return self._info_window.add_action(stock, callback, data)
 
-    def command_history_done(self):
+    def _command_history_done(self):
         self._history.add(self._entry.get_text())
         self._history_prefix = None
         self._entry.set_text('')
 
-    def on_wait_cancel(self):
+    def _on_wait_cancel(self):
         if self._suspended:
             self._suspended.resume()
 
@@ -346,7 +389,7 @@ GtkEntry#gedit-commander-entry {
             self._entry.set_sensitive(True)
 
     def _show_wait_cancel(self):
-        self._cancel_button = self.info_add_action(Gtk.STOCK_STOP, self.on_wait_cancel)
+        self._cancel_button = self._info_add_action(Gtk.STOCK_STOP, self._on_wait_cancel)
         self.info_status('<i>Waiting to finish...</i>')
 
         self._wait_timeout = 0
@@ -357,7 +400,7 @@ GtkEntry#gedit-commander-entry {
             if match.group(i) != None:
                 return [match.group(i), match.start(i), match.end(i)]
 
-    def on_suspend_resume(self):
+    def _on_suspend_resume(self):
         if self._wait_timeout:
             GLib.source_remove(self._wait_timeout)
             self._wait_timeout = 0
@@ -367,40 +410,29 @@ GtkEntry#gedit-commander-entry {
             self.info_status(None)
 
         self._entry.set_sensitive(True)
-        self.command_history_done()
+        self._command_history_done()
 
         if self._entry.props.has_focus or (self._info_window and not self._info_window.empty()):
             self._entry.grab_focus()
 
-        self.on_execute(None, 0)
-
-    def ellipsize(self, s, size):
-        if len(s) <= size:
-            return s
-
-        mid = (size - 4) / 2
-        return s[:mid] + '...' + s[-mid:]
+        self._on_execute(None, 0)
 
-    def destroy(self):
-        self.hide()
-        Gtk.EventBox.destroy(self)
-
-    def run_command(self, cb):
+    def _run_command(self, cb):
         self._suspended = None
 
         try:
             ret = cb()
         except Exception as e:
-            self.command_history_done()
+            self._command_history_done()
             self._command_state.clear()
 
-            self.prompt()
+            self._prompt()
 
             # Show error in info
             self.info_show('<b><span color="#f66">Error:</span></b> ' + saxutils.escape(str(e)), True)
 
             if not isinstance(e, commands.exceptions.Execute):
-                self.info_show(self.format_trace(), False)
+                self.info_show(self._format_trace(), False)
 
             return None
 
@@ -409,26 +441,26 @@ GtkEntry#gedit-commander-entry {
         if ret == mod.Result.SUSPEND:
             # Wait for it...
             self._suspended = ret
-            ret.register(self.on_suspend_resume)
+            ret.register(self._on_suspend_resume)
 
             self._wait_timeout = GLib.timeout_add(500, self._show_wait_cancel)
             self._entry.set_sensitive(False)
         else:
-            self.command_history_done()
-            self.prompt('')
+            self._command_history_done()
+            self._prompt('')
 
             if ret == mod.Result.PROMPT:
-                self.prompt(ret.prompt)
-            elif (ret == None or ret == mod.HIDE) and not self._prompt and (not self._info_window or 
self._info_window.empty()):
+                self._prompt(ret.prompt)
+            elif (ret == None or ret == mod.HIDE) and not self._prompt_text and (not self._info_window or 
self._info_window.empty()):
                 self._command_state.clear()
                 self._view.grab_focus()
-                self.destroy()
+                self._reveal.set_reveal_child(False)
             else:
                 self._entry.grab_focus()
 
         return ret
 
-    def format_trace(self):
+    def _format_trace(self):
         tp, val, tb = sys.exc_info()
 
         origtb = tb
@@ -455,7 +487,7 @@ GtkEntry#gedit-commander-entry {
 
         return r
 
-    def on_execute(self, dummy, modifier):
+    def _on_execute(self, dummy, modifier):
         if self._info_window and not self._suspended:
             self._info_window.destroy()
 
@@ -471,11 +503,11 @@ GtkEntry#gedit-commander-entry {
             self._entry.set_text('')
             return
 
-        self.run_command(lambda: commands.Commands().execute(self._command_state, text, words, wordsstr, 
self, modifier))
+        self._run_command(lambda: commands.Commands().execute(self._command_state, text, words, wordsstr, 
self, modifier))
 
         return True
 
-    def on_complete(self, dummy, modifier):
+    def _on_complete(self, dummy, modifier):
         # First split all the text in words
         text = self._entry.get_text()
         pos = self._entry.get_position()
@@ -650,32 +682,30 @@ GtkEntry#gedit-commander-entry {
 
         return True
 
-    def on_draw(self, widget, ct):
-        win = widget.get_window(Gtk.TextWindowType.BOTTOM)
-
-        if not Gtk.cairo_should_draw_window(ct, win):
-            return False
+    def do_draw(self, ctx):
+        ret = Gtk.Box.do_draw(self, ctx)
 
-        Gtk.cairo_transform_to_window(ct, widget, win)
+        col = self._border_color
 
-        color = self.get_border_color()
-        width = win.get_width()
+        ctx.set_line_width(1)
+        ctx.set_source_rgba(col.red, col.green, col.blue, col.alpha)
 
-        ct.set_source_rgba(color.red, color.green, color.blue, color.alpha)
-        ct.move_to(0, 0)
-        ct.line_to(width, 0)
-        ct.stroke()
+        ctx.move_to(0, 0)
+        ctx.line_to(self.get_allocated_width(), 0)
+        ctx.stroke()
 
-        return False
+        return ret
 
-    def on_destroy(self, widget):
-        self._view.set_border_window_size(Gtk.TextWindowType.BOTTOM, 0)
-        self._view.disconnect(self.view_style_updated_id)
-        self._view.disconnect(self.view_draw_id)
+    def do_destroy(self):
+        self._view.disconnect(self._view_style_updated_id)
 
         if self._info_window:
             self._info_window.destroy()
 
         self._history.save()
 
+        self._view = None
+
+        Gtk.Box.do_destroy(self)
+
 # vi:ex:ts=4:et
diff --git a/plugins/commander/commander/info.py b/plugins/commander/commander/info.py
index 569e339..02a20f0 100644
--- a/plugins/commander/commander/info.py
+++ b/plugins/commander/commander/info.py
@@ -45,9 +45,9 @@ class Info(TransparentWindow):
 
         self._text = Gtk.TextView()
 
-        font = self._entry.get_font()
-        fgcolor = self._entry.get_foreground_color()
-        bgcolor = self.background_color()
+        font = self._entry.font
+        fgcolor = self._entry.foreground_color
+        bgcolor = self.background_color
 
         self._text.override_font(font)
         self._text.override_color(Gtk.StateFlags.NORMAL, fgcolor)
@@ -345,6 +345,7 @@ class Info(TransparentWindow):
 
         ct.line_to(w - 0.5, h)
 
+    @property
     def background_color(self):
         color = self._entry.get_background_color().copy()
         color.alpha = 0.9
diff --git a/plugins/commander/commander/windowactivatable.py 
b/plugins/commander/commander/windowactivatable.py
index a064cf9..915a94c 100644
--- a/plugins/commander/commander/windowactivatable.py
+++ b/plugins/commander/commander/windowactivatable.py
@@ -71,7 +71,7 @@ class CommanderWindowActivatable(GObject.Object, Gedit.WindowActivatable):
             self._entry.grab_focus()
             self._view = view
         elif self._entry:
-            self._entry.destroy()
+            self._entry.remove()
             self._view = None
 
         action.set_state(GLib.Variant.new_boolean(active))


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]