[hamster-applet] some more progress - adjusting start date when looking on week/month showing major ticks
- From: Toms Baugis <tbaugis src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [hamster-applet] some more progress - adjusting start date when looking on week/month showing major ticks
- Date: Sun, 20 Dec 2009 16:39:08 +0000 (UTC)
commit add66f036aa2ff0c5d7433f14f085a84a14a8733
Author: Toms Bauģis <toms baugis gmail com>
Date: Sun Dec 20 16:39:00 2009 +0000
some more progress - adjusting start date when looking on week/month
showing major ticks
hamster/widgets/newtimeline.py | 251 +++++++++++++++++++++++++---------------
1 files changed, 158 insertions(+), 93 deletions(-)
---
diff --git a/hamster/widgets/newtimeline.py b/hamster/widgets/newtimeline.py
index dfcd222..ba3fdd1 100644
--- a/hamster/widgets/newtimeline.py
+++ b/hamster/widgets/newtimeline.py
@@ -24,6 +24,8 @@ from .hamster import graphics, stuff
from .hamster.configuration import GconfStore
import datetime as dt
+import calendar
+
from bisect import bisect, bisect_left
class NewTimeLine(graphics.Area):
@@ -31,9 +33,13 @@ class NewTimeLine(graphics.Area):
def __init__(self):
graphics.Area.__init__(self)
- self.start_date, self.end_date = None, None
+ self.start_time, self.end_time = None, None
self.facts = []
self.title = ""
+ self.day_start = GconfStore().get_day_start()
+ self.minor_tick = None
+
+ self.tick_totals = {}
def draw(self, facts, start_date, end_date):
@@ -41,24 +47,104 @@ class NewTimeLine(graphics.Area):
self.set_title(start_date, end_date) # we will forget about all our magic manipulations for the title
+ # we will operate in minutes since and until the day start
+ start_time = dt.datetime.combine(start_date, self.day_start.replace(minute=0))
+ end_time = dt.datetime.combine(end_date, self.day_start.replace(minute=0)) + dt.timedelta(days = 1)
+
+ fact_start_time, fact_end_time = start_time, end_time
+ if facts:
+ fact_start_time = facts[0]["start_time"]
+ fact_end_time = facts[-1]["start_time"] + facts[-1]["delta"]
+
+ self.start_time = min([start_time, fact_start_time])
+ self.end_time = max([end_time, fact_end_time])
+
+ if self.start_time > self.end_time: # make sure end is after start
+ self.start_time, self.end_time = self.end_time, self.start_time
- day_start = GconfStore().get_day_start()
- start_date = dt.datetime.combine(start_date, day_start.replace(minute=0))
- end_date = dt.datetime.combine(end_date, day_start.replace(minute=0)) + dt.timedelta(days = 1)
+ days = (self.end_time - self.start_time).days
+
+
+ # determine fraction and do addittional start time move
+ if days > 300:
+ self.minor_tick = dt.timedelta(days = 30) #this is approximate and will be replaced by exact days in month
+ # make sure we start on first day of month
+ self.start_time = self.start_time - dt.timedelta(self.start_time.day - 1)
+
+ elif days > 100:
+ self.minor_tick = dt.timedelta(days = 7)
+ # make sure we start week on first day
+ #set to monday
+ self.start_time = self.start_time - dt.timedelta(self.start_time.weekday() + 1)
+ # look if we need to start on sunday or monday
+ self.start_time = self.start_time + dt.timedelta(stuff.locale_first_weekday())
+
+ elif days > 2:
+ self.minor_tick = dt.timedelta(days = 1)
+ else:
+ self.minor_tick = dt.timedelta(seconds = 60 * 60)
- self.start_date = min([start_date, facts[0]["start_time"]])
- self.end_date = max([end_date, facts[-1]["start_time"] + facts[-1]["delta"]])
+ print self.start_time, self.end_time
+ self.count_hours()
- if self.start_date > self.end_date:
- self.start_date, self.end_date = self.end_date, self.start_date
- if self.end_date.time == dt.time(0,0):
- self.end_date += dt.timedelta(days=1)
self.redraw_canvas()
+ def count_hours(self):
+ #go through facts and make array of time used by our fraction
+ fractions = []
+
+ current_time = self.start_time
+
+ minor_tick = self.minor_tick
+ while current_time <= self.end_time:
+
+ # if minor tick is month, the starting date will have been
+ # already adjusted to the first
+ # now we have to make sure to move month by month
+ if self.minor_tick >= dt.timedelta(days=28):
+ minor_tick = dt.timedelta(calendar.monthrange(current_time.year, current_time.month)[1]) # days in month
+
+ fractions.append(current_time)
+ current_time += minor_tick
+
+ hours = [0] * len(fractions)
+
+ tick_minutes = float(stuff.duration_minutes(self.minor_tick))
+
+ for fact in self.facts:
+ end_time = fact["start_time"] + fact["delta"] # the thing about ongoing task - it has no end time
+
+ # find in which fraction the fact starts and
+ # add duration up to the border of tick to that fraction
+ # then move cursor to the start of next fraction
+ first_index = bisect_left(fractions, fact["start_time"]) - 1
+ step_time = fractions[first_index]
+ first_end = min(end_time, step_time + self.minor_tick)
+ first_tick = stuff.duration_minutes(first_end - fact["start_time"]) / tick_minutes
+
+ hours[first_index] += first_tick
+ step_time = step_time + self.minor_tick
+
+ # now go through ticks until we reach end of the time
+ while step_time < end_time:
+ index = bisect_left(fractions, step_time)
+ interval = min([1, stuff.duration_minutes(end_time - step_time) / tick_minutes])
+ hours[index] += interval
+
+ step_time += self.minor_tick
+
+
+ # now normalize
+ max_hour = max(hours)
+ hours = [hour / (max_hour or 1) for hour in hours]
+
+ self.tick_totals = zip(fractions, hours)
+
+
def set_title(self, start_date, end_date):
dates_dict = stuff.dateDict(start_date, "start_")
dates_dict.update(stuff.dateDict(end_date, "end_"))
@@ -92,79 +178,87 @@ class NewTimeLine(graphics.Area):
def on_expose(self):
self.fill_area(0, 0, self.width, self.height, "#fafafa")
- bar_width, time_step = self.figure_time_fraction()
-
- self.context.translate(0.5, 0.5) #move half a pixel to get sharp lines
-
-
- #go through facts and make array of time used by our fraction
- distribution = [] # TODO - think of a better name for a variable
- current_time = self.start_date
- while current_time <= self.end_date:
- distribution.append(current_time)
- current_time += time_step
+ total_minutes = stuff.duration_minutes(self.end_time - self.start_time)
+ tick_minutes = stuff.duration_minutes(self.minor_tick)
- hours = [0] * len(distribution)
+ bar_width = self.width / (total_minutes / float(tick_minutes))
- step_minutes = float(stuff.duration_minutes(time_step))
+ self.context.translate(0.5, 0.5) #move half a pixel to get sharp lines (hypothetically)
- for fact in self.facts:
-
- first_index = bisect_left(distribution, fact["start_time"]) - 1
-
- step_time = distribution[first_index]
- first_end = min(fact["start_time"] + fact["delta"], step_time + time_step)
-
- interval = stuff.duration_minutes(first_end - fact["start_time"]) / step_minutes
+ # the bars
+ x = 1
+ for current_time, total in self.tick_totals:
+ bar_size = round(self.height * total * 0.9)
- hours[first_index] += interval
-
- step_time = step_time + time_step
- while step_time < fact["start_time"] + fact["delta"]:
- index = bisect_left(distribution, step_time)
-
- interval = min([1, stuff.duration_minutes(fact["start_time"] + fact["delta"] - step_time) / step_minutes])
- hours[index] += interval
-
- step_time += time_step
+ self.fill_area(round(x), self.height - bar_size, round(bar_width * 0.9), bar_size, "#eeeeee")
+ x += bar_width
- max_hour = max(hours)
- hours = [hour / max_hour for hour in hours]
- per_interval = dict(zip(distribution, hours))
+ # major ticks
+ if (self.end_time - self.start_time) < dt.timedelta(days=2): # about the same day
+ major_step = dt.timedelta(seconds = 60 * 60)
+ else:
+ major_step = dt.timedelta(days=1)
x = 1
- current_time = self.start_date
- while current_time <= self.end_date:
- bar_size = round(self.height * per_interval[current_time] * 0.9)
-
- self.fill_area(round(x), self.height - bar_size, round(bar_width * 0.9), bar_size, "#eeeeee")
- current_time += time_step
- x += bar_width
+ major_tick_step = self.width / (total_minutes / float(stuff.duration_minutes(major_step)))
+ current_time = self.start_time
+ while current_time <= self.end_time:
+ if (self.end_time - self.start_time) < dt.timedelta(days=2): # about the same day
+ if current_time.time() == dt.time(0,0):
+ self.fill_area(round(x), 0, 1, self.height, "#666666")
+
+ elif self.minor_tick == dt.timedelta(days=1): # when going day by day, tick on week, month and year change
+ if current_time.weekday() == 0:
+ self.fill_area(round(x), 0, 1, self.height, "#999999")
+
+ elif current_time.day == 1:
+ self.fill_area(round(x), 0, 1, self.height, "#666666")
+
+ elif current_time.timetuple().tm_yday == 1:
+ self.fill_area(round(x), 0, 1, self.height, "#00FF00")
+
+ elif self.minor_tick == dt.timedelta(days=7): # when going week by week, tick on month and year change
+ if current_time.day == 1:
+ self.fill_area(round(x), 0, 1, self.height, "#666666")
- print time_step
- step_format = "%H:%M"
- if time_step < dt.timedelta(seconds = 60 * 60):
- step_format = "%H:%M"
- elif time_step < dt.timedelta(days = 1):
+ elif current_time.timetuple().tm_yday == 1:
+ self.fill_area(round(x), 0, 1, self.height, "#00FF00")
+
+ elif self.minor_tick >= dt.timedelta(days=28): # when going by month, tick on year change
+ if current_time.timetuple().tm_yday == 1:
+ self.fill_area(round(x), 0, 1, self.height, "#00FF00")
+
+
+
+ current_time += major_step
+ x += major_tick_step
+
+
+
+ #minor ticks
+ if self.minor_tick >= dt.timedelta(days = 28): # month
+ step_format = "%b"
+
+ elif self.minor_tick == dt.timedelta(days = 7): # week
+ step_format = "%a\n%d"
+ elif self.minor_tick == dt.timedelta(days = 1): # day
+ step_format = "%a\n%d"
+ else:
step_format = "%H:%M"
- elif time_step <= dt.timedelta(days = 7):
- step_format = "%a %d"
+
x = 1
- i = 1
- current_time = self.start_date
- while current_time <= self.end_date:
+ current_time = self.start_time
+ for current_time, total in self.tick_totals:
self.set_color("#aaaaaa")
- self.context.move_to(x, 30)
self.layout.set_text(current_time.strftime(step_format))
+ self.context.move_to(x, self.height - self.layout.get_pixel_size()[1])
self.context.show_layout(self.layout)
- current_time += time_step
x += bar_width
- i +=1
self.set_color("#aaaaaa")
@@ -178,32 +272,3 @@ class NewTimeLine(graphics.Area):
self.context.show_layout(self.layout)
-
- def figure_time_fraction(self):
- bar_width = 70 # preferred bar width
- bar_count = self.width / float(bar_width)
-
- minutes = stuff.duration_minutes(self.end_date - self.start_date)
- minutes_in_unit = int(minutes / bar_count)
-
- # now let's find closest human understandable fraction of time that we will be actually using
- fractions = [60, # minutes
- 60 * 24, # days
- 60 * 24 * 7, 60 * 24 * 14, # weeks (1,2)
- 60 * 24 * 30, 60 * 24 * 30 * 3, 60 * 24 * 30 * 4, # months (1, 3, 4)
- 60 * 24 * 356] # years
-
- human_step = bisect(fractions, minutes_in_unit)
- # go to the closest side
- if human_step > 0 and abs(fractions[human_step] - minutes_in_unit) > abs(fractions[human_step - 1] - minutes_in_unit):
- human_step -=1
-
- step_minutes = fractions[human_step]
-
- bar_count = minutes / step_minutes
- bar_width = self.width / float(bar_count)
-
- time_step = dt.timedelta(days = step_minutes / (60 * 24),
- seconds = (step_minutes % (60 * 24)) * 60)
-
- return bar_width, time_step
\ No newline at end of file
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]