Пример #1
0
    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()
Пример #2
0
    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()
Пример #3
0
    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()
Пример #4
0
    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()
Пример #5
0
    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()
Пример #6
0
    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()
Пример #7
0
    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()
Пример #8
0
    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)
Пример #9
0
    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()
Пример #10
0
    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()