Skip to content

Commit

Permalink
Add blobs of colour indicating tracks.
Browse files Browse the repository at this point in the history
  • Loading branch information
wjt committed Jan 27, 2011
1 parent 684799f commit 018c0ce
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 11 deletions.
42 changes: 31 additions & 11 deletions sojourner/eventlist.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,30 +6,32 @@
MaybeStackableWindow, MaybePannableArea, MagicCheckButton, STAR_ICON, esc
)
from sojourner.eventwindow import EventWindow
from sojourner.schedule import Event
from sojourner.schedule import Event, get_color

class EventList(MaybeStackableWindow):
COL_MARKUP = 0
COL_EVENT = 1
COL_FAVOURITED = 2
COL_IS_HEADER = 3
COL_IS_EVENT = 3
COL_SWATCH_COLOUR = 4

"""Shows a list of events; clicking on an event shows details of that
event."""
def __init__(self, schedule, title, events, event_fmt=Event.OMIT_DAY):
MaybeStackableWindow.__init__(self, title)
self.schedule = schedule
self.store = gtk.TreeStore(str, object, bool, bool)
self.store = gtk.TreeStore(str, object, bool, bool, gtk.gdk.Color)

for day_name, event_iter in groupby(events, lambda e: e.day_name()):
header = '<span size="x-large" foreground="#aaa">%s</span>' % (
esc(day_name))
self.store.append(None, (header, None, False, True))
self.store.append(None, (header, None, False, False, None))

for event in event_iter:
self.store.append(None,
(event.summary(fmt=event_fmt), event,
event in self.schedule.favourites, False))
event in self.schedule.favourites, True,
get_color(event.track)))

treeview = gtk.TreeView(self.store)
treeview.set_headers_visible(False)
Expand All @@ -38,14 +40,32 @@ def __init__(self, schedule, title, events, event_fmt=Event.OMIT_DAY):
tvcolumn = gtk.TreeViewColumn('Stuff')
treeview.append_column(tvcolumn)

# Here's a hack to show a chunk of colour at the left-hand side of
# events to indicate their track. We have a text renderer containing,
# erm, nothing, whose background colour we set. Then we have another
# one with a single space to add a consistent gap between the blob of
# colour and the event summary. This is easier than writing a custom
# cell renderer, or using CellRendererPixbuf.
swatch_cell = gtk.CellRendererText()
swatch_cell.set_property('text', '   ')
tvcolumn.pack_start(swatch_cell, False)
tvcolumn.add_attribute(swatch_cell, 'visible', EventList.COL_IS_EVENT)
tvcolumn.add_attribute(swatch_cell, 'background-gdk',
EventList.COL_SWATCH_COLOUR)

blank_cell = gtk.CellRendererText()
blank_cell.set_property('text', ' ')
tvcolumn.pack_start(blank_cell, False)
tvcolumn.add_attribute(swatch_cell, 'visible', EventList.COL_IS_EVENT)

cell = gtk.CellRendererText()
cell.set_property("ellipsize", pango.ELLIPSIZE_END)
tvcolumn.pack_start(cell, True)

def text_data_func(column, cell, model, i):
is_header, markup = self.store.get(i,
EventList.COL_IS_HEADER, EventList.COL_MARKUP)
xalign = 0.5 if is_header else 0.0
is_event, markup = self.store.get(i,
EventList.COL_IS_EVENT, EventList.COL_MARKUP)
xalign = 0.0 if is_event else 0.5
cell.set_properties(markup=markup, xalign=xalign)

tvcolumn.set_cell_data_func(cell, text_data_func)
Expand All @@ -63,10 +83,10 @@ def text_data_func(column, cell, model, i):

def event_activated(self, treeview, row, column):
i = self.store.get_iter(row)
is_header, event = self.store.get(i,
EventList.COL_IS_HEADER, EventList.COL_EVENT)
is_event, event = self.store.get(i,
EventList.COL_IS_EVENT, EventList.COL_EVENT)

if not is_header:
if is_event:
EventWindow(self.schedule, event, lambda state:
self.store.set(i, EventList.COL_FAVOURITED, state))

23 changes: 23 additions & 0 deletions sojourner/schedule.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
import cPickle
import os.path

import colorsys
import hashlib
import gtk

from sojourner.malvern import config_file, esc

def getChildrenByTagName(node, name):
Expand Down Expand Up @@ -63,6 +67,25 @@ def by_start_time(x, y):
class MalformedSchedule(Exception):
pass

# We deliberately stash the track colours outside of any object. There's no
# need to pickle these: they're based on the track name, so are stable.
swatches = {}

def get_color(track):
if track in swatches:
# In Violet
return swatches[track]
else:
# We pick nicely matching colours by fixing S and V and varying H. The
# first byte of an md5sum will do nicely for picking H!
m = hashlib.md5()
m.update(track)
h = ord(m.digest()[0]) / 255.0
r, g, b = colorsys.hsv_to_rgb(h, 0.9, 0.9)
swatch = gtk.gdk.Color(int(r * 65535), int(g * 65535), int(b * 65535))
swatches[track] = swatch
return swatch

class Schedule(object):
"""Version number for pickled event data. This must be incremented if this
class, or Event, is modified."""
Expand Down

0 comments on commit 018c0ce

Please sign in to comment.