!C99Shell v. 2.0 [PHP 7 Update] [25.02.2019]!

Software: Apache/2.2.16 (Debian). PHP/5.3.3-7+squeeze19 

uname -a: Linux mail.tri-specialutilitydistrict.com 2.6.32-5-amd64 #1 SMP Tue May 13 16:34:35 UTC
2014 x86_64
 

uid=33(www-data) gid=33(www-data) groups=33(www-data) 

Safe-mode: OFF (not secure)

/usr/share/pyshared/hamster/   drwxr-xr-x
Free 130.05 GB of 142.11 GB (91.51%)
Home    Back    Forward    UPDIR    Refresh    Search    Buffer    Encoder    Tools    Proc.    FTP brute    Sec.    SQL    PHP-code    Update    Feedback    Self remove    Logout    


Viewing file:     charting.py (31.12 KB)      -rw-r--r--
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
# - coding: utf-8 -

# Copyright (C) 2008 Toms Bauģis <toms.baugis at gmail.com>

# This file is part of Project Hamster.

# Project Hamster is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

# Project Hamster is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with Project Hamster.  If not, see <http://www.gnu.org/licenses/>.


"""Small charting library that enables you to draw bar and
horizontal bar charts. This library is not intended for scientific graphs.
More like some visual clues to the user.

The whole thing is a bit of minefield, but it can bring pretty decent results
if you don't ask for much.

For graph options see the Chart class and Chart.plot function

Author: toms.baugis@gmail.com
Feel free to contribute - more info at Project Hamster web page:
http://projecthamster.wordpress.com/

"""

import gtk, gobject
import cairo, pango
import copy
import math
from sys import maxint
import datetime as dt
import time
import colorsys
import logging

import graphics


def size_list(set, target_set):
    """turns set lenghts into target set - trim it, stretches it, but
       keeps values for cases when lengths match
    """
    set = set[:min(len(set), len(target_set))] #shrink to target
    set += target_set[len(set):] #grow to target

    #nest
    for i in range(len(set)):
        if isinstance(set[i], list):
            set[i] = size_list(set[i], target_set[i])
    return set

def get_limits(set, stack_subfactors = True):
    # stack_subfactors indicates whether we should sum up nested lists
    max_value, min_value = -maxint, maxint
    for col in set:
        if type(col) in [int, float]:
            max_value = max(col, max_value)
            min_value = min(col, min_value)
        elif stack_subfactors:
            max_value = max(sum(col), max_value)
            min_value = min(sum(col), min_value)
        else:
            for row in col:
                max_value = max(row, max_value)
                min_value = max(row, min_value)

    return min_value, max_value


class Bar(object):
    def __init__(self, value, size = 0):
        self.value = value
        self.size = size

    def __repr__(self):
        return str((self.value, self.size))


class Chart(graphics.Area):
    """Chart constructor. Optional arguments:
        self.max_bar_width     = pixels. Maximal width of bar. If not specified,
                                 bars will stretch to fill whole area
        self.legend_width      = pixels. Legend width will keep you graph
                                 from floating around.
        self.animate           = Should transitions be animated.
                                 Defaults to TRUE
        self.framerate         = Frame rate for animation. Defaults to 60

        self.background        = Tripplet-tuple of background color in RGB
        self.chart_background  = Tripplet-tuple of chart background color in RGB
        self.bar_base_color    = Tripplet-tuple of bar color in RGB

        self.show_scale        = Should we show scale values. See grid_stride!
        self.grid_stride       = Step of grid. If expressed in normalized range
                                 (0..1), will be treated as percentage.
                                 Otherwise will be striding through maximal value.
                                 Defaults to 0. Which is "don't draw"

        self.values_on_bars    = Should values for each bar displayed on top of
                                 it.
        self.value_format      = Format string for values. Defaults to "%s"

        self.show_stack_labels = If the labels of stack bar chart should be
                                 displayed. Defaults to False
        self.labels_at_end     = If stack bars are displayed, this allows to
                                 show them at right end of graph.
    """
    __gsignals__ = {
        "bar-clicked": (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT, )),
    }
    def __init__(self, **args):
        graphics.Area.__init__(self)

        # options
        self.max_bar_width     = args.get("max_bar_width", 500)
        self.legend_width      = args.get("legend_width", 0)
        self.animation           = args.get("animate", True)

        self.background        = args.get("background", None)
        self.chart_background  = args.get("chart_background", None)
        self.bar_base_color    = args.get("bar_base_color", None)

        self.grid_stride       = args.get("grid_stride", None)
        self.values_on_bars    = args.get("values_on_bars", False)
        self.value_format      = args.get("value_format", "%s")
        self.show_scale        = args.get("show_scale", False)

        self.show_stack_labels = args.get("show_stack_labels", False)
        self.labels_at_end     = args.get("labels_at_end", False)
        self.framerate         = args.get("framerate", 60)

        self.interactive       = args.get("interactive", False) # if the bars are clickable

        # other stuff
        self.bars = []
        self.keys = []
        self.data = None
        self.stack_keys = []

        self.key_colors = {} # key:color dictionary. if key's missing will grab basecolor
        self.stack_key_colors = {} # key:color dictionary. if key's missing will grab basecolor


        # use these to mark area where the "real" drawing is going on
        self.graph_x, self.graph_y = 0, 0
        self.graph_width, self.graph_height = None, None

        self.mouse_bar = None
        if self.interactive:
            self.connect("mouse-over", self.on_mouse_over)
            self.connect("button-release", self.on_clicked)

        self.bars_selected = []


    def on_mouse_over(self, area, region):
        if region:
            self.mouse_bar = int(region[0])
        else:
            self.mouse_bar = None

        self.redraw_canvas()

    def on_clicked(self, area, bar):
        self.emit("bar-clicked", self.mouse_bar)

    def select_bar(self, index):
        pass

    def get_bar_color(self, index):
        # returns color darkened by it's index
        # the approach reduces contrast by each step
        base_color = self.bar_base_color or (220, 220, 220)

        base_hls = colorsys.rgb_to_hls(*base_color)

        step = (base_hls[1] - 30) / 10 #will go from base down to 20 and max 22 steps

        return colorsys.hls_to_rgb(base_hls[0],
                                   base_hls[1] - step * index,
                                   base_hls[2])


    def draw_bar(self, x, y, w, h, color = None):
        """ draws a simple bar"""
        base_color = color or self.bar_base_color or (220, 220, 220)
        self.fill_area(x, y, w, h, base_color)


    def plot(self, keys, data, stack_keys = None):
        """Draw chart with given data"""
        self.keys, self.data, self.stack_keys = keys, data, stack_keys

        self.show()

        if not data: #if there is no data, just draw blank
            self.redraw_canvas()
            return


        min, self.max_value = get_limits(data)

        self._update_targets()

        if not self.animation:
            self.tweener.finish()

        self.redraw_canvas()


    def on_expose(self):
        # fill whole area
        if self.background:
            self.fill_area(0, 0, self.width, self.height, self.background)


    def _update_targets(self):
        # calculates new factors and then updates existing set
        max_value = float(self.max_value) or 1 # avoid division by zero

        self.bars = size_list(self.bars, self.data)

        #need function to go recursive
        def retarget(bars, new_values):
            for i in range(len(new_values)):
                if isinstance(new_values[i], list):
                    bars[i] = retarget(bars[i], new_values[i])
                else:
                    if isinstance(bars[i], Bar) == False:
                        bars[i] = Bar(new_values[i], 0)
                    else:
                        bars[i].value = new_values[i]
                        self.tweener.killTweensOf(bars[i])

                    self.tweener.addTween(bars[i], size = bars[i].value / float(max_value))
            return bars

        retarget(self.bars, self.data)


    def longest_label(self, labels):
        """returns width of the longest label"""
        max_extent = 0
        for label in labels:
            self.layout.set_text(label)
            label_w, label_h = self.layout.get_pixel_size()
            max_extent = max(label_w + 5, max_extent)

        return max_extent

    def draw(self):
        logging.error("OMG OMG, not implemented!!!")


class BarChart(Chart):
    def on_expose(self):
        Chart.on_expose(self)

        if not self.data:
            return

        context = self.context
        context.set_line_width(1)


        # determine graph dimensions
        if self.show_stack_labels:
            legend_width = self.legend_width or self.longest_label(self.keys)
        elif self.show_scale:
            if self.grid_stride < 1:
                grid_stride = int(self.max_value * self.grid_stride)
            else:
                grid_stride = int(self.grid_stride)

            scale_labels = [self.value_format % i
                  for i in range(grid_stride, int(self.max_value), grid_stride)]
            self.legend_width = legend_width = self.legend_width or self.longest_label(scale_labels)
        else:
            legend_width = self.legend_width

        if self.stack_keys and self.labels_at_end:
            self.graph_x = 0
            self.graph_width = self.width - legend_width
        else:
            self.graph_x = legend_width + 8 # give some space to scale labels
            self.graph_width = self.width - self.graph_x - 10

        self.graph_y = 0
        self.graph_height = self.height - 15

        if self.chart_background:
            self.fill_area(self.graph_x, self.graph_y,
                           self.graph_width, self.graph_height,
                           self.chart_background)

        self.context.stroke()

        # bars and keys
        max_bar_size = self.graph_height
        #make sure bars don't hit the ceiling
        if self.animate or self.before_drag_animate:
            max_bar_size = self.graph_height - 10


        prev_label_end = None
        self.layout.set_width(-1)

        exes = {}
        x = 0
        bar_width = min(self.graph_width / float(len(self.keys)), self.max_bar_width)
        for i, key in enumerate(self.keys):
            exes[key] = (x + self.graph_x, round(bar_width - 1))

            x = x + round(bar_width)
            bar_width = min(self.max_bar_width,
                            (self.graph_width - x) / float(max(1, len(self.keys) - i - 1)))


        # now for the text - we want reduced contrast for relaxed visuals
        fg_color = self.get_style().fg[gtk.STATE_NORMAL].to_string()
        if self.colors.is_light(fg_color):
            label_color = self.colors.darker(fg_color,  80)
        else:
            label_color = self.colors.darker(fg_color,  -80)


        for key, bar, data in zip(self.keys, self.bars, self.data):
            self.set_color(label_color);
            self.layout.set_text(key)
            label_w, label_h = self.layout.get_pixel_size()

            intended_x = exes[key][0] + (exes[key][1] - label_w) / 2

            if not prev_label_end or intended_x > prev_label_end:
                self.context.move_to(intended_x, self.graph_height + 4)
                context.show_layout(self.layout)

                prev_label_end = intended_x + label_w + 3


            bar_start = 0

            # determine bar color
            base_color = self.bar_base_color
            if not base_color: #yay, we can be theme friendly!
                bg_color = self.get_style().bg[gtk.STATE_NORMAL].to_string()
                if self.colors.is_light(bg_color):
                    base_color = self.colors.darker(bg_color,  30)
                else:
                    base_color = self.colors.darker(bg_color,  -30)
                    tick_color = self.colors.darker(bg_color,  -50)

            if self.stack_keys:
                remaining_fractions, remaining_pixels = 1, max_bar_size

                for j, stack_bar in enumerate(bar):
                    if stack_bar.size > 0:
                        bar_size = round(remaining_pixels * (stack_bar.size / remaining_fractions))
                        remaining_fractions -= stack_bar.size
                        remaining_pixels -= bar_size

                        bar_start += bar_size

                        last_color = self.stack_key_colors.get(self.stack_keys[j]) or self.get_bar_color(j)
                        self.draw_bar(exes[key][0],
                                      self.graph_height - bar_start,
                                      exes[key][1],
                                      bar_size,
                                      last_color)
            else:
                bar_size = round(max_bar_size * bar.size)
                bar_start = bar_size

                last_color = self.key_colors.get(key) or base_color
                self.draw_bar(exes[key][0],
                              self.graph_y + self.graph_height - bar_size,
                              exes[key][1],
                              bar_size,
                              last_color)


            if self.values_on_bars:  # it is either stack labels or values at the end for now
                if self.stack_keys:
                    total_value = sum(data[i])
                else:
                    total_value = data[i]

                self.layout.set_width(-1)
                self.layout.set_text(self.value_format % total_value)
                label_w, label_h = self.layout.get_pixel_size()


                if bar_start > label_h + 2:
                    label_y = self.graph_y + self.graph_height - bar_start + 5
                else:
                    label_y = self.graph_y + self.graph_height - bar_start - label_h + 5

                context.move_to(self.exes[key][0] + (self.exes[key][1] - label_w) / 2.0,
                                label_y)

                # we are in the bar so make sure that the font color is distinguishable
                if self.colors.is_light(last_color):
                    self.set_color(label_color)
                else:
                    self.set_color(self.colors.almost_white)

                context.show_layout(self.layout)


        #white grid and scale values
        if self.background:
            grid_color = self.background
        else:
            grid_color = self.get_style().bg[gtk.STATE_NORMAL].to_string()
            
        self.layout.set_width(-1)
        if self.grid_stride and self.max_value:
            # if grid stride is less than 1 then we consider it to be percentage
            if self.grid_stride < 1:
                grid_stride = int(self.max_value * self.grid_stride)
            else:
                grid_stride = int(self.grid_stride)

            context.set_line_width(1)
            for i in range(grid_stride, int(self.max_value), grid_stride):
                y = round(max_bar_size * (i / self.max_value)) + 0.5

                if self.show_scale:
                    self.layout.set_text(self.value_format % i)
                    label_w, label_h = self.layout.get_pixel_size()
                    context.move_to(legend_width - label_w - 8,
                                    y - label_h / 2)
                    self.set_color(self.colors.aluminium[4])
                    context.show_layout(self.layout)

                self.set_color(grid_color)
                self.context.move_to(legend_width, y)
                self.context.line_to(self.width, y)


        #stack keys
        if self.show_stack_labels:
            #put series keys
            self.set_color(label_color);

            y = self.graph_height
            label_y = None

            # if labels are at end, then we need show them for the last bar!
            if self.labels_at_end:
                factors = self.bars[-1]
            else:
                factors = self.bars[0]

            if isinstance(factors, Bar):
                factors = [factors]

            self.layout.set_ellipsize(pango.ELLIPSIZE_END)
            self.layout.set_width(self.graph_x * pango.SCALE)
            if self.labels_at_end:
                self.layout.set_alignment(pango.ALIGN_LEFT)
            else:
                self.layout.set_alignment(pango.ALIGN_RIGHT)

            for j in range(len(factors)):
                factor = factors[j].size
                bar_size = factor * max_bar_size

                if round(bar_size) > 0 and self.stack_keys:
                    label = "%s" % self.stack_keys[j]


                    self.layout.set_text(label)
                    label_w, label_h = self.layout.get_pixel_size()

                    y -= bar_size
                    intended_position = round(y + (bar_size - label_h) / 2)

                    if label_y:
                        label_y = min(intended_position, label_y - label_h)
                    else:
                        label_y = intended_position

                    if self.labels_at_end:
                        label_x = self.graph_x + self.graph_width
                        line_x1 = self.graph_x + self.graph_width - 1
                        line_x2 = self.graph_x + self.graph_width - 6
                    else:
                        label_x = -8
                        line_x1 = self.graph_x - 6
                        line_x2 = self.graph_x


                    context.move_to(label_x, label_y)
                    context.show_layout(self.layout)

                    if label_y != intended_position:
                        context.move_to(line_x1, label_y + label_h / 2)
                        context.line_to(line_x2, round(y + bar_size / 2))

        context.stroke()


class HorizontalBarChart(Chart):
    def on_expose(self):
        Chart.on_expose(self)

        if not self.data:
            return

        context = self.context
        rowcount, keys = len(self.keys), self.keys

        # 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
        self.graph_y, self.graph_height = 0, self.height


        if self.chart_background:
            self.fill_area(self.graph_x, self.graph_y, self.graph_width, self.graph_height, self.chart_background)


        if not self.data:  # go home if we have nothing
            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

        self.layout.set_alignment(pango.ALIGN_RIGHT)
        self.layout.set_ellipsize(pango.ELLIPSIZE_END)



        context.set_line_width(1)

        # bars and labels
        self.layout.set_width(legend_width * pango.SCALE)


        # determine bar color
        base_color = self.bar_base_color
        if not base_color: #yay, we can be theme friendly!
            bg_color = self.get_style().bg[gtk.STATE_NORMAL].to_string()
            if self.colors.is_light(bg_color):
                base_color = self.colors.darker(bg_color,  30)
            else:
                base_color = self.colors.darker(bg_color,  -30)
                tick_color = self.colors.darker(bg_color,  -50)
        last_color = base_color


        # now for the text - we want reduced contrast for relaxed visuals
        fg_color = self.get_style().fg[gtk.STATE_NORMAL].to_string()
        if self.colors.is_light(fg_color):
            label_color = self.colors.darker(fg_color,  80)
        else:
            label_color = self.colors.darker(fg_color,  -80)


        for i, label in enumerate(keys):
            if self.interactive:
                self.register_mouse_region(0,
                                           positions[label][0],
                                           self.width,
                                           positions[label][0] + positions[label][1],
                                           str(i))

            self.layout.set_width(legend_width * pango.SCALE)
            self.layout.set_text(label)
            label_w, label_h = self.layout.get_pixel_size()
            label_y = positions[label][0] + (positions[label][1] - label_h) / 2

            if i == self.mouse_bar:
                self.set_color(self.get_style().fg[gtk.STATE_PRELIGHT])
            else:
                self.set_color(label_color)


            context.move_to(0, label_y)
            context.show_layout(self.layout)


            if self.stack_keys:
                bar_start = 0

                remaining_fractions, remaining_pixels = 1, max_bar_size

                for j, stack_bar in enumerate(self.bars[i]):
                    if stack_bar.size > 0:
                        bar_size = round(remaining_pixels * (stack_bar.size / remaining_fractions))
                        remaining_fractions -= stack_bar.size
                        remaining_pixels -= bar_size

                        last_color = self.stack_key_colors.get(self.stack_keys[j]) or self.get_bar_color(j)
                        self.draw_bar(self.graph_x + bar_start,
                                      positions[label][0],
                                      bar_size,
                                      positions[label][1],
                                      last_color)
                        bar_start += bar_size
            else:
                bar_size = round(max_bar_size * self.bars[i].size)
                bar_start = bar_size

                if i in self.bars_selected:
                    last_color = self.get_style().bg[gtk.STATE_SELECTED].to_string()
                elif i == self.mouse_bar:
                    last_color = self.get_style().base[gtk.STATE_PRELIGHT].to_string()
                else:
                    last_color = self.key_colors.get(self.keys[i]) or base_color

                self.draw_bar(self.graph_x,
                              positions[label][0],
                              bar_size,
                              positions[label][1],
                              last_color)


            # value labels
            if self.stack_keys:
                total_value = sum(self.data[i])
            else:
                total_value = self.data[i]

            self.layout.set_width(-1)
            self.layout.set_text(self.value_format % total_value)
            label_w, label_h = self.layout.get_pixel_size()

            vertical_padding = max((positions[label][1] - label_h) / 2.0, 1)

            label_y = positions[label][0] + (positions[label][1] - label_h) / 2.0
            if  bar_start - vertical_padding < label_w:
                label_x = self.graph_x + bar_start + vertical_padding

                # avoid zero selected bars without any hints
                if not self.stack_keys and i in self.bars_selected and self.bars[i].value == 0:
                    self.set_color(self.get_style().bg[gtk.STATE_SELECTED])
                    self.draw_rect(label_x - 2,
                                   label_y - 2,
                                   label_w + 4,
                                   label_h + 4, 4)
                    self.context.fill()
                    self.set_color(self.get_style().fg[gtk.STATE_SELECTED])
                else:
                    self.set_color(label_color)
            else:
                label_x = self.graph_x + bar_start - label_w - vertical_padding

                if i in self.bars_selected:
                    self.set_color(self.get_style().fg[gtk.STATE_SELECTED].to_string())
                else:
                    # we are in the bar so make sure that the font color is distinguishable
                    if self.colors.is_light(last_color):
                        self.set_color(label_color)
                    else:
                        self.set_color(self.colors.almost_white)


            context.move_to(label_x, label_y)
            context.show_layout(self.layout)

        context.stroke()




class HorizontalDayChart(Chart):
    """Pretty much a horizontal bar chart, except for values it expects tuple
    of start and end time, and the whole thing hangs in air"""
    def __init__(self, *args, **kwargs):
        Chart.__init__(self, *args, **kwargs)
        self.start_time, self.end_time = None, None

    def plot_day(self, keys, data, start_time = None, end_time = None):
        self.keys, self.data = keys, data
        self.start_time, self.end_time = start_time, end_time
        self.show()
        self.redraw_canvas()

    def on_expose(self):
        context = self.context

        Chart.on_expose(self)
        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

        #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 self.chart_background:
            self.fill_area(self.graph_x, self.graph_y, self.graph_width, self.graph_height, self.chart_background)

        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 = self.get_style().fg[gtk.STATE_NORMAL].to_string()
        if self.colors.is_light(fg_color):
            label_color = self.colors.darker(fg_color,  80)
        else:
            label_color = self.colors.darker(fg_color,  -80)


        self.layout.set_alignment(pango.ALIGN_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
        base_color = self.bar_base_color
        if not base_color: #yay, we can be theme friendly!
            bg_color = self.get_style().bg[gtk.STATE_NORMAL].to_string()
            if self.colors.is_light(bg_color):
                base_color = self.colors.darker(bg_color,  30)
            else:
                base_color = self.colors.darker(bg_color,  -30)
                tick_color = self.colors.darker(bg_color,  -50)

        for i, label in enumerate(keys):
            self.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)

                self.draw_bar(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]]
        
        
        if self.background:
            grid_color = self.background
        else:
            grid_color = self.get_style().bg[gtk.STATE_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("%H<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)
            self.set_color(self.colors.aluminium[4])
            context.show_layout(self.layout)


            self.set_color(grid_color)
            self.context.move_to(round(self.graph_x + x) + 0.5, self.graph_y)
            self.context.line_to(round(self.graph_x + x) + 0.5,
                                 last_position[0] + last_position[1])


        context.stroke()


""" sample usage """
class BasicWindow:
    def __init__(self):
        window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        window.set_title("Hamster Charting")
        window.set_size_request(400, 300)
        window.connect("delete_event", lambda *args: gtk.main_quit())

        self.stacked = BarChart(background = "#fafafa",
                                bar_base_color = (220, 220, 220),
                                legend_width = 20,
                                show_stack_labels = True)

        box = gtk.VBox()
        box.pack_start(self.stacked)


        self.series = ["One", "Two", "Three", "Four", "Five", "Six", "Seven"]
        self.stacks = ["x", "y", "z", "a", "b", "c", "d"]
        self.stack_colors = dict([(stack, None) for stack in self.stacks])

        import random
        self.data = [[random.randint(0, 10) for j in range(len(self.stacks))] for i in range(len(self.series))]

        color_buttons = gtk.HBox()
        color_buttons.set_spacing(4)

        for stack in self.stacks:
            button = gtk.ColorButton()
            button.connect("color-set", self.on_color_set, stack)
            color_buttons.pack_start(button)

        box.pack_start(color_buttons, False)

        window.add(box)
        window.show_all()

        self.plot()


    def plot(self):
        self.stacked.stack_key_colors = self.stack_colors
        self.stacked.plot(self.series, self.data, self.stacks)


    def on_color_set(self, button, stack_idx):
        self.stack_colors[stack_idx] = button.get_color().to_string()
        self.plot()


if __name__ == "__main__":
   example = BasicWindow()
   gtk.main()

:: Command execute ::

Enter:
 
Select:
 

:: Search ::
  - regexp 

:: Upload ::
 
[ Read-Only ]

:: Make Dir ::
 
[ Read-Only ]
:: Make File ::
 
[ Read-Only ]

:: Go Dir ::
 
:: Go File ::
 

--[ c99shell v. 2.0 [PHP 7 Update] [25.02.2019] maintained by KaizenLouie | C99Shell Github | Generation time: 0.0138 ]--