[hamster-applet] removed the integrator and confused the whole thing with random addittions. will clear out later
- From: Toms Baugis <tbaugis src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [hamster-applet] removed the integrator and confused the whole thing with random addittions. will clear out later
- Date: Fri, 27 Nov 2009 20:47:41 +0000 (UTC)
commit c63914b106c4461861a67d52e509f6f946a53caa
Author: Toms Bauģis <toms baugis gmail com>
Date: Fri Nov 27 20:47:30 2009 +0000
removed the integrator and confused the whole thing with random addittions. will clear out later
hamster/widgets/dayline.py | 189 +++++++++++++++-----------------------------
1 files changed, 63 insertions(+), 126 deletions(-)
---
diff --git a/hamster/widgets/dayline.py b/hamster/widgets/dayline.py
index 3054f1a..57338b4 100644
--- a/hamster/widgets/dayline.py
+++ b/hamster/widgets/dayline.py
@@ -54,6 +54,8 @@ class DayLine(graphics.Area):
self.in_progress = False
self.range_start = None
+ self.range_start_int = None #same date just expressed as integer so we can interpolate it (a temporar hack)
+
self.in_motion = False
self.days = []
@@ -71,11 +73,15 @@ class DayLine(graphics.Area):
start_time = highlight[0] - dt.timedelta(minutes = highlight[0].minute) - dt.timedelta(hours = 10)
+ start_time_int = int(time.mktime(start_time.timetuple()))
+
if self.range_start:
- self.range_start.value = start_time
+ self.range_start = start_time
self.scroll_to_range_start()
else:
- self.range_start = Integrator(start_time, damping = 0.35, attraction = 0.5)
+ self.range_start = start_time
+ self.range_start_int = start_time_int
+
self.highlight = highlight
@@ -106,61 +112,32 @@ class DayLine(graphics.Area):
def get_time(self, pixels):
minutes = self.get_value_at_pos(x = pixels)
- return self.range_start.value + dt.timedelta(minutes = minutes)
+ return dt.datetime.fromtimestamp(self.range_start_int) + dt.timedelta(minutes = minutes)
- def scroll_to_range_start(self):
- if not self.in_motion:
- self.in_motion = True
- gobject.timeout_add(1000 / 30, self.animate_scale)
-
-
- def animate_scale(self):
- moving = self.range_start.update() > 5
-
-
- # check if maybe we are approaching day boundaries and should ask for
- # more data!
- if self.on_more_data:
- now = self.range_start.value
- date_plus = (now + dt.timedelta(hours = 12 + 2*4 + 1)).date()
- date_minus = (now - dt.timedelta(hours=1)).date()
-
- if date_minus != now.date() and date_minus not in self.days:
- self.facts += self.on_more_data(date_minus)
- self.days.append(date_minus)
- elif date_plus != now.date() and date_plus not in self.days:
- self.facts += self.on_more_data(date_plus)
- self.days.append(date_plus)
-
-
- self.redraw_canvas()
- if moving:
- return True
- else:
- self.in_motion = False
- return False
-
def draw_cursor(self, area, event):
if event.is_hint:
x, y, state = event.window.get_pointer()
else:
- x = event.x
- y = event.y
+ x = event.x + self.graph_x
+ y = event.y + self.graph_y
state = event.state
mouse_down = state & gtk.gdk.BUTTON1_MASK
+
+ highlight_start = self.highlight_start + self.graph_x
+ highlight_end = self.highlight_end + self.graph_x
- if self.highlight_start != None:
- start_drag = 10 > (self.highlight_start - x) > -1
+ if highlight_start != None:
+ start_drag = 10 > (highlight_start - x) > -1
- end_drag = 10 > (x - self.highlight_end) > -1
+ end_drag = 10 > (x - highlight_end) > -1
if start_drag and end_drag:
- start_drag = abs(x - self.highlight_start) < abs(x - self.highlight_end)
+ start_drag = abs(x - highlight_start) < abs(x - highlight_end)
- in_between = self.highlight_start <= x <= self.highlight_end
+ in_between = highlight_start <= x <= highlight_end
scale = True
if self.in_progress:
@@ -175,10 +152,10 @@ class DayLine(graphics.Area):
self.move_type = "end"
elif in_between:
self.move_type = "move"
- self.drag_start = x - self.highlight_start
+ self.drag_start = x - self.highlight_start + self.graph_x
elif scale:
self.move_type = "scale_drag"
- self.drag_start_time = self.range_start.value
+ self.drag_start_time = dt.datetime.fromtimestamp(self.range_start_int)
if mouse_down and self.drag_start:
@@ -186,21 +163,17 @@ class DayLine(graphics.Area):
if self.move_type and self.move_type != "scale_drag":
if self.move_type == "start":
if 0 <= x <= self.width:
- start = x
+ start = x - self.graph_x
end = self.highlight_end
elif self.move_type == "end":
if 0 <= x <= self.width:
start = self.highlight_start
- end = x
+ end = x - self.graph_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))
+ start = x - self.drag_start + self.graph_x
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))
@@ -208,12 +181,10 @@ class DayLine(graphics.Area):
self.__call_parent_time_changed()
else:
- self.range_start.target(self.drag_start_time +
- dt.timedelta(minutes = self.get_value_at_pos(self.drag_start) - self.get_value_at_pos(x)))
+ self.range_start = self.drag_start_time + dt.timedelta(minutes = self.get_value_at_pos(self.drag_start) - self.get_value_at_pos(x))
self.scroll_to_range_start()
-
if start_drag:
area.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.LEFT_SIDE))
elif end_drag:
@@ -225,17 +196,38 @@ class DayLine(graphics.Area):
def _minutes_from_start(self, date):
- delta = (date - self.range_start.value)
+ delta = (date - dt.datetime.fromtimestamp(self.range_start_int))
return delta.days * 24 * 60 + delta.seconds / 60
-
+
+ def scroll_to_range_start(self):
+ self.tweener.removeTweeningFrom(self)
+ self.animate(self, {"range_start_int": int(time.mktime(self.range_start.timetuple())),
+ "tweenType": graphics.Easing.Expo.easeOut,
+ "tweenTime": 0.4})
+
def on_expose(self):
+ # check if maybe we are approaching day boundaries and should ask for
+ # more data!
+ now = dt.datetime.fromtimestamp(self.range_start_int)
+ if self.on_more_data:
+ date_plus = (now + dt.timedelta(hours = 12 + 2*4 + 1)).date()
+ date_minus = (now - dt.timedelta(hours=1)).date()
+
+ if date_minus != now.date() and date_minus not in self.days:
+ self.facts += self.on_more_data(date_minus)
+ self.days.append(date_minus)
+ elif date_plus != now.date() and date_plus not in self.days:
+ self.facts += self.on_more_data(date_plus)
+ self.days.append(date_plus)
+
+
context = self.context
#TODO - use system colors and fonts
context.set_line_width(1)
#we will buffer 4 hours to both sides so partial labels also appear
- range_end = self.range_start.value + dt.timedelta(hours = 12 + 2 * 4)
+ range_end = now + dt.timedelta(hours = 12 + 2 * 4)
self.graph_x = -self.width / 3 #so x moves one third out of screen
pixels_in_minute = self.width / self.view_minutes
@@ -250,6 +242,9 @@ class DayLine(graphics.Area):
# graph area
self.fill_area(0, graph_y - 1, self.width, graph_height, (1,1,1))
+
+ context.save()
+ context.translate(self.graph_x, self.graph_y)
#bars
for fact in self.facts:
@@ -264,7 +259,7 @@ class DayLine(graphics.Area):
end_minutes = start_minutes
if end_minutes * pixels_in_minute > 0 and \
- start_minutes * pixels_in_minute < self.width:
+ start_minutes * pixels_in_minute + self.graph_x < self.width:
context.set_source_rgba(0.86, 0.86, 0.86, 0.5)
context.rectangle(round(start_minutes * pixels_in_minute),
@@ -287,7 +282,7 @@ class DayLine(graphics.Area):
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))
+ label_time = (now + dt.timedelta(minutes=i))
if label_time.minute == 0:
context.set_source_rgb(0.8, 0.8, 0.8)
@@ -326,7 +321,7 @@ class DayLine(graphics.Area):
self.highlight_end = round(self._minutes_from_start(self.highlight[1]) * pixels_in_minute)
#TODO - make a proper range check here
- if self.highlight_end > 0 and self.highlight_start < self.width:
+ if self.highlight_end + self.graph_x > 0 and self.highlight_start + self.graph_x < self.width:
rgb = colorsys.hls_to_rgb(.6, .7, .5)
self.fill_area(self.highlight_start,
@@ -343,75 +338,17 @@ class DayLine(graphics.Area):
self.context.line_to(self.highlight_end, graph_y + graph_height)
context.stroke()
+ context.restore()
+
#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:
- self.range_start.value = self.range_start.value - dt.timedelta(minutes=30)
- if self.highlight_end == self.width:
- self.range_start.value = self.range_start.value + dt.timedelta(minutes=30)
- self.scroll_to_range_start()
-
-
-
-# TODO - should remove this and replace with standard tweening instead!
-class Integrator(object):
- """an iterator, inspired by "visualizing data" book to simplify animation"""
- def __init__(self, start_value, damping = 0.5, attraction = 0.2):
- #if we got datetime, convert it to unix time, so we operate with numbers again
- self.current_value = start_value
- if isinstance(start_value, dt.datetime):
- self.current_value = int(time.mktime(start_value.timetuple()))
+ if self.move_type == "move" and (self.highlight_start + self.graph_x <= 0 or self.highlight_end + self.graph_x >= self.width):
+ if self.highlight_start + self.graph_x <= 0:
+ self.range_start = self.range_start - dt.timedelta(minutes=30)
+ if self.highlight_end + self.graph_x >= self.width:
+ self.range_start = self.range_start + dt.timedelta(minutes=30)
- self.value_type = type(start_value)
-
- self.target_value = start_value
- self.current_frame = 0
-
- self.targeting = False
- self.vel, self.accel, self.force = 0, 0, 0
- self.mass = 1
- self.damping = damping
- self.attraction = attraction
-
- def __repr__(self):
- current, target = self.current_value, self.target_value
- if self.value_type == dt.datetime:
- current = dt.datetime.fromtimestamp(current)
- target = dt.datetime.fromtimestamp(target)
- return "<Integrator %s, %s>" % (current, target)
-
- def target(self, value):
- """target next value"""
- self.targeting = True
- self.target_value = value
- if isinstance(value, dt.datetime):
- self.target_value = int(time.mktime(value.timetuple()))
-
- def update(self):
- """goes from current to target value
- if there is any action needed. returns velocity, which is synonym from
- delta. Use it to determine when animation is done (experiment to find
- value that fits you!"""
-
- if self.targeting:
- self.force += self.attraction * (self.target_value - self.current_value)
-
- self.accel = self.force / self.mass
- self.vel = (self.vel + self.accel) * self.damping
- self.current_value += self.vel
- self.force = 0
- return abs(self.vel)
-
- def finish(self):
- self.current_value = self.target_value
-
- @property
- def value(self):
- if self.value_type == dt.datetime:
- return dt.datetime.fromtimestamp(self.current_value)
- else:
- return self.current_value
+ self.scroll_to_range_start()
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]