Title: [commits] (jeffrey) [16048] [APP] Read color info from colors.conf
Revision
16048
Author
jeffrey
Date
2007-12-05 13:27:20 -0800 (Wed, 05 Dec 2007)

Log Message

[APP] Read color info from colors.conf
- Handle selection events in calendar canvases
- Change draw order based on most recent selection for a cluster
- Cache drawn lozenges by drawing them first to transparent bitmaps
- Tweak ExampleFrame to use the all_events cell, so Hi! events show up
in November
- Pass a height when updating a sash based on ideal_height to avoid
rounding differences when the Preview Area appears/disappears,
instead of a proportion

Modified Paths

Added Paths

Diff

Modified: branches/rearchitecture/Chandler-Debugging/ocap/debugging/py_crust.py (16047 => 16048)

--- branches/rearchitecture/Chandler-Debugging/ocap/debugging/py_crust.py	2007-12-05 20:53:26 UTC (rev 16047)
+++ branches/rearchitecture/Chandler-Debugging/ocap/debugging/py_crust.py	2007-12-05 21:27:20 UTC (rev 16048)
@@ -180,9 +180,8 @@
 
     @trellis.observer
     def bindEvents(self):
-        # XXX is this even necessary?  Could we just bind these events at
-        # frame level?  Do we need the events at all?  Taking this (and the
-        # start/end methods) doesn't seem to break anything.
+        # keep changes in the main_splitter from immediately causing adjustments
+        # to child_splitter, resize child_splitter after a sash drag finishes
         for s in (self.main_splitter, self.child_splitter):
             s.Bind(wx.EVT_SPLITTER_SASH_POS_CHANGING, self.start_resizing)
             s.Bind(wx.EVT_SPLITTER_SASH_POS_CHANGED, self.end_resizing)
@@ -203,8 +202,8 @@
             if (height > 0 and bottom is not None and
                 bottom.height != bottom.ideal_height):
                 trellis.on_commit(
-                    splitter.update_sash,
-                    float(height - bottom.ideal_height) / height
+                    splitter.update_gravity,
+                    height - bottom.ideal_height
                 )
 
     def __init__(self, app):
@@ -226,7 +225,7 @@
         sum = summary.SummaryPresentation(self.main_view, self.app.sidebar[0].items)
         sum.View.Name = 'list'
         cal = calendar_main.CalendarPresentation(self.main_view,
-                                                 many_days=self.app.all_days,
+                                                 many_days=app_cells['all_days'],
                                                  range_start=app_cells['selected_date'],
                                                  range_mode=app_cells['range_mode'],
                                                  )

Modified: branches/rearchitecture/Chandler-Platform/ocap/wxui/calendar_canvas.py (16047 => 16048)

--- branches/rearchitecture/Chandler-Platform/ocap/wxui/calendar_canvas.py	2007-12-05 20:53:26 UTC (rev 16047)
+++ branches/rearchitecture/Chandler-Platform/ocap/wxui/calendar_canvas.py	2007-12-05 21:27:20 UTC (rev 16048)
@@ -22,6 +22,8 @@
 from wx.lib.stattext import GenStaticText
 import wx.lib.newevent
 from wx import colheader
+from colors import get_lozonge_colors
+import itertools
 
 _ = lambda x : x
 
@@ -65,25 +67,17 @@
 
 SetRangeEvent,     EVT_SET_RANGE      = wx.lib.newevent.NewEvent()
 SetRangeModeEvent, EVT_SET_RANGE_MODE = wx.lib.newevent.NewEvent()
+SelectItemsEvent,  EVT_SELECT_ITEMS   = wx.lib.newevent.NewEvent()
 
+DefaultColors = get_lozonge_colors('Blue', 'UnSelected')
+DefaultSelectedColors = get_lozonge_colors('Blue', 'Selected')
+
 class InitializeSlots(object):
     __slots__ = ()
     def __init__(self, **kw):
         for slot in self.__slots__:
             setattr(self, slot, kw.get(slot))
 
-class LozengeColors(InitializeSlots):
-    __slots__ = ('text', 'outline', 'halo', 'gradient_left', 'gradient_right')
-
-DefaultColors = LozengeColors(
-    text = wx.WHITE,
-    outline = wx.Color(0, 102, 204),
-    halo = wx.Color(255,255,255, 128),
-    gradient_left = wx.Color(0, 63, 127),
-    gradient_right = wx.Color(0, 102, 204),
-)
-
-
 class Event(InitializeSlots):
     __slots__ = ('id', 'title', 'start', 'duration', 'color', 'swatch_colors')
     def __cmp__(self, other):
@@ -117,7 +111,31 @@
         self.start = self.end = self.front_event = None
         self.levels = []
         self.event_list = []
+        
+    def __iter__(self, reverse=False):
+        """Yield (depth, event) in draw order."""
+        if self.front_event is None:
+            depths = xrange(len(self.levels))
+            if reverse:
+                depths = reversed(depths)
+        else:
+            for depth, level in enumerate(self.levels):
+                if self.front_event in level:
+                    break
+            start = range(depth + 1)
+            end   = range(depth + 1, len(self.levels))
+            end.reverse()
+            depths = end + start
+            if reverse:
+                depths.reverse()
 
+        for depth in depths:
+            for event in self.levels[depth]:
+                yield depth, event
+
+    def __reversed__(self):
+        return self.__iter__(True)
+
     def add_to_levels(self, event):
         for level in self.levels:
             if event.overlaps(level[0]) and event < level[0]:
@@ -159,7 +177,7 @@
             event_list = []
         self.reset(event_list)
 
-    def change(self, event):
+    def change(self, event, move_to_front=False):
         if event in self.event_list:
             self.reset(self.event_list)
         else:
@@ -179,9 +197,11 @@
                         first_cluster.add(event)
                     self.clusters.remove(cluster)
             else:
-                new_cluster = OverlapCluster()
-                new_cluster.add(event)
-                self.clusters.append(new_cluster)
+                first_cluster = OverlapCluster()
+                first_cluster.add(event)
+                self.clusters.append(first_cluster)
+            if move_to_front:
+                first_cluster.front_event = event
 
     def reset(self, event_list):
         self.event_list = []
@@ -203,6 +223,7 @@
         super(EventsForWeek, self).__init__(start, event_list)
         self.duration = timedelta(7)
 
+lozenge_cache = {}
 
 class Calendar(wx.ScrolledWindow):
     def __init__(self, time_formatter=None, *arguments, **keywords):
@@ -211,8 +232,11 @@
         self.Bind(wx.EVT_PAINT, self.OnPaint)
         self.Bind(wx.EVT_SIZE,  self.OnSize)
         self.Bind(wx.EVT_ERASE_BACKGROUND, lambda x: None)
+        self.Bind(wx.EVT_LEFT_DOWN, self.OnClick)
+        self.Bind(EVT_SELECT_ITEMS, self.SelectItems)
 
         self.events = {}
+        self.selected_ids = []
         # EventsForDay or EventsForWeek associated with the current range
         self.intervals = []
 
@@ -314,28 +338,22 @@
         for interval in self.intervals:
             for cluster in interval.clusters:
                 max_depth = len(cluster.levels)
-                for depth, level in enumerate(cluster.levels):
-                    for event in level:
-                        args = event, interval, depth, max_depth
-                        rect, truncate, draw_text = self.LozengePosition(*args)
-                        self.DrawLozenge(gc, event, rect, truncate, draw_text)
+                for depth, event in cluster:
+                    args = event, interval, depth, max_depth
+                    rect, truncate, draw_text = self.LozengeGeometry(*args)
+                    self.DrawLozenge(gc, event, rect, truncate, draw_text)
 
-    def LozengePosition(self, event, range, depth, max_depth):
-        """Return (rect, truncate, draw_text)."""
-        start = max(range.start, event.start)
-        hour_start = start.hour + start.minute/60.0
-        end = min(range.end, event.end)
+    def RectFromTime(self, start, end, depth=1, max_depth=1):
         duration = end - start
         hours = duration.seconds / 3600.0 + 24.0*duration.days
         column = (start - self.range_start).days
-        
         if self.range_mode == 'week':
             x = BASE_DAY_WIDTH*column
-            width = BASE_DAY_WIDTH
+            width = BASE_DAY_WIDTH * max(1, duration.days)
         elif self.range_mode == 'day':
             x = 0
             width = BASE_DAY_WIDTH*7
-        y = BASE_HOUR_HEIGHT*hour_start
+        y = BASE_HOUR_HEIGHT*(start.hour + start.minute/60.0)
         rect = wx.Rect2D(x, y, width, BASE_HOUR_HEIGHT*hours)
 
         if max_depth > 1:
@@ -345,44 +363,74 @@
             else:
                 rect.Inset(depth/(max_depth - 1)*width*0.2, 0, 0, 0)
                 rect.width = width * 0.8
-        
-        rect = TransformRect(self.matrix, rect)
-        rect.Inset(HALO_WIDTH, HALO_WIDTH)
 
         min_height = 2*TEXT_Y_MARGIN + self.title_font_height
         if rect.height < min_height:
-            rect.SetBottom(min(self.hour_height * 24 - 1, rect.y + min_height))
+            rect.SetBottom(min(self.hour_height * 24, rect.y + min_height))
+
+        return TransformRect(self.matrix, rect)
+
+    def SidesToTruncate(self, real_start, real_end, lozenge_start, lozenge_end):
+        truncate = 0 if real_start >= lozenge_start else wx.TOP
+        return truncate | (0 if real_end <= lozenge_end else wx.BOTTOM)
     
+    def LozengeGeometry(self, event, range, depth, max_depth):
+        """Return (rect, truncate, draw_text)."""
+        start = max(range.start, event.start)
+        end = min(range.end, event.end)
+        rect = self.RectFromTime(start, end, depth, max_depth)
+        
+        rect.Inset(HALO_WIDTH, HALO_WIDTH)
+        
+        column = (start - self.range_start).days
         if column == 0 and depth == 0:
             # don't let the halo overlap the legend border by too much
             rect.Inset(.5, 0, 0, 0)
 
-        truncate = 0
-        if event.start < start:
-            truncate |= wx.TOP
-        if event.end > end:
-            truncate |= wx.BOTTOM
+        truncate = self.SidesToTruncate(event.start, event.end, start, end)
+        return tuple(rect), truncate, event.start >= start or column == 0
+    
+    def DrawLozenge(self, real_gc, event, rect_tup, truncate, draw_text):
+        rect = wx.Rect2D(*rect_tup)
+        bitmap_margin = int(HALO_WIDTH)
+        w = int(rect.width) + 2*(bitmap_margin + 1)
+        h = int(rect.height) + 2*(bitmap_margin + 1)
+
+        draw_rect = wx.Rect2D(int(rect.x) - bitmap_margin,
+                              int(rect.y) - bitmap_margin, w, h)
         
-        return rect, truncate, event.start >= start or column == 0
-    
-    def DrawLozenge(self, gc, event, rect, truncate, draw_text):
+        colors = (DefaultSelectedColors if event.id in self.selected_ids
+                                        else DefaultColors)
+
+        cache_key = (event.id, rect_tup, truncate, draw_text, colors)
+        bitmap = lozenge_cache.get(cache_key)
+        if bitmap:
+            real_gc.DrawBitmap(bitmap, *draw_rect)
+            return
+        
+        bitmap = lozenge_cache[cache_key] = transparent_bitmap(w, h)
+        rect.x = rect.x - int(rect.x) + bitmap_margin
+        rect.y = rect.y - int(rect.y) + bitmap_margin
+        
+        mdc = wx.MemoryDC(bitmap)
+        gc = wx.GraphicsContext.Create(mdc)
+        
         # Room for how many swatches (min 2)?  Draw swatches
         if not draw_text:
             # continuation lozenge, just draw a small-radius lozenge
-            DrawFilledLozenge(gc, rect, SMALL_RADIUS, truncate = truncate)
+            DrawFilledLozenge(gc, rect, SMALL_RADIUS, colors, truncate)
         else:
             line_height = self.title_font_height
             min_height = 2*TEXT_Y_MARGIN + line_height
             
             radius = SMALL_RADIUS if rect.height > min_height else rect.height/2
-            DrawFilledLozenge(gc, rect, radius, truncate = truncate)
+            DrawFilledLozenge(gc, rect, radius, colors, truncate)
 
             time_height = 2*TIME_Y_MARGIN + self.time_font_height
 
             rect.Inset(TEXT_X_MARGIN - 1, 0)
             gc.Clip(*rect)
             rect.Inset(1, 0)
-
             if rect.height <= time_height + line_height:
                 # room for just one line of text
                 rect.Inset(radius/3, 0, 0, 0)
@@ -402,6 +450,8 @@
 
             gc.ResetClip()
 
+        real_gc.DrawBitmap(bitmap, *draw_rect)
+
     def DrawBackground(self, gc):
         gc.SetPen(wx.Pen(MINOR_LINE_COLOR))
         gc.StrokePath(self.GetHalfHourLinePath(gc))
@@ -494,6 +544,7 @@
                 gc.StrokeLine(10, down, left - 3, down)
 
     def OnSize(self, event):
+        lozenge_cache.clear()
         width, height = self.GetSize()
         self.SetVirtualSize((width, self.hour_height * 24))
         self.SetScrollRate(0, self.hour_height / 3)
@@ -514,6 +565,49 @@
     def end(self):
         return self.start + self.duration
 
+    def SelectItems(self, evt):
+        local = set(id for id in  evt.selected_ids if id in self.events)
+        old   = set(id for id in self.selected_ids if id in self.events)
+        self.selected_ids = evt.selected_ids
+        
+        if local != old:
+            local_selected_events = set(self.events[id] for id in local)
+            if local:
+                for interval in self.intervals:
+                    if local_selected_events.intersection(interval.event_list):
+                        for cluster in interval.clusters:
+                            for event in cluster.event_list:
+                                if event.id in local:
+                                    cluster.front_event = event
+                                    break
+            self.Refresh(False)
+
+    def TopItemFromPosition(self, pos):
+        def match(obj, depth, constrain, max_depth=0):
+            start, end = obj.start, obj.end
+            if constrain:
+                start = max(constrain.start, start)
+                end = min(constrain.end, end)
+            return self.RectFromTime(start, end, depth, max_depth).Contains(pos)
+            
+        def matches(iterable, depth=0, constrain=None):
+            for obj in iterable:
+                if match(obj, depth, constrain):
+                    yield obj
+                    break
+
+        for interval in matches(self.intervals, -1):
+            for cluster in matches(interval.clusters, -1, constrain=interval):
+                for depth, event in reversed(cluster):
+                    if match(event, depth, interval, len(cluster.levels)):
+                        return event
+
+    def OnClick(self, wx_evt):
+        position = wx.Point2D(*self.CalcUnscrolledPosition(wx_evt.Position))
+        event = self.TopItemFromPosition(position)
+        selected_id = None if not event else event.id
+        wx.PostEvent(self, SelectItemsEvent(selected_ids=[selected_id]))
+
     def SetRange(self, start):
         self.range_start = start
         self.Reset()
@@ -527,11 +621,11 @@
 
     def FillIntervals(self):
         if self.range_start is not None:
-            for event in sorted(self.events.itervalues()):
-                if event.overlaps(self):
+            for ev in sorted(self.events.itervalues()):
+                if ev.overlaps(self):
                     for interval in self.intervals:
-                        if event.overlaps(interval):
-                            interval.change(event)
+                        if ev.overlaps(interval):
+                            interval.change(ev, ev.id in self.selected_ids)
 
     def Reset(self):
         """Create empty EventsForDay/EventsForWeek for the current range."""
@@ -598,39 +692,22 @@
         self.FillIntervals()
         self.Refresh(False)
 
-    def LozengePosition(self, event, range, depth, max_depth):
-        """Return (rect, truncate, draw_text)."""
-        start = max(range.start, event.start)
-        end = min(range.end, event.end)
-        column = (start - self.range_start).days
-        duration = max(1, (end - start).days)
-        height = 2*TEXT_Y_MARGIN + self.title_font_height + 2*HALO_WIDTH
-        
-        if self.range_mode == 'week':
-            x = BASE_DAY_WIDTH*column
-            width = BASE_DAY_WIDTH*duration
-        elif self.range_mode == 'day':
-            x = 0
-            width = BASE_DAY_WIDTH*7
-        rect = wx.Rect2D(x, 0, width, 0)
-        rect = TransformRect(self.matrix, rect)
-        rect.y = height*depth
-        rect.height = height
-        rect.Inset(HALO_WIDTH, HALO_WIDTH)
+    def RectFromTime(self, start, end, depth=-1, max_depth=0):
+        rect = super(AllDayCalendar, self).RectFromTime(start, end)
+        # usually for AllDay events, height should be set small, but in order
+        # to allow a rect to be calculated for the whole day, leave height
+        # large if no depth is passed in
+        if depth >= 0:
+            height = 2*TEXT_Y_MARGIN + self.title_font_height + 2*HALO_WIDTH
+            rect.y = height*depth
+            rect.height = height
+        return rect
 
-        if column == 0 and depth == 0:
-            # don't let the halo overlap the legend border by too much
-            rect.Inset(.5, 0, 0, 0)
+    def SidesToTruncate(self, real_start, real_end, lozenge_start, lozenge_end):
+        truncate = 0 if real_start >= lozenge_start else wx.LEFT
+        return truncate | (0 if real_end <= lozenge_end else wx.RIGHT)
 
-        truncate = 0
-        if event.start < start:
-            truncate |= wx.LEFT
-        if event.end > end:
-            truncate |= wx.RIGHT
-        
-        return rect, truncate, True
 
-
 class CalendarPanel(wx.Panel):
     def __init__(self, parent, **kw):
         super(CalendarPanel, self).__init__(parent, -1, style=wx.NO_BORDER, **kw)
@@ -889,6 +966,20 @@
     gc.SetFont(font)
     return gc.GetTextExtent('M')[1]
 
+empty = '\x00' * 300**2
+
+def transparent_bitmap(w, h):
+    image = wx.EmptyImage(w, h)
+    image.InitAlpha()
+    alpha = image.GetAlphaBuffer()
+    if len(alpha) < len(empty):
+        alpha[:] = empty[:len(alpha)]
+    else:
+        for i in xrange(len(alpha)):
+            alpha[i] = '\x00'
+
+    return wx.BitmapFromImage(image)
+
 def shortTZ(dt, tzinfo=None):
     """
     Return an empty string or the short timezone string for dt if dt.tzinfo

Added: branches/rearchitecture/Chandler-Platform/ocap/wxui/colors.conf (16047 => 16048)

--- branches/rearchitecture/Chandler-Platform/ocap/wxui/colors.conf	2007-12-05 20:53:26 UTC (rev 16047)
+++ branches/rearchitecture/Chandler-Platform/ocap/wxui/colors.conf	2007-12-05 21:27:20 UTC (rev 16048)
@@ -0,0 +1,204 @@
+[summary]
+SectionBackground = rgbcccccc
+SectionLabel = rgb000000
+SectionCount = rgb888888
+SectionSample_sectionTriageStatus_now = rgb00cc00
+SectionSample_sectionTriageStatus_later = rgbffcc00
+SectionSample_sectionTriageStatus_done = rgb555555
+
+[colororder]
+# listed colors must all be on one line
+order = Blue, Green, Red, Orange, Gold, Plum, Turquoise, Fuchsia, Indigo
+
+[colors]
+# Names of colors and their hue.  To be used, a color must appear in colors
+# and colororder.  Also, checked and unchecked icons for the color should
+# be added to Chandler.egg-info/resources/images, these images are used for menu
+# icons.  Finally, to be localized, color name strings should be kept in sync
+# with parcels/osaf/usercollections.py
+Blue        = 210
+Green       = 120
+Red         = 0
+Orange      = 30
+Gold        = 50
+Plum        = 300
+Turquoise   = 170
+Fuchsia     = 330
+Indigo      = 270
+
+
+[calendarcanvas]
+
+######### Selected Lozenges ################
+
+SelectedGradientLeftSaturation    = 1.0
+SelectedGradientLeftValue         = 0.5
+
+SelectedGradientRightSaturation   = 1.0
+SelectedGradientRightValue        = 0.8
+
+SelectedOutlineSaturation         = 1.0
+SelectedOutlineValue              = 0.8
+
+SelectedTextSaturation            = 0.0
+SelectedTextValue                 = 1.0
+
+######### Unselected Lozenges ##############
+UnSelectedGradientLeftSaturation    = 1.0
+UnSelectedGradientLeftValue         = 0.8
+
+UnSelectedGradientRightSaturation   = 0.8
+UnSelectedGradientRightValue        = 1.0
+
+UnSelectedOutlineSaturation         = 0.8
+UnSelectedOutlineValue              = 1.0
+
+UnSelectedTextSaturation            = 0.0
+UnSelectedTextValue                 = 1.0
+
+########## Overlaid Lozenges ###############
+OverlayGradientLeftSaturation    = 0.33
+OverlayGradientLeftValue         = 1.0
+
+OverlayGradientRightSaturation   = 0.33
+OverlayGradientRightValue        = 1.0
+
+OverlayOutlineSaturation         = 0.33
+OverlayOutlineValue              = 1.0
+
+OverlayTextSaturation            = 1.0
+OverlayTextValue                 = 0.8
+
+#### Selected FYI/Anytime/@Time Lozenges ########
+
+SelectedFYIGradientLeftSaturation    = 0.33
+SelectedFYIGradientLeftValue         = 1.0
+
+SelectedFYIGradientRightSaturation   = 0.15
+SelectedFYIGradientRightValue        = 1.0
+
+SelectedFYIOutlineSaturation         = 0.8
+SelectedFYIOutlineValue              = 1.0
+
+SelectedFYITextSaturation            = 1.0
+SelectedFYITextValue                 = 0.8
+
+#### Unselected FYI/Anytime/@Time Lozenges ######
+UnSelectedFYIGradientLeftSaturation    = 0.11
+UnSelectedFYIGradientLeftValue         = 1.0
+
+UnSelectedFYIGradientRightSaturation   = 0.05
+UnSelectedFYIGradientRightValue        = 1.0
+
+UnSelectedFYIOutlineSaturation         = 0.8
+UnSelectedFYIOutlineValue              = 1.0
+
+UnSelectedFYITextSaturation            = 1.0
+UnSelectedFYITextValue                 = 0.8
+
+#### Overlaid FYI/Anytime/@Time Lozenges ########
+OverlayFYIGradientLeftSaturation    = 0.05
+OverlayFYIGradientLeftValue         = 1.0
+
+OverlayFYIGradientRightSaturation   = 0.05
+OverlayFYIGradientRightValue        = 1.0
+
+OverlayFYIOutlineSaturation         = 0.15
+OverlayFYIOutlineValue              = 1.0
+
+OverlayFYITextSaturation            = 1.0
+OverlayFYITextValue                 = 0.8
+
+
+######## Default swatch colors ##########
+
+SelectedSwatchOutlineSaturation     = 0.0
+SelectedSwatchOutlineValue          = 1.0
+
+SelectedFYISwatchOutlineSaturation  = 0.0
+SelectedFYISwatchOutlineValue       = 1.0
+
+OverlaySwatchOutlineSaturation      = 0.0
+OverlaySwatchOutlineValue           = 1.0
+
+OverlayFYISwatchOutlineSaturation   = 0.0
+OverlayFYISwatchOutlineValue        = 1.0
+
+
+######## Color-specific lozenge colors ##########
+# To override gradients/text/outline colors for a particular color,
+# add an entry whose key is Color + Type where type matches one of the
+# default keys above.
+
+BlueUnSelectedGradientRightValue            = 0.95
+BlueUnSelectedOutlineValue                  = 0.95
+
+GreenSelectedGradientLeftValue              = 0.44
+GreenSelectedGradientRightValue             = 0.66
+GreenSelectedOutlineValue                   = 0.66
+
+GreenUnSelectedGradientLeftValue            = 0.6
+GreenUnSelectedGradientRightSaturation      = 1.0
+GreenUnSelectedGradientRightValue           = 0.77
+GreenUnSelectedOutlineSaturation            = 1.0
+GreenUnSelectedOutlineValue                 = 0.77
+GreenOverlayGradientLeftValue               = 0.95
+GreenOverlayGradientRightValue              = 0.95
+GreenOverlayOutlineValue                    = 0.95
+GreenOverlayTextValue                       = 0.66
+
+GreenSelectedFYIOutlineValue                = 0.66
+GreenSelectedFYITextValue                   = 0.66
+GreenUnselectedFYIOutlineValue              = 0.66
+GreenUnselectedFYITextValue                 = 0.66
+GreenOverlayFYIOutlineValue                 = 0.95
+GreenOverlayFYITextValue                    = 0.66
+
+GoldUnselectedGradientLeftValue             = 0.75
+GoldUnselectedGradientRightValue            = 0.9
+GoldUnselectedOutlineValue                  = 0.9
+GoldOverlayGradientLeftValue                = 0.95
+GoldOverlayGradientRightValue               = 0.95
+GoldOverlayOutlineValue                     = 0.95
+GoldOverlayTextValue                        = 0.66
+
+GoldSelectedFYIOutlineValue                 = 0.66
+GoldSelectedFYITextValue                    = 0.66
+GoldUnSelectedFYIOutlineValue               = 0.66
+GoldUnSelectedFYITextValue                  = 0.66
+GoldOverlayFYIOutlineValue                  = 0.95
+GoldOverlayFYITextValue                     = 0.66
+
+PlumSelectedGradientLeftValue               = 0.44
+PlumSelectedGradientRightValue              = 0.66
+PlumSelectedOutlineValue                    = 0.66
+
+PlumUnSelectedGradientLeftValue             = 0.66
+PlumUnSelectedGradientRightSaturation       = 1.0
+PlumUnSelectedGradientRightValue            = 0.88
+PlumUnSelectedOutlineSaturation             = 1.0
+PlumUnSelectedOutlineValue                  = 0.88
+PlumOverlayTextValue                        = 0.66
+
+PlumSelectedFYIOutlineValue                 = 0.66
+PlumSelectedFYITextValue                    = 0.66
+PlumUnselectedFYIOutlineValue               = 0.66
+PlumUnselectedFYITextValue                  = 0.66
+PlumOverlayFYITextValue                     = 0.66
+
+TurquoiseSelectedGradientRightValue         = 0.75
+TurquoiseSelectedOutlineValue               = 0.75
+TurquoiseUnSelectedGradientLeftValue        = 0.66
+TurquoiseUnSelectedGradientRightSaturation  = 1.0
+TurquoiseUnSelectedGradientRightValue       = 0.85
+TurquoiseOverlayGradientLeftValue           = 0.95
+TurquoiseOverlayGradientRightValue          = 0.95
+TurquoiseOverlayOutlineValue                = 0.95
+TurquoiseOverlayTextValue                   = 0.66
+
+TurquoiseSelectedFYIOutlineValue            = 0.66
+TurquoiseSelectedFYITextValue               = 0.66
+TurquoiseUnSelectedFYIOutlineValue          = 0.66
+TurquoiseUnSelectedFYITextValue             = 0.66
+TurquoiseOverlayFYIOutlineValue             = 0.95
+TurquoiseOverlayFYITextValue                = 0.66

Added: branches/rearchitecture/Chandler-Platform/ocap/wxui/colors.py (16047 => 16048)

--- branches/rearchitecture/Chandler-Platform/ocap/wxui/colors.py	2007-12-05 20:53:26 UTC (rev 16047)
+++ branches/rearchitecture/Chandler-Platform/ocap/wxui/colors.py	2007-12-05 21:27:20 UTC (rev 16048)
@@ -0,0 +1,61 @@
+from __future__ import with_statement
+from ConfigParser import SafeConfigParser, NoOptionError
+from os.path import dirname, join
+from colorsys import rgb_to_hsv, hsv_to_rgb
+import wx
+
+cfg = SafeConfigParser()
+
+with file(join(dirname(__file__), 'colors.conf'), 'r') as f:
+    cfg.readfp(f)
+
+# hue -> colorName mapping
+hue_map = dict((int(v), k) for k, v in cfg.items('colors'))
+
+def color_from_type(hue, lozenge_type):
+    def rgb2color(r, g, b):
+        return int(r*255), int(g*255), int(b*255)
+    
+    def value_from_name(hue, name):
+        degrees = int(hue*360)
+        hue_name = hue_map.get(degrees)
+        if hue_name is None:
+            # int rounds floats down, try rounding up
+            hue_name = hue_map.get(degrees + 1)
+        if hue_name is not None:
+            try:
+                return cfg.getfloat('calendarcanvas', hue_name + name)
+            except NoOptionError:
+                pass
+        return cfg.getfloat('calendarcanvas', name)
+
+    return rgb2color(*hsv_to_rgb(hue,
+                        value_from_name(hue, lozenge_type + 'Saturation'),
+                        value_from_name(hue, lozenge_type + 'Value'))
+                     )
+
+colors_cache = {}
+suffixes = 'Text', 'Outline', 'GradientLeft', 'GradientRight'
+halo_color = wx.Color(255,255,255, 128)
+
+class LozengeColors(object):
+    __slots__ = ('text', 'outline', 'gradient_left', 'gradient_right', 'halo')
+
+
+def get_lozonge_colors(hue, prefix):
+    if isinstance(hue, basestring):
+        hue = cfg.getint('colors', hue)/360.0
+    colors = colors_cache.get((hue, prefix))
+    if colors is not None:
+        return colors
+
+    colors = colors_cache[(hue, prefix)] = LozengeColors()
+    
+    for suffix, attr in zip(suffixes, colors.__slots__[:4]):
+        color_tuple = color_from_type(hue, prefix + suffix)
+        setattr(colors, attr, wx.Color(*color_tuple))
+    
+    # for now, this is a constant
+    colors.halo = halo_color
+    
+    return colors
Property changes on: branches/rearchitecture/Chandler-Platform/ocap/wxui/colors.py
___________________________________________________________________
Name: svn:eol-style
   + native

Modified: branches/rearchitecture/Chandler-Platform/ocap/wxui/layout.py (16047 => 16048)

--- branches/rearchitecture/Chandler-Platform/ocap/wxui/layout.py	2007-12-05 20:53:26 UTC (rev 16047)
+++ branches/rearchitecture/Chandler-Platform/ocap/wxui/layout.py	2007-12-05 21:27:20 UTC (rev 16048)
@@ -103,6 +103,7 @@
             return self.Size.width - self.SashSize
         
     def update_gravity(self, position):
+        self.SashPosition = position
         self.SashGravity = float(position)/self.get_size()
         # when trellis.on_commit calls, grandchildren's sizes don't update
         # properly




_______________________________________________
Commits mailing list
[email protected]
http://lists.osafoundation.org/mailman/listinfo/commits

Reply via email to