[hamster-applet] work on the "preview thing"
- From: Toms Baugis <tbaugis src gnome org>
- To: svn-commits-list gnome org
- Subject: [hamster-applet] work on the "preview thing"
- Date: Sun, 21 Jun 2009 10:50:02 -0400 (EDT)
commit f6f41235481c42522c89bf961245a6acf6f22a97
Author: Toms Bauģis <toms baugis gmail com>
Date: Sun Jun 21 15:48:39 2009 +0100
work on the "preview thing"
* added tickers, moved time inside, changed from that "glass over ruler" paradigm to good ol' "don't change time when scrolling".
* focusing next field on input
* there are some issues with pixel precision et al, but still this feels better
* made the scrolling less jumpy
* mouse cursor now gives the hint that preview is scrollable
hamster/edit_activity.py | 230 +++++++++++++++++++++++++++-------------------
1 files changed, 134 insertions(+), 96 deletions(-)
---
diff --git a/hamster/edit_activity.py b/hamster/edit_activity.py
index 49192e5..86032cd 100644
--- a/hamster/edit_activity.py
+++ b/hamster/edit_activity.py
@@ -63,7 +63,28 @@ class Dayline(graphics.Area):
self.in_motion = False
self.days = []
-
+
+ def draw(self, day_facts, highlight = None):
+ """Draw chart with given data"""
+ self.facts = day_facts
+ if self.facts:
+ self.days.append(self.facts[0]["start_time"].date())
+
+ start_time = highlight[0] - dt.timedelta(minutes = highlight[0].minute) - dt.timedelta(hours = 10)
+
+ if self.range_start:
+ self.range_start.target(start_time)
+ self.scroll_to_range_start()
+ else:
+ self.range_start = graphics.Integrator(start_time, damping = 0.35, attraction = 0.5)
+
+ self.highlight = highlight
+
+ self.show()
+
+ self.redraw_canvas()
+
+
def on_button_release(self, area, event):
if not self.drag_start:
return
@@ -71,21 +92,23 @@ class Dayline(graphics.Area):
self.drag_start, self.move_type = None, None
if event.state & gtk.gdk.BUTTON1_MASK:
- self.call_parent_time_changed()
+ self.__call_parent_time_changed()
def set_in_progress(self, in_progress):
self.in_progress = in_progress
- def call_parent_time_changed(self):
+ def __call_parent_time_changed(self):
#now calculate back from pixels into minutes
- start_time = self.get_value_at_pos(x = self.highlight_start)
- start_time = self.range_start.value + dt.timedelta(minutes = start_time)
-
- end_time = self.get_value_at_pos(x = self.highlight_end)
- end_time = self.range_start.value + dt.timedelta(minutes = end_time)
+ start_time = self.highlight[0]
+ end_time = self.highlight[1]
+
if self.on_time_changed:
self.on_time_changed(start_time, end_time)
-
+
+ def get_time(self, pixels):
+ minutes = self.get_value_at_pos(x = pixels)
+ return self.range_start.value + dt.timedelta(minutes = minutes)
+
def scroll_to_range_start(self):
if not self.in_motion:
self.in_motion = True
@@ -116,8 +139,6 @@ class Dayline(graphics.Area):
return True
else:
self.in_motion = False
- self.call_parent_time_changed()
-
return False
@@ -165,35 +186,36 @@ class Dayline(graphics.Area):
if mouse_down and self.drag_start:
start, end = 0, 0
- if self.move_type == "start":
- if 0 <= x <= self.width:
- start = x
- end = self.highlight_end
- elif self.move_type == "end":
- if 0 <= x <= self.width:
- start = self.highlight_start
- end = x
- elif self.move_type == "move":
- width = self.highlight_end - self.highlight_start
- start = x - self.drag_start
- start = max(0, min(start, self.width))
-
- end = start + width
- if end > self.width:
- end = self.width
- start = end - width
-
- if end - start > 1:
- self.highlight_start = start
- self.highlight_end = end
- self.redraw_canvas()
-
- if self.move_type == "scale_drag":
+ if self.move_type and self.move_type != "scale_drag":
+ if self.move_type == "start":
+ if 0 <= x <= self.width:
+ start = x
+ end = self.highlight_end
+ elif self.move_type == "end":
+ if 0 <= x <= self.width:
+ start = self.highlight_start
+ end = x
+ elif self.move_type == "move":
+ width = self.highlight_end - self.highlight_start
+ start = x - self.drag_start
+ start = max(0, min(start, self.width))
+
+ end = start + width
+ if end > self.width:
+ end = self.width
+ start = end - width
+
+ if end - start > 1:
+ self.highlight = (self.get_time(start), self.get_time(end))
+ self.redraw_canvas()
+
+ self.__call_parent_time_changed()
+ else:
self.range_start.target(self.drag_start_time +
dt.timedelta(minutes = self.get_value_at_pos(x = self.drag_start) - self.get_value_at_pos(x = x)))
self.scroll_to_range_start()
- self.call_parent_time_changed()
+
if start_drag:
area.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.LEFT_SIDE))
@@ -202,26 +224,9 @@ class Dayline(graphics.Area):
elif in_between:
area.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.FLEUR))
else:
- area.window.set_cursor(None)
+ area.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.SB_H_DOUBLE_ARROW))
- def draw(self, day_facts, highlight = None):
- """Draw chart with given data"""
- self.facts = day_facts
- if self.facts:
- self.days.append(self.facts[0]["start_time"].date())
-
- start_time = highlight[0] - dt.timedelta(minutes = highlight[0].minute) - dt.timedelta(hours = 10)
-
- self.range_start = graphics.Integrator(start_time, damping = 0.5, attraction = 0.7)
-
- self.highlight = highlight
-
- self.show()
-
- self.redraw_canvas()
-
-
def _minutes_from_start(self, date):
delta = (date - self.range_start.value)
return delta.days * 24 * 60 + delta.seconds / 60
@@ -242,76 +247,103 @@ class Dayline(graphics.Area):
graph_y = 4
- graph_height = self.height - 25
+ graph_height = self.height - 10
graph_y2 = graph_y + graph_height
# graph area
self.fill_area(0, graph_y - 1, self.width, graph_height, (1,1,1))
- context.set_source_rgb(0.7, 0.7, 0.7)
- context.rectangle(0, graph_y-1, self.width - 1, graph_height)
- context.stroke()
- #time scale
+ #bars
+ for fact in self.facts:
+ start_minutes = self._minutes_from_start(fact["start_time"])
+
+ if fact["end_time"]:
+ end_minutes = self._minutes_from_start(fact["end_time"])
+ else:
+ if fact["start_time"].date() > dt.date.today() - dt.timedelta(days=1):
+ end_minutes = self._minutes_from_start(dt.datetime.now())
+
+ if self.get_pixel(end_minutes) > 0 and \
+ self.get_pixel(start_minutes) < self.width:
+ context.set_source_rgba(0.86, 0.86, 0.86, 0.5)
+ context.rectangle(self.get_pixel(start_minutes), graph_y,
+ self.get_pixel(end_minutes) - self.get_pixel(start_minutes), graph_height - 1)
+ context.fill()
+ context.stroke()
+
+ context.set_source_rgba(0.86, 0.86, 0.86, 1)
+ self.move_to(start_minutes, graph_y)
+ self.line_to(start_minutes, graph_y2)
+ self.move_to(end_minutes, graph_y)
+ self.line_to(end_minutes, graph_y2)
+ context.stroke()
- #scale labels
+
+
+ #time scale
context.set_source_rgb(0, 0, 0)
+ self.layout.set_width(-1)
for i in range(minutes):
label_time = (self.range_start.value + dt.timedelta(minutes=i))
+
+ if label_time.minute == 0:
+ context.set_source_rgb(0.8, 0.8, 0.8)
+ self.move_to(i, graph_y2 - 15)
+ self.line_to(i, graph_y2)
+ context.stroke()
+ elif label_time.minute % 15 == 0:
+ context.set_source_rgb(0.8, 0.8, 0.8)
+ self.move_to(i, graph_y2 - 5)
+ self.line_to(i, graph_y2)
+ context.stroke()
+
+
+
if label_time.minute == 0 and label_time.hour % 2 == 0:
if label_time.hour == 0:
context.set_source_rgb(0.8, 0.8, 0.8)
self.move_to(i, graph_y)
self.line_to(i, graph_y2)
- label_minutes = label_time.strftime("%b %d.")
+ label_minutes = label_time.strftime("%b %d")
else:
- label_minutes = label_time.strftime("%H:%M")
+ label_minutes = label_time.strftime("%H<small><sup>%M</sup></small>")
- context.set_source_rgb(0, 0, 0)
- self.layout.set_text(label_minutes)
+ context.set_source_rgb(0.4, 0.4, 0.4)
+ self.layout.set_markup(label_minutes)
label_w, label_h = self.layout.get_pixel_size()
- context.move_to(self.get_pixel(x_value=i) - label_w/2,
- graph_y2 + 6)
+ context.move_to(self.get_pixel(i) + 2, graph_y2 - label_h - 8)
context.show_layout(self.layout)
context.stroke()
- #bars
- context.set_source_rgba(0.86, 0.86, 0.86, 0.5)
- for fact in self.facts:
- start_minutes = self._minutes_from_start(fact["start_time"])
-
- if fact["end_time"]:
- end_minutes = self._minutes_from_start(fact["end_time"])
- else:
- if fact["start_time"].date() == dt.date.today():
- end_minutes = self._minutes_from_start(dt.datetime.now())
-
- if self.get_pixel(x_value = end_minutes) > 0 and \
- self.get_pixel(x_value = start_minutes) < self.width:
- context.rectangle(self.get_pixel(x_value = start_minutes), graph_y,
- self.get_pixel(x_value=end_minutes) - self.get_pixel(x_value=start_minutes), graph_height - 1)
- context.fill()
-
-
-
+ #highlight rectangle
if self.highlight:
- self.highlight_start =self.get_pixel(x_value= self._minutes_from_start(self.highlight[0]))
- self.highlight_end = self.get_pixel(x_value=self._minutes_from_start(self.highlight[1]))
- self.highlight = None
-
+ self.highlight_start = self.get_pixel(self._minutes_from_start(self.highlight[0]))
+ self.highlight_end = self.get_pixel(self._minutes_from_start(self.highlight[1]))
- #highlight rectangle
- if self.highlight_start != None:
+ #TODO - make a proper range check here
+ if self.highlight_end > 0 and self.highlight_start < self.width:
rgb = colorsys.hls_to_rgb(.6, .7, .5)
- context.set_source_rgba(rgb[0], rgb[1], rgb[2], 0.5)
- context.rectangle(self.highlight_start, graph_y-3,
- self.highlight_end - self.highlight_start, graph_height + 4)
- context.fill_preserve()
+
+ self.fill_area(self.highlight_start, graph_y,
+ self.highlight_end - self.highlight_start, graph_height,
+ (rgb[0], rgb[1], rgb[2], 0.5))
+ context.stroke()
+
context.set_source_rgb(*rgb)
+ self.context.move_to(self.highlight_start, graph_y)
+ self.context.line_to(self.highlight_start, graph_y + graph_height)
+ self.context.move_to(self.highlight_end, graph_y)
+ self.context.line_to(self.highlight_end, graph_y + graph_height)
context.stroke()
+
+ #and now put a frame around the whole thing
+ context.set_source_rgb(0.7, 0.7, 0.7)
+ context.rectangle(0, graph_y-1, self.width - 1, graph_height)
+ context.stroke()
if self.move_type == "move" and (self.highlight_start == 0 or self.highlight_end == self.width):
if self.highlight_start == 0:
@@ -369,7 +401,7 @@ class CustomFactController:
self.start_date = widgets.DateInput(start_date)
self.get_widget("start_date_placeholder").add(self.start_date)
- self.start_date.connect("date-entered", self.validate_fields)
+ self.start_date.connect("date-entered", self.on_start_date_entered)
self.start_time = widgets.TimeInput(start_date)
self.get_widget("start_time_placeholder").add(self.start_time)
@@ -581,11 +613,16 @@ class CustomFactController:
def on_activity_combo_changed(self, combo):
self.validate_fields()
+ def on_start_date_entered(self, widget):
+ self.validate_fields()
+ self.start_time.grab_focus()
+
def on_start_time_entered(self, widget):
self.end_time.set_time(self.start_time.get_time() +
dt.timedelta(minutes = 30))
self.end_time.set_start_time(self.start_time.get_time())
self.validate_fields()
+ self.end_time.grab_focus()
def on_end_time_entered(self, widget):
self.validate_fields()
@@ -620,6 +657,7 @@ class CustomFactController:
looks_good = True
self.get_widget("save_button").set_sensitive(looks_good)
+ return looks_good
def on_window_key_pressed(self, tree, event_key):
if (event_key.keyval == gtk.keysyms.Escape
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]