def _draw(self, context, opacity, matrix): g = graphics.Graphics(context) g.save_context() g.translate(self.x, self.y) # arbitrary 3/4 total width for label, 1/4 for histogram hist_width = self.alloc_w // 4; margin = 10 # pixels label_width = self.alloc_w - hist_width - margin self.layout.set_width(label_width * pango.SCALE) label_h = self.label_height bar_start_x = label_width + margin for i, (label, value) in enumerate(self.values): g.set_color("#333") duration_str = stuff.format_duration(value, human=False) markup_label = stuff.escape_pango(str(label)) markup_duration = stuff.escape_pango(duration_str) self.layout.set_markup("{}, <i>{}</i>".format(markup_label, markup_duration)) y = int(i * label_h * 1.5) g.move_to(0, y) pangocairo.show_layout(context, self.layout) if self._max > dt.timedelta(0): w = ceil(hist_width * value.total_seconds() / self._max.total_seconds()) else: w = 1 g.rectangle(bar_start_x, y, int(w), int(label_h)) g.fill("#999") g.restore_context()
def on_enter_frame(self, scene, context): if not self.height: return colors = { "normal": self.style.get_color(gtk.StateFlags.NORMAL), "normal_bg": self.style.get_background_color(gtk.StateFlags.NORMAL), "selected": self.style.get_color(gtk.StateFlags.SELECTED), "selected_bg": self.style.get_background_color(gtk.StateFlags.SELECTED), } g = graphics.Graphics(context) g.set_line_style(1) g.translate(0.5, 0.5) for row, y in zip(self.rows, self.row_positions): g.save_context() g.translate(0, y) color, bg = colors["normal"], colors["normal_bg"] if row == self.current_row: color, bg = colors["selected"], colors["selected_bg"] g.fill_area(0, 0, self.width, self.row_height, bg) label = row.label if row.description: description_color = graphics.Colors.contrast(color, 50) description_color = graphics.Colors.hex(description_color) label += '<span color="%s"> - %s</span>' % (description_color, row.description) self.label.show(g, label, color=color) g.restore_context()
def _draw(self, context, opacity, matrix): g = graphics.Graphics(context) g.save_context() g.translate(self.x, self.y) hours = [(value.days * 24.0 + value.seconds / 3600.0) for _, value in self.values] total = self._total.days * 24.0 + self._total.seconds / 3600.0 for i, (label, value) in enumerate(self.values): percent = 100.0 * hours[i] / total label += " (%3.2fh; %3.1f%%)" % (hours[i], percent) g.set_color("#333") self.layout.set_markup(stuff.escape_pango(label)) label_w, label_h = self.layout.get_pixel_size() y = int(i * label_h * 1.5) g.move_to(180 - label_w, y) pangocairo.show_layout(context, self.layout) w = (self.alloc_w - 200) * value.total_seconds() / self._max.total_seconds() w = max(1, int(round(w))) g.rectangle(190, y, int(w), int(label_h)) g.fill("#999") g.restore_context()
def _draw(self, context, opacity, matrix): g = graphics.Graphics(context) g.save_context() g.translate(self.x, self.y) for i, (label, value) in enumerate(self.values): g.set_color("#333") duration_str = stuff.format_duration(value, human=False) markup = stuff.escape_pango('{}, {}'.format(label, duration_str)) self.layout.set_markup(markup) label_w, label_h = self.layout.get_pixel_size() bar_start_x = 150 # pixels margin = 10 # pixels y = int(i * label_h * 1.5) g.move_to(bar_start_x - margin - label_w, y) pangocairo.show_layout(context, self.layout) if self._max > dt.timedelta(0): w = ceil((self.alloc_w - bar_start_x) * value.total_seconds() / self._max.total_seconds()) else: w = 1 g.rectangle(bar_start_x, y, int(w), int(label_h)) g.fill("#999") g.restore_context()
def on_enter_frame(self, scene, context): has_focus = self.get_toplevel().has_toplevel_focus() if has_focus: colors = { "normal": self.style.get_color(gtk.StateFlags.NORMAL), "normal_bg": self.style.get_background_color(gtk.StateFlags.NORMAL), "selected": self.style.get_color(gtk.StateFlags.SELECTED), "selected_bg": self.style.get_background_color(gtk.StateFlags.SELECTED), } else: colors = { "normal": self.style.get_color(gtk.StateFlags.BACKDROP), "normal_bg": self.style.get_background_color(gtk.StateFlags.BACKDROP), "selected": self.style.get_color(gtk.StateFlags.BACKDROP), "selected_bg": self.style.get_background_color(gtk.StateFlags.BACKDROP), } if not self.height: return g = graphics.Graphics(context) g.set_line_style(1) g.translate(0.5, 0.5) g.fill_area(0, 0, 105, self.height, "#dfdfdf") y = int(self.y) for rec in self.visible_range: g.save_context() g.translate(0, rec['y']) if not rec['facts']: "do a collapsy thing" g.rectangle(0, 0, self.width, 10) g.clip() g.rectangle(0, 0, self.width, 10) g.fill("#eee") g.move_to(0, 0) g.line_to(self.width, 0) g.stroke("#ccc") g.restore_context() continue g.set_color(colors["normal"]) self.date_label.show(g, rec['day'].strftime("%A\n%b %d")) g.translate(105, 0) for fact in rec['facts']: self.fact_row.show(g, colors, fact, fact==self.current_fact) g.translate(0, self.fact_row.height(fact)) g.restore_context()
def on_enter_frame(self, scene, context): has_focus = self.get_toplevel().has_toplevel_focus() if has_focus: colors = { "normal": self.style.get_color(gtk.StateFlags.NORMAL), "normal_bg": self.style.get_background_color(gtk.StateFlags.NORMAL), "selected": self.style.get_color(gtk.StateFlags.SELECTED), "selected_bg": self.style.get_background_color(gtk.StateFlags.SELECTED), } else: colors = { "normal": self.style.get_color(gtk.StateFlags.BACKDROP), "normal_bg": self.style.get_background_color(gtk.StateFlags.BACKDROP), "selected": self.style.get_color(gtk.StateFlags.BACKDROP), "selected_bg": self.style.get_background_color(gtk.StateFlags.BACKDROP), } if not self.height: return g = graphics.Graphics(context) g.set_line_style(1) g.translate(0.5, 0.5) date_bg_color = self.colors.mix(colors["normal_bg"], colors["normal"], 0.15) g.fill_area(0, 0, 105, self.height, date_bg_color) y = int(self.y) for rec in self.visible_range: g.save_context() g.translate(0, rec['y']) g.set_color(colors["normal"]) self.date_label.show(g, rec['day'].strftime("%A\n%b %d")) g.translate(105, 0) for fact in rec['facts']: is_selected = (self.current_fact is not None and fact.id == self.current_fact.id) self.fact_row.set_fact(fact) self.fact_row.show(g, colors, is_selected=is_selected) g.translate(0, self.fact_row.height) g.restore_context()
def _draw(self, context, opacity, matrix): g = graphics.Graphics(context) g.save_context() g.translate(self.x, self.y) for i, (label, value) in enumerate(self.values): g.set_color("#333") self.layout.set_markup(stuff.escape_pango(label)) label_w, label_h = self.layout.get_pixel_size() y = int(i * label_h * 1.5) g.move_to(100 - label_w, y) pangocairo.show_layout(context, self.layout) w = (self.alloc_w - 110) * value.total_seconds() / self._max.total_seconds() w = max(1, int(round(w))) g.rectangle(110, y, int(w), int(label_h)) g.fill("#999") g.restore_context()
def on_enter_frame(self, scene, context): g = graphics.Graphics(context) self.plot_area.height = self.height - 30 vertical = min(self.plot_area.height / 5, 7) minute_pixel = (self.scope_hours * 60.0 - 15) / self.width g.set_line_style(width=1) g.translate(0.5, 0.5) colors = { "normal": self._style.get_color(gtk.StateFlags.NORMAL), "normal_bg": self._style.get_background_color(gtk.StateFlags.NORMAL), "selected": self._style.get_color(gtk.StateFlags.SELECTED), "selected_bg": self._style.get_background_color(gtk.StateFlags.SELECTED), } bottom = self.plot_area.y + self.plot_area.height for bar in self.fact_bars: bar.y = vertical * bar.category + 5 bar.height = vertical 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) 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 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.chosen_selection.parent.height # use the oportunity to set proper colors too self.chosen_selection.fill = colors['selected_bg'] self.chosen_selection.duration_label.color = colors['selected'] #time scale g.set_color("#000") background = colors["normal_bg"] text = colors["normal"] tick_color = g.colors.contrast(background, 80) layout = g.create_layout(size = 10) for i in range(self.scope_hours * 60): time = (self.view_time + dt.timedelta(minutes=i)) g.set_color(tick_color) if time.minute == 0: g.move_to(round(i / minute_pixel), bottom - 15) g.line_to(round(i / minute_pixel), bottom) g.stroke() elif time.minute % 15 == 0: g.move_to(round(i / minute_pixel), bottom - 5) g.line_to(round(i / minute_pixel), bottom) g.stroke() if time.minute == 0 and time.hour % 4 == 0: if time.hour == 0: g.move_to(round(i / minute_pixel), self.plot_area.y) g.line_to(round(i / minute_pixel), bottom) label_minutes = time.strftime("%b %d") else: label_minutes = time.strftime("%H<small><sup>%M</sup></small>") g.set_color(text) layout.set_markup(label_minutes) g.move_to(round(i / minute_pixel) + 2, 0) pangocairo.show_layout(context, layout) #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) g.rectangle(minutes, 0, self.width, self.height) g.fill(colors['normal_bg'], 0.7) g.move_to(minutes, self.plot_area.y) g.line_to(minutes, bottom) g.stroke("#f00", 0.4)
def on_enter_frame(self, scene, context): g = graphics.Graphics(context) rowcount, keys = len(self.keys), self.keys start_hour = 0 if self.start_time: start_hour = self.start_time end_hour = 24 * 60 if self.end_time: end_hour = self.end_time # push graph to the right, so it doesn't overlap legend_width = self.legend_width or self.longest_label(keys) self.graph_x = legend_width self.graph_x += 8 #add another 8 pixes of padding self.graph_width = self.width - self.graph_x # TODO - should handle the layout business in graphics self.layout = context.create_layout() default_font = "Sans Serif" #pango.FontDescription(self.get_style().font_desc.to_string()) default_font.set_size(8 * pango.SCALE) self.layout.set_font_description(default_font) #on the botttom leave some space for label self.layout.set_text("1234567890:") label_w, label_h = self.layout.get_pixel_size() self.graph_y, self.graph_height = 0, self.height - label_h - 4 if not self.data: #if we have nothing, let's go home return positions = {} y = 0 bar_width = min(self.graph_height / float(len(self.keys)), self.max_bar_width) for i, key in enumerate(self.keys): positions[key] = (y + self.graph_y, round(bar_width - 1)) y = y + round(bar_width) bar_width = min(self.max_bar_width, (self.graph_height - y) / float(max(1, len(self.keys) - i - 1))) max_bar_size = self.graph_width - 15 # now for the text - we want reduced contrast for relaxed visuals fg_color = "#666" #self.get_style().fg[gtk.StateType.NORMAL].to_string() label_color = self.colors.contrast(fg_color, 80) self.layout.set_alignment(pango.Alignment.RIGHT) self.layout.set_ellipsize(pango.ELLIPSIZE_END) # bars and labels self.layout.set_width(legend_width * pango.SCALE) factor = max_bar_size / float(end_hour - start_hour) # determine bar color bg_color = "#eee" #self.get_style().bg[gtk.StateType.NORMAL].to_string() base_color = self.colors.contrast(bg_color, 30) for i, label in enumerate(keys): g.set_color(label_color) self.layout.set_text(label) label_w, label_h = self.layout.get_pixel_size() context.move_to( 0, positions[label][0] + (positions[label][1] - label_h) / 2) context.show_layout(self.layout) if isinstance(self.data[i], list) == False: self.data[i] = [self.data[i]] for row in self.data[i]: bar_x = round((row[0] - start_hour) * factor) bar_size = round((row[1] - start_hour) * factor - bar_x) g.fill_area(round(self.graph_x + bar_x), positions[label][0], bar_size, positions[label][1], base_color) #white grid and scale values self.layout.set_width(-1) context.set_line_width(1) pace = ((end_hour - start_hour) / 3) / 60 * 60 last_position = positions[keys[-1]] grid_color = "#aaa" # self.get_style().bg[gtk.StateType.NORMAL].to_string() for i in range(start_hour + 60, end_hour, pace): x = round((i - start_hour) * factor) minutes = i % (24 * 60) self.layout.set_markup( dt.time(minutes / 60, minutes % 60).strftime("%-I<small><sup>%M</sup></small>")) label_w, label_h = self.layout.get_pixel_size() context.move_to(self.graph_x + x - label_w / 2, last_position[0] + last_position[1] + 4) g.set_color(label_color) context.show_layout(self.layout) g.set_color(grid_color) g.move_to(round(self.graph_x + x) + 0.5, self.graph_y) g.line_to( round(self.graph_x + x) + 0.5, last_position[0] + last_position[1]) context.stroke()
def on_enter_frame(self, scene, context): has_focus = self.get_toplevel().has_toplevel_focus() if has_focus: colors = { "normal": self.style.get_color(gtk.StateFlags.NORMAL), "normal_bg": self.style.get_background_color(gtk.StateFlags.NORMAL), "selected": self.style.get_color(gtk.StateFlags.SELECTED), "selected_bg": self.style.get_background_color(gtk.StateFlags.SELECTED), } else: colors = { "normal": self.style.get_color(gtk.StateFlags.BACKDROP), "normal_bg": self.style.get_background_color(gtk.StateFlags.BACKDROP), "selected": self.style.get_color(gtk.StateFlags.BACKDROP), "selected_bg": self.style.get_background_color(gtk.StateFlags.BACKDROP), } if not self.height: return g = graphics.Graphics(context) g.set_line_style(1) g.translate(0.5, 0.5) date_bg_color = self.colors.mix(colors["normal_bg"], colors["normal"], 0.15) g.fill_area(0, 0, 105, self.height, date_bg_color) y = int(self.y) for rec in self.visible_range: g.save_context() g.translate(0, rec['y']) if not rec['facts']: "do a collapsy thing" g.rectangle(0, 0, self.width, 10) g.clip() g.rectangle(0, 0, self.width, 10) none_bg_color = self.colors.mix(colors["normal_bg"], colors["normal"], 0.75) g.fill(none_bg_color) # line, useful to separate consecutive days with no activity g.move_to(0, 0) g.line_to(self.width, 0) none_stroke_color = self.colors.mix(colors["normal_bg"], colors["normal"], 0.25) g.stroke(none_stroke_color) g.restore_context() continue g.set_color(colors["normal"]) self.date_label.show(g, rec['day'].strftime("%A\n%b %d")) g.translate(105, 0) for fact in rec['facts']: is_selected = (self.current_fact is not None and fact.id == self.current_fact.id) self.fact_row.show(g, colors, fact, is_selected) g.translate(0, self.fact_row.height(fact)) g.restore_context()