[meld] Use gtkrc-set symbolic colours for most drawing



commit 4c909343e2d384bc28f0241e2dc732a3ccec1e3f
Author: Kai Willadsen <kai willadsen gmail com>
Date:   Mon Jan 2 06:48:37 2012 +1000

    Use gtkrc-set symbolic colours for most drawing
    
    This patch series moves Meld towards retreiving drawing colours from
    a gtkrc set rather than from our preferences. This change should improve
    themeability over the long term, though there may be some regressions.
    
    While gtkrc is not GTK3-friendly, this should also make it somewhat
    easier to forward port to the new themeing mechanics.
    
    Treeview colours are still hard-coded.

 Makefile            |    2 +
 bin/meld            |    1 +
 data/gtkrc          |   18 +++++++++++
 meld/diffmap.py     |   16 +++++-----
 meld/dirdiff.py     |   40 ++++++++++++++++++------
 meld/filediff.py    |   85 +++++++++++++++++++++++++++-----------------------
 meld/linkmap.py     |    4 +-
 meld/meldwindow.py  |    1 +
 meld/misc.py        |    3 ++
 meld/paths.py       |    6 +++
 meld/preferences.py |    5 ---
 11 files changed, 117 insertions(+), 64 deletions(-)
---
diff --git a/Makefile b/Makefile
index 2dd6e7a..6cb6b9f 100644
--- a/Makefile
+++ b/Makefile
@@ -61,6 +61,8 @@ install: $(addsuffix .install,$(SPECIALS)) meld.desktop
 		$(DESTDIR)$(sharedir)/applications
 	$(PYTHON)    -c 'import compileall; compileall.compile_dir("$(DESTDIR)$(libdir_)",10,"$(libdir_)")'
 	$(PYTHON) -O -c 'import compileall; compileall.compile_dir("$(DESTDIR)$(libdir_)",10,"$(libdir_)")'
+	install -m 644 data/gtkrc \
+		$(DESTDIR)$(sharedir_)
 	install -m 644 \
 		data/ui/*.ui \
 		$(DESTDIR)$(sharedir_)/ui
diff --git a/bin/meld b/bin/meld
index 6cb7a7b..07fa0ea 100755
--- a/bin/meld
+++ b/bin/meld
@@ -130,6 +130,7 @@ except (ImportError, AssertionError) as e:
 
 
 gtk.icon_theme_get_default().append_search_path(meld.paths.icon_dir())
+gtk.rc_parse(meld.paths.share_dir("gtkrc"))
 
 def main():
     import meld.meldapp
diff --git a/data/gtkrc b/data/gtkrc
new file mode 100644
index 0000000..78d845f
--- /dev/null
+++ b/data/gtkrc
@@ -0,0 +1,18 @@
+
+style "meld-color-scheme"
+{
+    color["insert-bg"] = "DarkSeaGreen1"
+    color["insert-outline"] = shade(0.8, @insert-bg)
+    color["delete-bg"] = "White"
+    color["delete-outline"] = shade(0.8, @delete-bg)
+    color["replace-bg"] = "#ddeeff"
+    color["replace-outline"] = shade(0.8, @replace-bg)
+    color["conflict-bg"] = "Pink"
+    color["conflict-outline"] = shade(0.8, @conflict-bg)
+    color["error-bg"] = "#fce94f"
+    color["error-outline"] = shade(0.8, @error-bg)
+    color["inline-bg"] = "LightSteelBlue2"
+    color["inline-fg"] = "Red"
+    color["current-line-highlight"] = "#ffff00"
+}
+widget "meldapp.*" style : lowest "meld-color-scheme"
diff --git a/meld/diffmap.py b/meld/diffmap.py
index 609138b..403690d 100644
--- a/meld/diffmap.py
+++ b/meld/diffmap.py
@@ -41,9 +41,8 @@ class DiffMap(gtk.DrawingArea):
         self._h_offset = 0
         self._scroll_y = 0
         self._scroll_height = 0
-        self.ctab = {}
 
-    def setup(self, scrollbar, change_chunk_fn, colour_map):
+    def setup(self, scrollbar, change_chunk_fn, color_map):
         for (o, h) in self._handlers:
             o.disconnect(h)
 
@@ -63,7 +62,11 @@ class DiffMap(gtk.DrawingArea):
                           (self._scrolladj, adj_change_hid),
                           (self._scrolladj, adj_val_hid)]
         self._difffunc = change_chunk_fn
-        self.ctab = colour_map
+        self.set_color_scheme(color_map)
+        self.queue_draw()
+
+    def set_color_scheme(self, color_map):
+        self.fill_colors, self.line_colors = color_map
         self.queue_draw()
 
     def on_scrollbar_style_set(self, scrollbar, previous_style):
@@ -102,20 +105,17 @@ class DiffMap(gtk.DrawingArea):
         context.rectangle(x0 - 3, -1, x1 + 6, height + 1)
         context.clip()
 
-        darken = lambda color: [x * 0.8 for x in color]
-
         tagged_diffs = collections.defaultdict(list)
         for c, y0, y1 in self._difffunc():
             tagged_diffs[c].append((y0, y1))
 
         for tag, diffs in tagged_diffs.iteritems():
-            color = self.ctab[tag]
-            context.set_source_rgb(*color)
+            context.set_source_color(self.fill_colors[tag])
             for y0, y1 in diffs:
                 y0, y1 = round(y0 * height) - 0.5, round(y1 * height) - 0.5
                 context.rectangle(x0, y0, x1, y1 - y0)
             context.fill_preserve()
-            context.set_source_rgb(*darken(color))
+            context.set_source_color(self.line_colors[tag])
             context.stroke()
 
         page_color = (0., 0., 0., 0.1)
diff --git a/meld/dirdiff.py b/meld/dirdiff.py
index 04e87b4..556315e 100644
--- a/meld/dirdiff.py
+++ b/meld/dirdiff.py
@@ -212,7 +212,6 @@ class DirDiff(melddoc.MeldDoc, gnomeglade.Component):
         tree.STATE_ERROR: "error",
         tree.STATE_EMPTY: None,
         tree.STATE_MODIFIED: "replace",
-        tree.STATE_CONFLICT: "conflict",
         tree.STATE_MISSING: "delete",
     }
 
@@ -263,6 +262,10 @@ class DirDiff(melddoc.MeldDoc, gnomeglade.Component):
         self.map_widgets_into_lists(["treeview", "fileentry", "scrolledwindow",
                                      "diffmap", "linkmap", "msgarea_mgr",
                                      "vbox"])
+
+        self.widget.connect("style-set", self.on_style_set)
+        self.widget.ensure_style()
+
         self.set_num_panes(num_panes)
         self.focus_in_events = []
         self.focus_out_events = []
@@ -300,6 +303,31 @@ class DirDiff(melddoc.MeldDoc, gnomeglade.Component):
                 action_name = self.state_actions[s][1]
                 self.actiongroup.get_action(action_name).set_active(True)
 
+    def on_style_set(self, widget, prev_style):
+        style = widget.get_style()
+
+        lookup = lambda color_id, default: style.lookup_color(color_id) or \
+                                           gtk.gdk.color_parse(default)
+
+        self.fill_colors = {"insert"  : lookup("insert-bg", "DarkSeaGreen1"),
+                            "delete"  : lookup("delete-bg", "White"),
+                            "replace" : lookup("replace-bg", "#ddeeff"),
+                            "error"   : lookup("error-bg", "#fce94f")}
+        self.line_colors = {"insert"  : lookup("insert-outline", "#77f077"),
+                            "delete"  : lookup("delete-outline", "Grey"),
+                            "replace" : lookup("replace-outline", "#8bbff3"),
+                            "error"   : lookup("error-outline", "#edd400")}
+
+        for diffmap in self.diffmap:
+            diffmap.set_color_scheme([self.fill_colors, self.line_colors])
+        self.queue_draw()
+
+    def queue_draw(self):
+        for treeview in self.treeview:
+            treeview.queue_draw()
+        for diffmap in self.diffmap:
+            diffmap.queue_draw()
+
     def on_custom_filter_menu_toggled(self, item):
         if item.get_active():
             self.custom_popup.connect("deactivate",
@@ -1087,18 +1115,10 @@ class DirDiff(melddoc.MeldDoc, gnomeglade.Component):
                 self.treeview[i].set_model(self.model)
             self.model.connect("row-deleted", self.on_treemodel_row_deleted)
 
-            colour_map = {
-                "conflict": (1.0, 0.75294117647058822, 0.79607843137254897),
-                "error": (0.9882352941176, 0.9137254901960, 0.30980392156862),
-                "insert": (0.75686274509803919, 1.0, 0.75686274509803919),
-                "replace": (0.8666666666666667, 0.93333333333333335, 1.0),
-                "delete": (1.0, 1.0, 1.0),
-            }
-
             for (w, i) in zip(self.diffmap, (0, n - 1)):
                 scroll = self.scrolledwindow[i].get_vscrollbar()
                 idx = 1 if i else 0
-                w.setup(scroll, self.get_state_traversal(idx), colour_map)
+                w.setup(scroll, self.get_state_traversal(idx), [self.fill_colors, self.line_colors])
 
             toshow =  self.scrolledwindow[:n] + self.fileentry[:n]
             toshow += self.linkmap[:n-1] + self.diffmap[:n]
diff --git a/meld/filediff.py b/meld/filediff.py
index 1c2724d..f04a3ee 100644
--- a/meld/filediff.py
+++ b/meld/filediff.py
@@ -178,28 +178,10 @@ class FileDiff(melddoc.MeldDoc, gnomeglade.Component):
         self.in_nested_textview_gutter_expose = False
         self._inline_cache = set()
         self._cached_match = CachedSequenceMatcher()
-        self.anim_source_id = []
-        self.animating_chunks = []
+        self.anim_source_id = [None for buf in self.textbuffer]
+        self.animating_chunks = [[] for buf in self.textbuffer]
         for buf in self.textbuffer:
-            buf.create_tag("inline", background=self.prefs.color_inline_bg,
-                                     foreground=self.prefs.color_inline_fg)
-            self.anim_source_id.append(None)
-            self.animating_chunks.append([])
-
-        def parse_to_cairo(color_spec):
-            c = gtk.gdk.color_parse(color_spec)
-            return tuple([x / 65535. for x in (c.red, c.green, c.blue)])
-
-        self.fill_colors = {"insert"   : parse_to_cairo(self.prefs.color_delete_bg),
-                            "delete"   : parse_to_cairo(self.prefs.color_delete_bg),
-                            "conflict" : parse_to_cairo(self.prefs.color_conflict_bg),
-                            "replace"  : parse_to_cairo(self.prefs.color_replace_bg)}
-
-        darken = lambda color: tuple([x * 0.8 for x in color])
-        self.line_colors = {"insert"   : darken(self.fill_colors["insert"]),
-                            "delete"   : darken(self.fill_colors["delete"]),
-                            "conflict" : darken(self.fill_colors["conflict"]),
-                            "replace"  : darken(self.fill_colors["replace"])}
+            buf.create_tag("inline")
 
         actions = (
             ("MakePatch", None, _("Format as patch..."), None, _("Create a patch using differences between files"), self.make_patch),
@@ -233,6 +215,10 @@ class FileDiff(melddoc.MeldDoc, gnomeglade.Component):
         self.actiongroup.add_actions(actions)
         self.actiongroup.add_toggle_actions(toggle_actions)
         self.findbar = findbar.FindBar(self.table)
+
+        self.widget.connect("style-set", self.on_style_set)
+        self.widget.ensure_style()
+
         self.set_num_panes(num_panes)
         gobject.idle_add( lambda *args: self.load_font()) # hack around Bug 316730
         gnomeglade.connect_signal_handlers(self)
@@ -258,6 +244,33 @@ class FileDiff(melddoc.MeldDoc, gnomeglade.Component):
         self.emit("action-mode-changed", mode)
     keymask = property(get_keymask, set_keymask)
 
+    def on_style_set(self, widget, prev_style):
+        style = widget.get_style()
+
+        lookup = lambda color_id, default: style.lookup_color(color_id) or \
+                                           gtk.gdk.color_parse(default)
+
+        for buf in self.textbuffer:
+            tag = buf.get_tag_table().lookup("inline")
+            tag.props.background = lookup("inline-bg", "LightSteelBlue2")
+            tag.props.foreground = lookup("inline-fg", "Red")
+
+        self.fill_colors = {"insert"  : lookup("insert-bg", "DarkSeaGreen1"),
+                            "delete"  : lookup("insert-bg", "DarkSeaGreen1"),
+                            "conflict": lookup("conflict-bg", "Pink"),
+                            "replace" : lookup("replace-bg", "#ddeeff")}
+        self.line_colors = {"insert"  : lookup("insert-outline", "#77f077"),
+                            "delete"  : lookup("insert-outline", "#77f077"),
+                            "conflict": lookup("conflict-outline", "#f0768b"),
+                            "replace" : lookup("replace-outline", "#8bbff3")}
+
+        for diffmap in self.diffmap:
+            diffmap.set_color_scheme([self.fill_colors, self.line_colors])
+
+        self.highlight_color = lookup("highlight-bg", "#ffff00")
+
+        self.queue_draw()
+
     def on_focus_change(self):
         self.keymask = 0
 
@@ -1212,21 +1225,22 @@ class FileDiff(melddoc.MeldDoc, gnomeglade.Component):
 
             context.rectangle(-0.5, ypos0 - 0.5, width + 1, ypos1 - ypos0)
             if change[1] != change[2]:
-                context.set_source_rgb(*self.fill_colors[change[0]])
+                context.set_source_color(self.fill_colors[change[0]])
                 context.fill_preserve()
                 if self.linediffer.locate_chunk(pane, change[1])[0] == self.cursor.chunk:
                     context.set_source_rgba(1.0, 1.0, 1.0, 0.5)
                     context.fill_preserve()
 
-            context.set_source_rgb(*self.line_colors[change[0]])
+            context.set_source_color(self.line_colors[change[0]])
             context.stroke()
 
         if textview.is_focus() and self.cursor.line is not None:
             it = self.textbuffer[pane].get_iter_at_line(self.cursor.line)
             ypos, line_height = self.textview[pane].get_line_yrange(it)
-            context.set_source_rgba(1, 1, 0, .25)
             context.rectangle(0, ypos - visible.y, width, line_height)
-            context.fill()
+            context.clip()
+            context.set_source_color(self.highlight_color)
+            context.paint_with_alpha(0.25)
 
         current_time = glib.get_current_time()
         new_anim_chunks = []
@@ -1532,16 +1546,9 @@ class FileDiff(melddoc.MeldDoc, gnomeglade.Component):
                         yield c[0], y0 / max_y, (y + h) / max_y
                 return coords_by_chunk
 
-            colour_map = {
-                "conflict": (1.0, 0.75294117647058822, 0.79607843137254897),
-                "insert": (0.75686274509803919, 1.0, 0.75686274509803919),
-                "replace": (0.8666666666666667, 0.93333333333333335, 1.0),
-                "delete": (0.75686274509803919, 1.0, 0.75686274509803919)
-            }
-
             for (w, i) in zip(self.diffmap, (0, self.num_panes - 1)):
                 scroll = self.scrolledwindow[i].get_vscrollbar()
-                w.setup(scroll, coords_iter(i), colour_map)
+                w.setup(scroll, coords_iter(i), [self.fill_colors, self.line_colors])
 
             for (w, i) in zip(self.linkmap, (0, self.num_panes - 2)):
                 w.associate(self, self.textview[i], self.textview[i + 1])
@@ -1599,8 +1606,8 @@ class FileDiff(melddoc.MeldDoc, gnomeglade.Component):
         mark1 = b1.create_mark(None, new_end, True)
         # FIXME: If the inserted chunk ends up being an insert chunk, then
         # this animation is not visible; this happens often in three-way diffs
-        rgba0 = self.fill_colors['insert'] + (1.0,)
-        rgba1 = self.fill_colors['insert'] + (0.0,)
+        rgba0 = misc.gdk_to_cairo_color(self.fill_colors['insert']) + (1.0,)
+        rgba1 = misc.gdk_to_cairo_color(self.fill_colors['insert']) + (0.0,)
         anim = TextviewLineAnimation(mark0, mark1, rgba0, rgba1, 0.5)
         self.animating_chunks[dst].append(anim)
 
@@ -1619,8 +1626,8 @@ class FileDiff(melddoc.MeldDoc, gnomeglade.Component):
         mark1 = b1.create_mark(None, new_end, True)
         # FIXME: If the inserted chunk ends up being an insert chunk, then
         # this animation is not visible; this happens often in three-way diffs
-        rgba0 = self.fill_colors['insert'] + (1.0,)
-        rgba1 = self.fill_colors['insert'] + (0.0,)
+        rgba0 = misc.gdk_to_cairo_color(self.fill_colors['insert']) + (1.0,)
+        rgba1 = misc.gdk_to_cairo_color(self.fill_colors['insert']) + (0.0,)
         anim = TextviewLineAnimation(mark0, mark1, rgba0, rgba1, 0.5)
         self.animating_chunks[dst].append(anim)
 
@@ -1633,8 +1640,8 @@ class FileDiff(melddoc.MeldDoc, gnomeglade.Component):
         mark0 = b0.create_mark(None, it, True)
         mark1 = b0.create_mark(None, it, True)
         # TODO: Need a more specific colour here; conflict is wrong
-        rgba0 = self.fill_colors['conflict'] + (1.0,)
-        rgba1 = self.fill_colors['conflict'] + (0.0,)
+        rgba0 = misc.gdk_to_cairo_color(self.fill_colors['conflict']) + (1.0,)
+        rgba1 = misc.gdk_to_cairo_color(self.fill_colors['conflict']) + (0.0,)
         anim = TextviewLineAnimation(mark0, mark1, rgba0, rgba1, 0.5)
         self.animating_chunks[src].append(anim)
 
diff --git a/meld/linkmap.py b/meld/linkmap.py
index 3c5b9ef..d37f844 100644
--- a/meld/linkmap.py
+++ b/meld/linkmap.py
@@ -213,7 +213,7 @@ class LinkMap(gtk.DrawingArea):
                                  x_steps[0], f1 - 0.5)
                 context.close_path()
 
-            context.set_source_rgb(*self.fill_colors[c[0]])
+            context.set_source_color(self.fill_colors[c[0]])
             context.fill_preserve()
 
             chunk_idx = self.filediff.linediffer.locate_chunk(left, c[1])[0]
@@ -221,7 +221,7 @@ class LinkMap(gtk.DrawingArea):
                 context.set_source_rgba(1.0, 1.0, 1.0, 0.5)
                 context.fill_preserve()
 
-            context.set_source_rgb(*self.line_colors[c[0]])
+            context.set_source_color(self.line_colors[c[0]])
             context.stroke()
 
             if culled:
diff --git a/meld/meldwindow.py b/meld/meldwindow.py
index 1bffda0..c3263cc 100644
--- a/meld/meldwindow.py
+++ b/meld/meldwindow.py
@@ -126,6 +126,7 @@ class MeldWindow(gnomeglade.Component):
     def __init__(self):
         gladefile = paths.ui_dir("meldapp.ui")
         gnomeglade.Component.__init__(self, gladefile, "meldapp")
+        self.widget.set_name("meldapp")
 
         actions = (
             ("FileMenu", None, _("_File")),
diff --git a/meld/misc.py b/meld/misc.py
index 05b8dbd..f35bbc2 100644
--- a/meld/misc.py
+++ b/meld/misc.py
@@ -135,6 +135,9 @@ def make_tool_button_widget(label):
     hbox.show_all()
     return hbox
 
+def gdk_to_cairo_color(color):
+    return (color.red / 65535., color.green / 65535., color.blue / 65535.)
+
 def all_equal(alist):
     """Return true if all members of the list are equal to the first.
 
diff --git a/meld/paths.py b/meld/paths.py
index ab20ca3..60ae44a 100644
--- a/meld/paths.py
+++ b/meld/paths.py
@@ -35,6 +35,12 @@ def locale_dir(*args): # i18n files
 def help_dir(*args): # help
     return os.path.join(_help_dir, *args)
 
+def share_dir(*args):
+    if os.path.exists(os.path.join(_share_dir, "data")):
+        return os.path.join(_share_dir, "data", *args)
+    else:
+        return os.path.join(_share_dir, *args)
+
 def ui_dir(*args):
     if os.path.exists(os.path.join(_share_dir, "data")):
         return os.path.join(_share_dir, "data", "ui", *args)
diff --git a/meld/preferences.py b/meld/preferences.py
index f339858..6d681b8 100644
--- a/meld/preferences.py
+++ b/meld/preferences.py
@@ -223,11 +223,6 @@ class MeldPreferences(prefs.Preferences):
         "text_codecs": prefs.Value(prefs.STRING, "utf8 latin1"),
         "ignore_symlinks": prefs.Value(prefs.BOOL,0),
         "vc_console_visible": prefs.Value(prefs.BOOL, 0),
-        "color_delete_bg" : prefs.Value(prefs.STRING, "DarkSeaGreen1"),
-        "color_replace_bg" : prefs.Value(prefs.STRING, "#ddeeff"),
-        "color_conflict_bg" : prefs.Value(prefs.STRING, "Pink"),
-        "color_inline_bg" : prefs.Value(prefs.STRING, "LightSteelBlue2"),
-        "color_inline_fg" : prefs.Value(prefs.STRING, "Red"),
         "filters" : prefs.Value(prefs.STRING,
             #TRANSLATORS: translate this string ONLY to the first "\t", leave it and the following parts intact
             _("Backups\t1\t#*# .#* ~* *~ *.{orig,bak,swp}\n") + \



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