conduit r1688 - in trunk: . conduit/gtkui conduit/hildonui



Author: jstowers
Date: Fri Aug 29 23:36:45 2008
New Revision: 1688
URL: http://svn.gnome.org/viewvc/conduit?rev=1688&view=rev

Log:
Merge from trunk

Added:
   trunk/conduit/gtkui/Util.py
Modified:
   trunk/   (props changed)
   trunk/ChangeLog
   trunk/NEWS
   trunk/conduit/gtkui/Canvas.py
   trunk/conduit/gtkui/Makefile.am
   trunk/conduit/hildonui/Canvas.py

Modified: trunk/NEWS
==============================================================================
--- trunk/NEWS	(original)
+++ trunk/NEWS	Fri Aug 29 23:36:45 2008
@@ -6,6 +6,7 @@
   architectural improvements.
 * Conflict inprovements. Duplicate conflicts should no longer be shown
   in the UI.
+* The UI should will now reuse your theme colors
 
 NEW in 0.3.12:
 ==============

Modified: trunk/conduit/gtkui/Canvas.py
==============================================================================
--- trunk/conduit/gtkui/Canvas.py	(original)
+++ trunk/conduit/gtkui/Canvas.py	Fri Aug 29 23:36:45 2008
@@ -7,54 +7,155 @@
 Copyright: John Stowers, 2006
 License: GPLv2
 """
+import cairo
 import goocanvas
 import gtk
 import pango
 from gettext import gettext as _
+
 import logging
 log = logging.getLogger("gtkui.Canvas")
 
-import conduit
+import conduit.utils as Utils
 import conduit.Conduit as Conduit
 import conduit.gtkui.Tree
+import conduit.gtkui.Util as GtkUtil
+
+log.info("Module Information: %s" % Utils.get_module_information(goocanvas, "pygoocanvas_version"))
+
+class _StyleMixin:
+
+    STYLES = (
+        "fg",
+        "bg",
+        "light",
+        "dark",
+        "mid",
+        "text",
+        "base",
+        "text_aa"
+        )
+    STYLE_STATES = (
+        "normal",
+        "active",
+        "prelight",
+        "selected",
+        "insensitive"
+        )
+        
+    def _get_colors_and_state(self, styleName, stateName):
+        style = self.get_gtk_style()
+        if style:
+            colors = getattr(style, styleName.lower(), None)
+            state = getattr(gtk, "STATE_%s" % stateName.upper(), None)
+        else:
+            colors = None
+            state = None
+
+        return colors,state
+
+    def get_gtk_style(self):
+        """
+        @returns: The gtk.Style for the widget
+        """
+        #not that clean, we can be mixed into the
+        #canvas, or a canvas item
+        try:
+            return self.get_canvas().style
+        except AttributeError:
+            try:
+                return self.style
+            except AttributeError:
+                return None
+
+    def get_style_color_rgb(self, styleName, stateName):
+        colors,state = self._get_colors_and_state(styleName, stateName)
+        if colors != None and state != None:
+            return GtkUtil.gdk2rgb(colors[state])
+        else:
+            return GtkUtil.gdk2rgb(GtkUtil.str2gdk("red"))
+        
+    def get_style_color_rgba(self, styleName, stateName, a=1):
+        colors,state = self._get_colors_and_state(styleName, stateName)
+        if colors != None and state != None:
+            return GtkUtil.gdk2rgba(colors[state], a)
+        else:
+            return GtkUtil.gdk2rgba(GtkUtil.str2gdk("red"), a)
+            
+    def get_style_color_int_rgb(self, styleName, stateName):
+        colors,state = self._get_colors_and_state(styleName, stateName)
+        if colors != None and state != None:
+            return GtkUtil.gdk2intrgb(colors[state])
+        else:
+            return GtkUtil.gdk2intrgb(GtkUtil.str2gdk("red"))
+            
+    def get_style_color_int_rgba(self, styleName, stateName, a=1):
+        colors,state = self._get_colors_and_state(styleName, stateName)
+        if colors != None and state != None:
+            return GtkUtil.gdk2intrgba(colors[state], int(a*255))
+        else:
+            return GtkUtil.gdk2intrgba(GtkUtil.str2gdk("red"), int(a*255))
 
-#Tango colors taken from 
-#http://tango.freedesktop.org/Tango_Icon_Theme_Guidelines
-TANGO_COLOR_BUTTER_LIGHT = int("fce94fff",16)
-TANGO_COLOR_BUTTER_MID = int("edd400ff",16)
-TANGO_COLOR_BUTTER_DARK = int("c4a000ff",16)
-TANGO_COLOR_ORANGE_LIGHT = int("fcaf3eff",16)
-TANGO_COLOR_ORANGE_MID = int("f57900",16)
-TANGO_COLOR_ORANGE_DARK = int("ce5c00ff",16)
-TANGO_COLOR_CHOCOLATE_LIGHT = int("e9b96eff",16)
-TANGO_COLOR_CHOCOLATE_MID = int("c17d11ff",16)
-TANGO_COLOR_CHOCOLATE_DARK = int("8f5902ff",16)
-TANGO_COLOR_CHAMELEON_LIGHT = int("8ae234ff",16)
-TANGO_COLOR_CHAMELEON_MID = int("73d216ff",16)
-TANGO_COLOR_CHAMELEON_DARK = int("4e9a06ff",16)
-TANGO_COLOR_SKYBLUE_LIGHT = int("729fcfff",16)
-TANGO_COLOR_SKYBLUE_MID = int("3465a4ff",16)
-TANGO_COLOR_SKYBLUE_DARK = int("204a87ff",16)
-TANGO_COLOR_PLUM_LIGHT = int("ad7fa8ff",16)
-TANGO_COLOR_PLUM_MID = int("75507bff",16)
-TANGO_COLOR_PLUM_DARK = int("5c3566ff",16)
-TANGO_COLOR_SCARLETRED_LIGHT = int("ef2929ff",16)
-TANGO_COLOR_SCARLETRED_MID = int("cc0000ff",16)
-TANGO_COLOR_SCARLETRED_DARK = int("a40000ff",16)
-TANGO_COLOR_ALUMINIUM1_LIGHT = int("eeeeecff",16)
-TANGO_COLOR_ALUMINIUM1_MID = int("d3d7cfff",16)
-TANGO_COLOR_ALUMINIUM1_DARK = int("babdb6ff",16)
-TANGO_COLOR_ALUMINIUM2_LIGHT = int("888a85ff",16)
-TANGO_COLOR_ALUMINIUM2_MID = int("555753ff",16)
-TANGO_COLOR_ALUMINIUM2_DARK = int("2e3436ff",16)
-TRANSPARENT_COLOR = int("00000000",16)
-
-#Style elements common to ConduitCanvasItem and DPCanvasItem
-SIDE_PADDING = 10.0
-LINE_WIDTH = 3.0
-RECTANGLE_RADIUS = 5.0
+class _CanvasItem(goocanvas.Group, _StyleMixin):
 
-class Canvas(goocanvas.Canvas):
+    #attributes common to Conduit and Dataprovider items
+    RECTANGLE_RADIUS =  4.0
+
+    def __init__(self, parent, model):
+        #FIXME: If parent is None in base constructor then goocanvas segfaults
+        #this means a ref to items may be kept so this may leak...
+        goocanvas.Group.__init__(self, parent=parent)
+        self.model = model
+        
+        #this little piece of magic re-applies style properties to the
+        #widgets, when the users theme changes
+        canv = self.get_canvas()
+        if canv:
+            canv.connect("style-set", self._automatic_style_updater)
+
+    def _automatic_style_updater(self, *args):
+        if not self.get_gtk_style():
+            #while in the midst of changing theme, the style is sometimes
+            #None, but dont worry, we will get called again
+            return
+        for attr in self.get_styled_item_names():
+            item = getattr(self, attr, None)
+            if item:
+                item.set_properties(
+                        **self.get_style_properties(attr)
+                        )
+
+    def get_height(self):
+        b = self.get_bounds()
+        return b.y2-b.y1
+
+    def get_width(self):
+        b = self.get_bounds()
+        return b.x2-b.x1
+
+    def get_top(self):
+        b = self.get_bounds()
+        return b.y1
+
+    def get_bottom(self):
+        b = self.get_bounds()
+        return b.y2
+
+    def get_left(self):
+        b = self.get_bounds()
+        return b.x1
+
+    def get_right(self):
+        b = self.get_bounds()
+        return b.x2
+        
+    def get_styled_item_names(self):
+        raise NotImplementedError        
+        
+    def get_style_properties(self, specifier):
+        raise NotImplementedError
+
+class Canvas(goocanvas.Canvas, _StyleMixin):
     """
     This class manages many objects
     """
@@ -92,9 +193,13 @@
         self.connect('drag-motion', self.on_drag_motion)
         self.connect('size-allocate', self._canvas_resized)
 
-        #Show a friendly welcome message on the canvas the first time the
-        #application is launched
-        self.welcomeMessage = None
+        #track theme chages for canvas background
+        self.connect('realize', self._update_for_theme)
+        #We need a flag becuase otherwise we recurse forever.
+        #It appears that setting background_color_rgb in the 
+        #sync-set handler causes sync-set to be emitted again, and again...
+        self._changing_style = False
+        self.connect("style-set", self._update_for_theme)
 
         #keeps a reference to the currently selected (most recently clicked)
         #canvas items
@@ -104,8 +209,27 @@
         #model is a SyncSet, not set till later because it is loaded from xml
         self.model = None
         
-        log.info("Goocanvas version: %s" % str(goocanvas.pygoocanvas_version))
+        #Show a friendly welcome message on the canvas the first time the
+        #application is launched
+        self.welcomeMessage = None
+        self._show_welcome_message()
         
+    def _update_for_theme(self, *args):
+        if not self.get_gtk_style() or self._changing_style:
+            return
+
+        self._changing_style = True    
+        self.set_property(
+                "background_color_rgb",
+                self.get_style_color_int_rgb("bg","normal")
+                )
+        if self.welcomeMessage:
+            self.welcomeMessage.set_property(
+                "fill_color_rgba",
+                self.get_style_color_int_rgba("text","normal")
+                )
+        self._changing_style = False
+
     def _setup_popup_menus(self, dataproviderPopupXML, conduitPopupXML):
         """
         Sets up the popup menus and their callbacks
@@ -161,7 +285,7 @@
                                     anchor=gtk.ANCHOR_CENTER,
                                     alignment=pango.ALIGN_CENTER,
                                     font="Sans 10",
-                                    fill_color="black",
+                                    fill_color_rgba=self.get_style_color_int_rgba("text","normal"),
                                     )
 
         idx = self.root.find_child(self.welcomeMessage)
@@ -291,7 +415,7 @@
         items = self._get_child_conduit_canvas_items()
         if len(items) > 0:
             #special case where the top one was deleted
-            top = items[0].get_top()-(LINE_WIDTH/2)
+            top = items[0].get_top()-(items[0].LINE_WIDTH/2)
             if top != 0.0:
                 for item in items:
                     #translate all those below
@@ -317,8 +441,8 @@
                 else:
                     log.warn("Error finding item")
         self._remove_overlap()
-        self._show_welcome_message()
 
+        self._show_welcome_message()
         c_x,c_y,c_w,c_h = self.get_bounds()
         self.set_bounds(
                     0,
@@ -331,7 +455,6 @@
         """
         Creates a ConduitCanvasItem for the new conduit
         """
-
         #check for duplicates to eliminate race condition in set_sync_set
         if conduitAdded in [i.model for i in self._get_child_conduit_canvas_items()]:
             return
@@ -345,8 +468,8 @@
                                 width=c_w)
         conduitCanvasItem.connect('button-press-event', self._on_conduit_button_press)
         conduitCanvasItem.translate(
-                LINE_WIDTH/2.0,
-                bottom+(LINE_WIDTH/2.0)
+                conduitCanvasItem.LINE_WIDTH/2.0,
+                bottom+(conduitCanvasItem.LINE_WIDTH/2.0)
                 )
 
         for dp in conduitAdded.get_all_dataproviders():
@@ -368,7 +491,6 @@
             if item.model == dataproviderRemoved:
                 conduitCanvasItem.delete_dataprovider_canvas_item(item)
         self._remove_overlap()
-        self._show_welcome_message()
 
     def on_dataprovider_added(self, sender, dataproviderAdded, conduitCanvasItem):
         """
@@ -387,7 +509,6 @@
         item.connect('button-press-event', self._on_dataprovider_button_press)
         conduitCanvasItem.add_dataprovider_canvas_item(item)
         self._remove_overlap()
-        self._show_welcome_message()
 
     def get_sync_set(self):
         return self.model
@@ -400,8 +521,6 @@
         self.model.connect("conduit-added", self.on_conduit_added)
         self.model.connect("conduit-removed", self.on_conduit_removed)
 
-        self._show_welcome_message()
-        
     def on_drag_motion(self, wid, context, x, y, time):
         context.drag_status(gtk.gdk.ACTION_COPY, time)
         return True
@@ -522,52 +641,15 @@
     def clear_canvas(self):
         self.model.clear()
 
-class _CanvasItem(goocanvas.Group):
-    def __init__(self, parent, model):
-        #FIXME: If parent is None in base constructor then goocanvas segfaults
-        #this means a ref to items may be kept so this may leak...
-        goocanvas.Group.__init__(self, parent=parent)
-        self.model = model
-
-    def get_height(self):
-        b = self.get_bounds()
-        return b.y2-b.y1
-
-    def get_width(self):
-        b = self.get_bounds()
-        return b.x2-b.x1
-
-    def get_top(self):
-        b = self.get_bounds()
-        return b.y1
-
-    def get_bottom(self):
-        b = self.get_bounds()
-        return b.y2
-
-    def get_left(self):
-        b = self.get_bounds()
-        return b.x1
-
-    def get_right(self):
-        b = self.get_bounds()
-        return b.x2
-
 class DataProviderCanvasItem(_CanvasItem):
 
     WIDGET_WIDTH = 130
     WIDGET_HEIGHT = 60
     IMAGE_TO_TEXT_PADDING = 5
     PENDING_MESSAGE = "Pending"
-    PENDING_FILL_COLOR = TANGO_COLOR_BUTTER_LIGHT
-    SOURCE_FILL_COLOR = TANGO_COLOR_ALUMINIUM1_MID
-    SINK_FILL_COLOR = TANGO_COLOR_SKYBLUE_LIGHT
-    TWOWAY_FILL_COLOR = TANGO_COLOR_BUTTER_MID
-
-    NAME_FONT = "Sans 8"
-    STATUS_FONT = "Sans 7"
     MAX_TEXT_LENGTH = 10
     MAX_TEXT_LINES = 2
+    LINE_WIDTH = 2.0
 
     def __init__(self, parent, model):
         _CanvasItem.__init__(self, parent, model)
@@ -597,19 +679,6 @@
             
         return text
 
-    def _get_fill_color(self):
-        if self.model.module == None:
-            return self.PENDING_FILL_COLOR
-        else:
-            if self.model.module_type == "source":
-                return self.SOURCE_FILL_COLOR
-            elif self.model.module_type == "sink":
-                return self.SINK_FILL_COLOR
-            elif self.model.module_type == "twoway":
-                return self.TWOWAY_FILL_COLOR
-            else:
-                log.warn("Unknown module type: Cannot get fill color")
-
     def _get_icon(self):
         return self.model.get_icon()        
 
@@ -617,13 +686,11 @@
         self.box = goocanvas.Rect(   
                                 x=0, 
                                 y=0, 
-                                width=self.WIDGET_WIDTH-(2*LINE_WIDTH), 
-                                height=self.WIDGET_HEIGHT-(2*LINE_WIDTH),
-                                line_width=LINE_WIDTH, 
-                                stroke_color="black",
-                                fill_color_rgba=self._get_fill_color(), 
-                                radius_y=RECTANGLE_RADIUS, 
-                                radius_x=RECTANGLE_RADIUS
+                                width=self.WIDGET_WIDTH-(2*self.LINE_WIDTH), 
+                                height=self.WIDGET_HEIGHT-(2*self.LINE_WIDTH),
+                                radius_y=self.RECTANGLE_RADIUS, 
+                                radius_x=self.RECTANGLE_RADIUS,
+                                **self.get_style_properties("box")
                                 )
         pb = self.model.get_icon()
         pbx = int((1*self.WIDGET_WIDTH/5) - (pb.get_width()/2))
@@ -632,12 +699,13 @@
                                 x=pbx,
                                 y=pby
                                 )
-        self.name = goocanvas.Text(  x=pbx + pb.get_width() + self.IMAGE_TO_TEXT_PADDING, 
+        self.name = goocanvas.Text(
+                                x=pbx + pb.get_width() + self.IMAGE_TO_TEXT_PADDING, 
                                 y=int(1*self.WIDGET_HEIGHT/3), 
                                 width=3*self.WIDGET_WIDTH/5, 
                                 text=self._get_model_name(), 
-                                anchor=gtk.ANCHOR_WEST, 
-                                font=self.NAME_FONT
+                                anchor=gtk.ANCHOR_WEST,
+                                **self.get_style_properties("name")
                                 )
         self.statusText = goocanvas.Text(  
                                 x=int(1*self.WIDGET_WIDTH/10), 
@@ -645,11 +713,9 @@
                                 width=4*self.WIDGET_WIDTH/5, 
                                 text="", 
                                 anchor=gtk.ANCHOR_WEST, 
-                                font=self.STATUS_FONT,
-                                fill_color_rgba=TANGO_COLOR_ALUMINIUM2_MID,
+                                **self.get_style_properties("statusText")
                                 )                                    
         
-           
         #Add all the visual elements which represent a dataprovider    
         self.add_child(self.box)
         self.add_child(self.name)
@@ -662,6 +728,50 @@
     def _on_status_changed(self, dataprovider):
         msg = dataprovider.get_status()
         self.statusText.set_property("text", msg)
+    
+    def get_styled_item_names(self):
+        return "box","name","statusText"
+        
+    def get_style_properties(self, specifier):
+        if specifier == "box":
+            #color the box differently if it is pending, i.e. unavailable,
+            #disconnected, etc.
+            if self.model.module == None:
+                insensitive = self.get_style_color_int_rgba("mid","insensitive")
+                kwargs = {
+                    "line_width":1.5,
+                    "stroke_color_rgba":insensitive,
+                    "fill_color_rgba":insensitive
+                }
+                
+            else:
+                pattern = cairo.LinearGradient(0, 0, 0, 100)
+                pattern.add_color_stop_rgb(
+                                        0,
+                                        *self.get_style_color_rgb("dark","active")
+                                        );
+                pattern.add_color_stop_rgb(
+                                        0.5,
+                                        *self.get_style_color_rgb("dark","prelight")
+                                        );
+            
+                kwargs = {
+                    "line_width":2.0,
+                    "stroke_color":"black",
+                    "fill_pattern":pattern
+                }
+        elif specifier == "name":
+            kwargs = {
+                "font":"Sans 8",
+                "fill_color_rgba":self.get_style_color_int_rgba("text","normal")
+            }
+        elif specifier == "statusText":
+            kwargs = {
+                "font":"Sans 7",
+                "fill_color_rgba":self.get_style_color_int_rgba("text_aa","normal")
+            }
+        
+        return kwargs
         
     def update_appearance(self):
         #the image
@@ -678,7 +788,9 @@
             statusText = self.model.module.get_status()
         self.statusText.set_property("text",statusText)
 
-        self.box.set_property("fill_color_rgba",self._get_fill_color())
+        self.box.set_properties(
+                    **self.get_style_properties("box")
+                    )
 
     def set_model(self, model):
         self.model = model
@@ -689,7 +801,11 @@
     
 class ConduitCanvasItem(_CanvasItem):
 
+    DIVIDER = False
+    FLAT_BOX = True
     WIDGET_HEIGHT = 100
+    SIDE_PADDING = 10.0
+    LINE_WIDTH = 2.0
 
     def __init__(self, parent, model, width):
         _CanvasItem.__init__(self, parent, model)
@@ -702,9 +818,15 @@
         self.sinkDpItems = []
         self.connectorItems = {}
 
-        self.bounding_box = None
         self.l = None
         self.progressText = None
+        self.boundingBox = None        
+
+        #if self.DIVIDER, show an transparent bouding box, and a
+        #simple dividing line
+        self.divider = None
+        #goocanvas.Points need a list of tuples, not a list of lists. Yuck
+        self.dividerPoints = [(),()]
 
         #Build the widget
         self._build_widget(width)
@@ -720,8 +842,7 @@
                                     text="", 
                                     anchor=gtk.ANCHOR_WEST,
                                     alignment=pango.ALIGN_LEFT,
-                                    font="Sans 7",
-                                    fill_color="black",
+                                    **self.get_style_properties("progressText")
                                     )
                 self.add_child(self.progressText) 
 
@@ -730,42 +851,55 @@
         if dpx == 0:
             #Its a source
             dpCanvasItem.translate(
-                        SIDE_PADDING,
-                        SIDE_PADDING + self.l.get_property("line_width")
+                        self.SIDE_PADDING,
+                        self.SIDE_PADDING + self.l.get_property("line_width")
                         )
         else:
             #Its a sink
             if dpy == 0:
-                i = SIDE_PADDING
+                i = self.SIDE_PADDING
             else:
-                i = (dpy * SIDE_PADDING) + SIDE_PADDING
+                i = (dpy * self.SIDE_PADDING) + self.SIDE_PADDING
 
             dpCanvasItem.translate(
-                            self.get_width() - dpCanvasItem.get_width() - SIDE_PADDING,
+                            self.get_width() - dpCanvasItem.get_width() - self.SIDE_PADDING,
                             (dpy * dpCanvasItem.get_height()) + i + self.l.get_property("line_width")
                             )
 
     def _build_widget(self, width):
-        true_width = width-LINE_WIDTH
+        true_width = width-self.LINE_WIDTH
 
         #draw a spacer to give some space between conduits
         points = goocanvas.Points([(0.0, 0.0), (true_width, 0.0)])
-        self.l = goocanvas.Polyline(points=points, line_width=LINE_WIDTH, stroke_color_rgba=TRANSPARENT_COLOR)
+        self.l = goocanvas.Polyline(
+                                points=points,
+                                line_width=self.LINE_WIDTH,
+                                stroke_color_rgba=GtkUtil.TRANSPARENT_COLOR
+                                )
         self.add_child(self.l)
 
         #draw a box which will contain the dataproviders
-        self.bounding_box = goocanvas.Rect(
+        self.boundingBox = goocanvas.Rect(
                                 x=0, 
                                 y=5, 
                                 width=true_width,     
-                                height=ConduitCanvasItem.WIDGET_HEIGHT,
-                                line_width=LINE_WIDTH, 
-                                stroke_color="black",
-                                fill_color_rgba=TANGO_COLOR_ALUMINIUM1_LIGHT, 
-                                radius_y=RECTANGLE_RADIUS, 
-                                radius_x=RECTANGLE_RADIUS
+                                height=self.WIDGET_HEIGHT,
+                                radius_y=self.RECTANGLE_RADIUS, 
+                                radius_x=self.RECTANGLE_RADIUS,
+                                **self.get_style_properties("boundingBox")
                                 )
-        self.add_child(self.bounding_box)
+        self.add_child(self.boundingBox)
+        if self.DIVIDER:
+            #draw an underline
+            #from point
+            self.dividerPoints[0] = (true_width*0.33,5+self.WIDGET_HEIGHT)
+            self.dividerPoints[1] = (2*(true_width*0.33),5+self.WIDGET_HEIGHT)
+            
+            self.divider = goocanvas.Polyline(
+                                    points=goocanvas.Points(self.dividerPoints),
+                                    **self.get_style_properties("divider")
+                                    )
+            self.add_child(self.divider)
 
     def _resize_height(self):
         sourceh =   0.0
@@ -776,13 +910,13 @@
         #padding between items
         numSinks = len(self.sinkDpItems)
         if numSinks:
-            sinkh += ((numSinks - 1)*SIDE_PADDING)
+            sinkh += ((numSinks - 1)*self.SIDE_PADDING)
         if self.sourceItem != None:
             sourceh += self.sourceItem.get_height()
 
         self.set_height(
-                    max(sourceh, sinkh)+    #expand to the largest
-                    (1.5*SIDE_PADDING)        #padding at the top and bottom
+                    max(sourceh, sinkh)+        #expand to the largest
+                    (1.5*self.SIDE_PADDING)        #padding at the top and bottom
                     )
 
     def _delete_connector(self, item):
@@ -826,7 +960,7 @@
         items = self.sinkDpItems
         if len(items) > 0:
             #special case where the top one was deleted
-            top = items[0].get_top()-self.get_top()-SIDE_PADDING-LINE_WIDTH
+            top = items[0].get_top()-self.get_top()-self.SIDE_PADDING-items[0].LINE_WIDTH
             if top != 0.0:
                 for item in items:
                     #translate all those below
@@ -841,16 +975,63 @@
                         log.debug("Sink Overlap: %s %s ----> %s" % (overlap,i,i+1))
                         #If there is anything more than the normal padding gap between then
                         #the dp must be translated
-                        if overlap < -SIDE_PADDING:
+                        if overlap < -self.SIDE_PADDING:
                             #translate all those below, and make their connectors work again
                             for item in items[i+1:]:
-                                item.translate(0,overlap+SIDE_PADDING)
+                                item.translate(0,overlap+self.SIDE_PADDING)
                                 if self.sourceItem != None:
                                     fromx,fromy,tox,toy = self._get_connector_coordinates(self.sourceItem,item)
                                     self.connectorItems[item].reconnect(fromx,fromy,tox,toy)
                     except IndexError:
                         break
 
+    def get_styled_item_names(self):
+        return "boundingBox","progressText","divider"
+
+    def get_style_properties(self, specifier):
+        if specifier == "boundingBox":
+            if self.DIVIDER:
+                kwargs = {
+                    "line_width":0
+                }
+            else: 
+                if self.FLAT_BOX:
+                    kwargs = {
+                        "line_width":0,
+                        "fill_color_rgba":self.get_style_color_int_rgba("base","prelight")
+                    }
+                else:
+                    pattern = cairo.LinearGradient(0, -30, 0, 100)
+                    pattern.add_color_stop_rgb(
+                                            0,
+                                            *self.get_style_color_rgb("dark","selected")
+                                            );
+                    pattern.add_color_stop_rgb(
+                                            0.7,
+                                            *self.get_style_color_rgb("mid","selected")
+                                            );
+                    
+                    kwargs = {
+                        "line_width":2.0, 
+                        "fill_pattern":pattern,
+                        "stroke_color_rgba":self.get_style_color_int_rgba("text","normal")
+                    }
+
+        elif specifier == "progressText":
+            kwargs = {
+                "font":"Sans 7",
+                "fill_color_rgba":self.get_style_color_int_rgba("text","normal")
+            }
+        elif specifier == "divider":
+            kwargs = {
+                "line_width":3.0,
+                "line_cap":cairo.LINE_CAP_ROUND,
+                "stroke_color_rgba":self.get_style_color_int_rgba("text_aa","normal")
+            }
+        else:
+            kwargs = {}
+
+        return kwargs
 
     def update_appearance(self):
         self._resize_height()
@@ -930,19 +1111,32 @@
         self.update_appearance()
 
     def set_height(self, h):
-        self.bounding_box.set_property("height",h)
+        self.boundingBox.set_property("height",h)
+
+        if self.DIVIDER:
+            #update height points for the divider line
+            self.dividerPoints[0] = (self.dividerPoints[0][0],h+10)
+            self.dividerPoints[1] = (self.dividerPoints[0][0],h+10)
+            self.divider.set_property("points", 
+                                goocanvas.Points(self.dividerPoints))        
 
     def set_width(self, w):
-        true_width = w-LINE_WIDTH
+        true_width = w-self.LINE_WIDTH
+        self.boundingBox.set_property("width",true_width)
+
+        if self.DIVIDER:
+            #update width points for the divider line
+            self.dividerPoints[0] = (true_width*0.33,self.dividerPoints[0][1])
+            self.dividerPoints[1] = (2*(true_width*0.33),self.dividerPoints[1][1])
+            self.divider.set_property("points", 
+                                goocanvas.Points(self.dividerPoints))
 
-        #resize the box
-        self.bounding_box.set_property("width",true_width)
         #resize the spacer
         p = goocanvas.Points([(0.0, 0.0), (true_width, 0.0)])
         self.l.set_property("points",p)
 
         for d in self.sinkDpItems:
-            desired = w - d.get_width() - SIDE_PADDING
+            desired = w - d.get_width() - self.SIDE_PADDING
             actual = d.get_left()
             change = desired-actual
             #move righthand dp
@@ -950,14 +1144,14 @@
             #resize arrow (if exists)
             if self.sourceItem != None:
                 self.connectorItems[d].resize_connector_width(change)
-
+                
 class ConnectorCanvasItem(_CanvasItem):
 
     CONNECTOR_RADIUS = 30
-    CONNECTOR_LINE_WIDTH = 5
     CONNECTOR_YOFFSET = 20
     CONNECTOR_TEXT_XPADDING = 5
     CONNECTOR_TEXT_YPADDING = 10
+    LINE_WIDTH = 5.0
 
     def __init__(self, parent, fromX, fromY, toX, toY, twoway, conversionExists):
         _CanvasItem.__init__(self, parent, None)
@@ -966,14 +1160,8 @@
         self.fromY = fromY
         self.toX = toX
         self.toY = toY
-
         self.twoway = twoway
 
-        if conversionExists == True:
-            self.color = "black"
-        else:
-            self.color = "red"
-
         self._build_widget()
         
     def _build_widget(self):
@@ -982,18 +1170,18 @@
                                     center_y=self.fromY, 
                                     radius_x=6, 
                                     radius_y=6, 
-                                    fill_color=self.color, 
-                                    line_width=0.0
+                                    line_width=0.0,
+                                    **self.get_style_properties("left_end_round")
                                     )
         points = goocanvas.Points([(self.fromX-6, self.fromY), (self.fromX-7, self.fromY)])
         self.left_end_arrow = goocanvas.Polyline(
                             points=points,
-                            stroke_color=self.color,
                             line_width=5,
                             end_arrow=True,
                             arrow_tip_length=3,
                             arrow_length=3,
-                            arrow_width=3
+                            arrow_width=3,
+                            **self.get_style_properties("left_end_arrow")
                             )
 
         
@@ -1001,18 +1189,22 @@
         points = goocanvas.Points([(self.toX-1, self.toY), (self.toX, self.toY)])
         self.right_end = goocanvas.Polyline(
                             points=points,
-                            stroke_color=self.color,
                             line_width=5,
                             end_arrow=True,
                             arrow_tip_length=3,
                             arrow_length=3,
-                            arrow_width=3
+                            arrow_width=3,
+                            **self.get_style_properties("right_end")
                             )
 
         self._draw_arrow_ends()
         self.add_child(self.right_end,-1)
 
-        self.path = goocanvas.Path(data="",stroke_color=self.color,line_width=ConnectorCanvasItem.CONNECTOR_LINE_WIDTH)
+        self.path = goocanvas.Path(
+                            data="",
+                            line_width=self.LINE_WIDTH,
+                            **self.get_style_properties("path")
+                            )
         self._draw_path()
 
     def _draw_arrow_ends(self):
@@ -1070,8 +1262,29 @@
             self.remove_child(pidx)
 
         #Reecreate the path to work round goocanvas bug
-        self.path = goocanvas.Path(data=p,stroke_color=self.color,line_width=ConnectorCanvasItem.CONNECTOR_LINE_WIDTH)
+        self.path = goocanvas.Path(
+                            data=p,
+                            line_width=self.LINE_WIDTH,
+                            **self.get_style_properties("path")
+                            )
         self.add_child(self.path,-1)
+    
+    def get_styled_item_names(self):
+        return "left_end_round", "left_end_arrow", "right_end", "path"
+        
+    def get_style_properties(self, specifier):
+        if specifier == "left_end_round":
+            kwargs = {
+                "fill_color_rgba":self.get_style_color_int_rgba("text","normal")
+            }
+        elif specifier in ("left_end_arrow", "right_end", "path"):
+            kwargs = {
+                "stroke_color_rgba":self.get_style_color_int_rgba("text","normal")
+            }
+        else:
+            kwargs = {}
+        
+        return kwargs
             
     def resize_connector_width(self, dw):
         """

Modified: trunk/conduit/gtkui/Makefile.am
==============================================================================
--- trunk/conduit/gtkui/Makefile.am	(original)
+++ trunk/conduit/gtkui/Makefile.am	Fri Aug 29 23:36:45 2008
@@ -6,6 +6,7 @@
 	__init__.py \
 	SimpleConfigurator.py \
 	Tree.py \
+	Util.py \
 	UI.py
 
 clean-local:

Added: trunk/conduit/gtkui/Util.py
==============================================================================
--- (empty file)
+++ trunk/conduit/gtkui/Util.py	Fri Aug 29 23:36:45 2008
@@ -0,0 +1,85 @@
+import gtk.gdk
+
+#
+# Tango colors taken from 
+# http://tango.freedesktop.org/Tango_Icon_Theme_Guidelines
+#
+TANGO_COLOR_BUTTER_LIGHT = int("fce94fff",16)
+TANGO_COLOR_BUTTER_MID = int("edd400ff",16)
+TANGO_COLOR_BUTTER_DARK = int("c4a000ff",16)
+TANGO_COLOR_ORANGE_LIGHT = int("fcaf3eff",16)
+TANGO_COLOR_ORANGE_MID = int("f57900",16)
+TANGO_COLOR_ORANGE_DARK = int("ce5c00ff",16)
+TANGO_COLOR_CHOCOLATE_LIGHT = int("e9b96eff",16)
+TANGO_COLOR_CHOCOLATE_MID = int("c17d11ff",16)
+TANGO_COLOR_CHOCOLATE_DARK = int("8f5902ff",16)
+TANGO_COLOR_CHAMELEON_LIGHT = int("8ae234ff",16)
+TANGO_COLOR_CHAMELEON_MID = int("73d216ff",16)
+TANGO_COLOR_CHAMELEON_DARK = int("4e9a06ff",16)
+TANGO_COLOR_SKYBLUE_LIGHT = int("729fcfff",16)
+TANGO_COLOR_SKYBLUE_MID = int("3465a4ff",16)
+TANGO_COLOR_SKYBLUE_DARK = int("204a87ff",16)
+TANGO_COLOR_PLUM_LIGHT = int("ad7fa8ff",16)
+TANGO_COLOR_PLUM_MID = int("75507bff",16)
+TANGO_COLOR_PLUM_DARK = int("5c3566ff",16)
+TANGO_COLOR_SCARLETRED_LIGHT = int("ef2929ff",16)
+TANGO_COLOR_SCARLETRED_MID = int("cc0000ff",16)
+TANGO_COLOR_SCARLETRED_DARK = int("a40000ff",16)
+TANGO_COLOR_ALUMINIUM1_LIGHT = int("eeeeecff",16)
+TANGO_COLOR_ALUMINIUM1_MID = int("d3d7cfff",16)
+TANGO_COLOR_ALUMINIUM1_DARK = int("babdb6ff",16)
+TANGO_COLOR_ALUMINIUM2_LIGHT = int("888a85ff",16)
+TANGO_COLOR_ALUMINIUM2_MID = int("555753ff",16)
+TANGO_COLOR_ALUMINIUM2_DARK = int("2e3436ff",16)
+TRANSPARENT_COLOR = int("00000000",16)
+
+#
+# Color conversion utility functions
+#
+def str2gdk(name):
+    return gtk.gdk.color_parse(name)
+
+def int2gdk(i):
+    red   = (i >> 24) & 0xff
+    green = (i >> 16) & 0xff
+    blue  = (i >>  8) & 0xff
+    return gtk.gdk.Color(red * 256, green * 256, blue * 256)
+
+def gdk2intrgba(color, a=0xff):
+    return (color.red   / 256 << 24) \
+         | (color.green / 256 << 16) \
+         | (color.blue  / 256 <<  8) \
+         | 0xff
+         
+def gdk2intrgb(color):
+    return (color.red   / 256 << 16) \
+         | (color.green / 256 << 8) \
+         | (color.blue  / 256 )
+
+def gdk2rgb(color):
+    return (color.red / 65535.0, color.green / 65535.0, color.blue / 65535.0)
+
+def gdk2rgba(color, a=1):
+    return (color.red / 65535.0, color.green / 65535.0, color.blue / 65535.0, a)
+
+def convert(color, converter):
+    if isinstance(color, gtk.gdk.Color):
+        pass
+    elif type(color) == type(0) or type(color) == type(0l):
+        color = int2gdk(color)
+    elif type(color) == type(''):
+        color = str2gdk(color)
+    else:
+        raise TypeError('%s is not a known color type' % type(color))
+    return converter(color)
+
+def to_int(color):
+    return convert(color, gdk2int)
+
+def to_rgb(color):
+    return convert(color, gdk2rgb)
+
+def to_rgba(color):
+    return convert(color, gdk2rgba)
+
+

Modified: trunk/conduit/hildonui/Canvas.py
==============================================================================
--- trunk/conduit/hildonui/Canvas.py	(original)
+++ trunk/conduit/hildonui/Canvas.py	Fri Aug 29 23:36:45 2008
@@ -13,7 +13,8 @@
 import logging
 log = logging.getLogger("hildonui.Canvas")
 
-import conduit.gtkui.Canvas 
+import conduit.gtkui.Canvas
+import conduit.gtkui.Util as GtkUtil 
 
 LINE_WIDTH = 3.0
 
@@ -37,6 +38,9 @@
                                 None,None)
         self.position = -1
         
+    def _update_for_theme(self, *args):
+        pass
+
     def _setup_popup_menus(self, dataproviderPopupXML, conduitPopupXML):
         # dp context menu
         self.dataproviderMenu = DataProviderMenu(self)
@@ -85,6 +89,25 @@
     def on_conduit_removed(self, sender, conduitRemoved):
         self.move_previous ()
 
+    def on_dataprovider_removed(self, sender, dataproviderRemoved, conduitCanvasItem):
+        for item in self._get_child_dataprovider_canvas_items():
+            if item.model == dataproviderRemoved:
+                conduitCanvasItem.delete_dataprovider_canvas_item(item)
+        self._remove_overlap()
+
+    def on_dataprovider_added(self, sender, dataproviderAdded, conduitCanvasItem):
+        #check for duplicates to eliminate race condition in set_sync_set
+        if dataproviderAdded in [i.model for i in self._get_child_dataprovider_canvas_items()]:
+            return
+
+        item = DataProviderCanvasItem(
+                            parent=conduitCanvasItem, 
+                            model=dataproviderAdded
+                            )
+        item.connect('button-press-event', self._on_dataprovider_button_press)
+        conduitCanvasItem.add_dataprovider_canvas_item(item)
+        self._remove_overlap()
+
     def set_sync_set(self, syncSet):
         conduit.gtkui.Canvas.Canvas.set_sync_set(self, syncSet)
         if len(self.model.get_all_conduits()) > 0:
@@ -250,17 +273,90 @@
     #         self.selectedConduitItem.model.disable_slow_sync()
 
 class DataProviderCanvasItem(conduit.gtkui.Canvas.DataProviderCanvasItem):
+
     WIDGET_WIDTH = 160
     WIDGET_HEIGHT = 85
+    LINE_WIDTH = 3.0
+
+    def get_styled_item_names(self):
+        return ()
 
-    NAME_FONT = "Sans 12"
-    STATUS_FONT = "Sans 10"
+    def get_style_properties(self, specifier):
+        if specifier == "box":
+            #color the box differently if it is pending
+            if self.model.module == None:
+                color = GtkUtil.TANGO_COLOR_BUTTER_LIGHT
+            else:
+                if self.model.module_type == "source":
+                    color = GtkUtil.TANGO_COLOR_ALUMINIUM1_MID
+                elif self.model.module_type == "sink":
+                    color = GtkUtil.TANGO_COLOR_SKYBLUE_LIGHT
+                elif self.model.module_type == "twoway":
+                    color = GtkUtil.TANGO_COLOR_BUTTER_MID
+                else:
+                    color = None
+        
+            kwargs = {
+                "line_width":LINE_WIDTH,
+                "stroke_color":"black",
+                "fill_color_rgba":color
+            }
+        elif specifier == "name":
+            kwargs = {
+                "font":"Sans 8"
+            }
+        elif specifier == "statusText":
+            kwargs = {
+                "font":"Sans 7",
+                "fill_color_rgba":GtkUtil.TANGO_COLOR_ALUMINIUM2_MID
+            }
+       
+        return kwargs
 
 class ConduitCanvasItem(conduit.gtkui.Canvas.ConduitCanvasItem):
-    pass 
+
+    FLAT_BOX = False
+    DIVIDER = False
+    LINE_WIDTH = 3.0
+
+    def get_styled_item_names(self):
+        return ()
+
+    def get_style_properties(self, specifier):
+        if specifier == "boundingBox":
+            kwargs = {
+                "line_width":LINE_WIDTH, 
+                "fill_color_rgba":GtkUtil.TANGO_COLOR_ALUMINIUM1_LIGHT, 
+                "stroke_color":"black"
+            }
+        elif specifier == "progressText":
+            kwargs = {
+                "font":"Sans 7",
+                "fill_color":"black"
+            }
+        else:
+            kwargs = {}
+
+        return kwargs
 
 class ConnectorCanvasItem(conduit.gtkui.Canvas.ConnectorCanvasItem):
-    pass
+
+    def get_styled_item_names(self):
+        return ()
+
+    def get_style_properties(self, specifier):
+        if specifier == "left_end_round":
+            kwargs = {
+                "fill_color":"black"
+            }
+        elif specifier in ("left_end_arrow", "right_end", "path"):
+            kwargs = {
+                "stroke_color":"black"
+            }
+        else:
+            kwargs = {}
+        
+        return kwargs
 
 class ContextMenu(gtk.Menu):
     def __init__(self):



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