[hamster-applet] bits and bobs, little things; trying to be pixel perfect, not jumping to next day just because it is



commit 5d527e7ecc995db05042f8dc14398defeea625b1
Author: Toms Bauģis <toms baugis gmail com>
Date:   Sun Apr 11 00:35:28 2010 +0100

    bits and bobs, little things; trying to be pixel perfect, not jumping to next day just because it is past midnight, and others

 src/hamster/widgets/dayline.py |  123 ++++++++++++++++++++++-----------------
 1 files changed, 69 insertions(+), 54 deletions(-)
---
diff --git a/src/hamster/widgets/dayline.py b/src/hamster/widgets/dayline.py
index 0f94096..a67e052 100644
--- a/src/hamster/widgets/dayline.py
+++ b/src/hamster/widgets/dayline.py
@@ -42,10 +42,10 @@ class Selection(graphics.Shape):
         self.add_child(self.start_label, self.end_label, self.duration_label)
 
     def draw_shape(self):
-        self.graphics.rectangle(0, 0, self.width, self.height - self.duration_label.height - 5.5)
+        self.graphics.rectangle(0, 0, self.width, self.height)
         self.graphics.fill(self.fill, 0.3)
 
-        self.graphics.rectangle(0, 0, self.width, self.height - self.duration_label.height - 5.5)
+        self.graphics.rectangle(0, 0, self.width, self.height)
         self.graphics.stroke(self.fill)
 
 
@@ -58,13 +58,13 @@ class Selection(graphics.Shape):
             else:
                 self.start_label.x = 5
 
-            self.start_label.y = self.height - self.start_label.height
+            self.start_label.y = self.height
 
         self.end_label.visible = self.fixed == False and self.end_time is not None
         if self.end_label.visible:
             self.end_label.text = self.end_time.strftime("%H:%M")
             self.end_label.x = self.width + 5
-            self.end_label.y = self.height - self.end_label.height
+            self.end_label.y = self.height
 
 
 
@@ -95,7 +95,9 @@ class DayLine(graphics.Scene):
         self.day_start = dt.time(day_start / 60, day_start % 60)
 
         self.view_time = start_time or dt.datetime.combine(dt.date.today(), self.day_start)
-        self.start_time = self.view_time - dt.timedelta(hours=12) # we will work with twice the time we will be displaying
+
+        self.scope_hours = 24
+
 
         self.fact_bars = []
         self.categories = []
@@ -107,20 +109,24 @@ class DayLine(graphics.Scene):
         self.connect("on-click", self.on_click)
 
 
+        self.plot_area = graphics.Sprite()
+
         self.selection = Selection()
         self.chosen_selection = Selection()
 
-        self.add_child(self.selection, self.chosen_selection)
+        self.plot_area.add_child(self.selection, self.chosen_selection)
 
         self.drag_start = None
         self.current_x = None
         self.snap_points = []
 
+        self.add_child(self.plot_area)
+
 
-    def set_facts(self, facts, highlight):
+    def plot(self, date, facts, select_start, select_end = None):
         for bar in self.fact_bars:
-            self.sprites.remove(bar)
-            
+            self.plot_area.sprites.remove(bar)
+
         self.fact_bars = []
         for fact in facts:
             fact_bar = graphics.Rectangle(0, 0, fill = "#aaa", stroke="#aaa") # dimensions will depend on screen situation
@@ -132,18 +138,16 @@ class DayLine(graphics.Scene):
                 fact_bar.category = len(self.categories)
                 self.categories.append(fact['category'])
 
-            self.add_child(fact_bar)
+            self.plot_area.add_child(fact_bar)
             self.fact_bars.append(fact_bar)
 
-        self.view_time = dt.datetime.combine(highlight[0].date(), self.day_start)
-        self.start_time = self.view_time - dt.timedelta(hours=12)
+        self.view_time = dt.datetime.combine((select_start - dt.timedelta(hours=self.day_start.hour, minutes=self.day_start.minute)).date(), self.day_start)
 
-        if highlight:
-            self.chosen_selection.start_time = highlight[0]
-            self.chosen_selection.end_time = highlight[1]
-            self.chosen_selection.width = None
-            self.chosen_selection.fixed = True
-            self.chosen_selection.visible = True
+        self.chosen_selection.start_time = select_start
+        self.chosen_selection.end_time = select_end
+        self.chosen_selection.width = None
+        self.chosen_selection.fixed = True
+        self.chosen_selection.visible = True
 
         self.redraw()
 
@@ -167,8 +171,8 @@ class DayLine(graphics.Scene):
         start_time = self.selection.start_time
         end_time = None
         if self.fact_bars:
-            times = [bar.fact['start_time'] for bar in self.fact_bars if bar.fact['start_time'] - start_time > dt.timedelta(minutes=1)]
-            times.extend([bar.fact['end_time'] for bar in self.fact_bars if bar.fact['end_time'] - start_time  > dt.timedelta(minutes=1)])
+            times = [bar.fact['start_time'] for bar in self.fact_bars if bar.fact['start_time'] - start_time > dt.timedelta(minutes=5)]
+            times.extend([bar.fact['start_time'] + bar.fact['delta'] for bar in self.fact_bars if bar.fact['start_time'] + bar.fact['delta'] - start_time  > dt.timedelta(minutes=5)])
             if times:
                 end_time = min(times)
 
@@ -178,9 +182,9 @@ class DayLine(graphics.Scene):
 
 
     def new_selection(self):
-        self.sprites.remove(self.selection)
+        self.plot_area.sprites.remove(self.selection)
         self.selection = Selection()
-        self.add_child(self.selection)
+        self.plot_area.add_child(self.selection)
         self.redraw()
 
     def on_mouse_move(self, scene, event):
@@ -203,78 +207,83 @@ class DayLine(graphics.Scene):
     def on_enter_frame(self, scene, context):
         g = graphics.Graphics(context)
 
-        vertical = 7
-        minute_pixel = (24.0 * 60) / self.width
+        self.plot_area.y = 15.5
+        self.plot_area.height = self.height - 30
+
+
+
+
+        vertical = min(self.plot_area.height / 5 , 7)
+        minute_pixel = (self.scope_hours * 60.0) / self.width
 
         snap_points = []
 
         g.set_line_style(width=1)
 
 
-        bottom = self.height - self.selection.end_label.height - 5
+
+
+        bottom = self.plot_area.y + self.plot_area.height
 
         for bar in self.fact_bars:
             bar.y = vertical * bar.category + 5
             bar.height = vertical
 
-
-            minutes = (bar.fact['start_time'] - self.view_time).seconds / 60 + (bar.fact['start_time'] - self.view_time).days * 24  * 60
+            bar_start_time = bar.fact['start_time'] - self.view_time
+            minutes = bar_start_time.seconds / 60 + bar_start_time.days * self.scope_hours  * 60
 
             bar.x = round(minutes / minute_pixel) + 0.5
             bar.width = round((bar.fact['delta']).seconds / 60 / minute_pixel)
 
-            snap_points.append(bar.x)
-            snap_points.append(bar.x + bar.width)
+            if not snap_points or bar.x - snap_points[-1][0] > 1:
+                snap_points.append((bar.x, bar.fact['start_time']))
+
+            if not snap_points or bar.x + bar.width - snap_points[-1][0] > 1:
+                snap_points.append((bar.x + bar.width, bar.fact['start_time'] + bar.fact['delta']))
 
         self.snap_points = snap_points
 
 
-        if self.view_time < dt.datetime.now() < self.view_time + dt.timedelta(hours = 24):
-            minutes = round((dt.datetime.now() - self.view_time).seconds / 60 / minute_pixel) + 0.5
-            g.move_to(minutes, 0)
-            g.line_to(minutes, bottom)
-            g.stroke("#f00", 0.4)
-            snap_points.append(minutes - 0.5)
-
         if self.chosen_selection.start_time and self.chosen_selection.width is None:
             # we have time but no pixels
             minutes = round((self.chosen_selection.start_time - self.view_time).seconds / 60 / minute_pixel) + 0.5
-            self.chosen_selection.x = minutes - 1
+            self.chosen_selection.x = minutes
             if self.chosen_selection.end_time:
                 self.chosen_selection.width = round((self.chosen_selection.end_time - self.chosen_selection.start_time).seconds / 60 / minute_pixel)
             else:
                 self.chosen_selection.width = 0
-            self.chosen_selection.height = self.height
+            self.chosen_selection.height = self.chosen_selection.parent.height
 
             # use the oportunity to set proper colors too
             self.chosen_selection.fill = self.get_style().bg[gtk.STATE_SELECTED].to_string()
             self.chosen_selection.duration_label.color = self.get_style().fg[gtk.STATE_SELECTED].to_string()
 
 
-        self.selection.visible = self.mouse_x is not None
+        self.selection.visible = self._mouse_in # TODO - think harder about the mouse_out event
 
         self.selection.width = 0
-        self.selection.height = self.height
+        self.selection.height = self.selection.parent.height
         if self.mouse_x:
             start_x = max(min(self.mouse_x, self.width-1), 0) #mouse, but within screen regions
 
             # check for snap points
             start_x = start_x + 0.5
             minutes = int(round(start_x * minute_pixel / 15)) * 15
+            start_time = self.view_time + dt.timedelta(hours = minutes / 60, minutes = minutes % 60)
+
             if snap_points:
-                delta, closest_snap = min((abs(start_x - i), i) for i in snap_points)
+                delta, closest_snap, time = min((abs(start_x - i), i, time) for i, time in snap_points)
 
 
                 if abs(closest_snap - start_x) < 5 and (not self.drag_start or self.drag_start != closest_snap):
                     start_x = closest_snap
-                    minutes = int(start_x * minute_pixel)
+                    minutes = (time.hour - self.day_start.hour) * 60 + time.minute - self.day_start.minute
+                    start_time = time
 
 
             self.current_x = minutes / minute_pixel
 
 
-            start_time = self.view_time + dt.timedelta(hours = minutes / 60, minutes = minutes % 60)
-
             end_time, end_x = None, None
             if self.drag_start:
                 minutes = int(self.drag_start * minute_pixel)
@@ -302,9 +311,8 @@ class DayLine(graphics.Scene):
 
         #time scale
         g.set_color("#000")
-        #self.layout.set_width(-1)
-
-        for i in range(24*60):
+        layout = g.create_layout(context, 8)
+        for i in range(self.scope_hours * 60):
             label_time = (self.view_time + dt.timedelta(minutes=i))
 
             if label_time.minute == 0:
@@ -320,20 +328,27 @@ class DayLine(graphics.Scene):
 
 
 
-            if label_time.minute == 0 and label_time.hour % 2 == 0:
+            if label_time.minute == 0 and label_time.hour % 4 == 0:
                 if label_time.hour == 0:
                     g.set_color((0.8, 0.8, 0.8))
-                    g.move_to(round(i / minute_pixel) + 0.5, 0)
+                    g.move_to(round(i / minute_pixel) + 0.5, self.plot_area.y)
                     g.line_to(round(i / minute_pixel) + 0.5, bottom)
                     label_minutes = label_time.strftime("%b %d")
                 else:
                     label_minutes = label_time.strftime("%H<small><sup>%M</sup></small>")
 
                 g.set_color((0.4, 0.4, 0.4))
-                #self.layout.set_markup(label_minutes)
-                #label_w, label_h = self.layout.get_pixel_size()
-
-                #g.move_to(round(i * pixels_in_minute) + 2, graph_y2 - label_h - 8)
+                layout.set_markup(label_minutes)
+                label_w, label_h = layout.get_pixel_size()
 
-                #context.show_layout(self.layout)
+                g.move_to(round(i / minute_pixel) + 2, 0)
+                context.show_layout(layout)
         g.stroke()
+
+        #current time
+        if self.view_time < dt.datetime.now() < self.view_time + dt.timedelta(hours = self.scope_hours):
+            minutes = round((dt.datetime.now() - self.view_time).seconds / 60 / minute_pixel) + 0.5
+            g.move_to(minutes, self.plot_area.y)
+            g.line_to(minutes, bottom)
+            g.stroke("#f00", 0.4)
+            snap_points.append(minutes - 0.5)



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