def _compute_margin(self): """Compute graph margins from set texts""" if self.show_legend and self.series: h, w = get_texts_box( map(lambda x: truncate(x, self.truncate_legend or 15), cut(self.series, 'title')), self.legend_font_size) if self.legend_at_bottom: h_max = max(h, self.legend_box_size) self.margin.bottom += 10 + h_max * round( sqrt(self._order) - 1) * 1.5 + h_max else: self.margin.right += 10 + w + self.legend_box_size if self.title: h, _ = get_text_box(self.title[0], self.title_font_size) self.margin.top += len(self.title) * (10 + h) if self._x_labels: h, w = get_texts_box( cut(self._x_labels), self.label_font_size) self._x_labels_height = 10 + max( w * sin(rad(self.x_label_rotation)), h) self.margin.bottom += self._x_labels_height if self.x_label_rotation: self.margin.right = max( w * cos(rad(self.x_label_rotation)), self.margin.right) else: self._x_labels_height = 0 if self._y_labels: h, w = get_texts_box( cut(self._y_labels), self.label_font_size) self.margin.left += 10 + max( w * cos(rad(self.y_label_rotation)), h)
def _compute_margin(self): """Compute graph margins from set texts""" if self.show_legend and self.series: h, w = get_texts_box( map(lambda x: truncate(x, self.truncate_legend or 15), cut(self.series, 'title')), self.legend_font_size) if self.legend_at_bottom: h_max = max(h, self.legend_box_size) self.margin.bottom += 10 + h_max * round( sqrt(self._order) - 1) * 1.5 + h_max else: self.margin.right += 10 + w + self.legend_box_size if self.title: h, _ = get_text_box(self.title[0], self.title_font_size) self.margin.top += len(self.title) * (10 + h) if self._x_labels: h, w = get_texts_box(cut(self._x_labels), self.label_font_size) self._x_labels_height = 10 + max( w * sin(rad(self.x_label_rotation)), h) self.margin.bottom += self._x_labels_height if self.x_label_rotation: self.margin.right = max(w * cos(rad(self.x_label_rotation)), self.margin.right) else: self._x_labels_height = 0 if self._y_labels: h, w = get_texts_box(cut(self._y_labels), self.label_font_size) self.margin.left += 10 + max(w * cos(rad(self.y_label_rotation)), h)
def _compute_margin(self): """Compute graph margins from set texts""" self._legend_at_left_width = 0 for series_group in (self.series, self.secondary_series): if self.show_legend and series_group: h, w = get_texts_box( map(lambda x: truncate(x, self.truncate_legend or 15), cut(series_group, 'title')), self.legend_font_size) if self.legend_at_bottom: h_max = max(h, self.legend_box_size) cols = (self._order // self.legend_at_bottom_columns if self.legend_at_bottom_columns else ceil(sqrt(self._order)) or 1) self.margin.bottom += self.spacing + h_max * round( cols - 1) * 1.5 + h_max else: if series_group is self.series: legend_width = self.spacing + w + self.legend_box_size self.margin.left += legend_width self._legend_at_left_width += legend_width else: self.margin.right += ( self.spacing + w + self.legend_box_size) self._x_labels_height = 0 if (self._x_labels or self._x_2nd_labels) and self.show_x_labels: for xlabels in (self._x_labels, self._x_2nd_labels): if xlabels: h, w = get_texts_box( map(lambda x: truncate(x, self.truncate_label or 25), cut(xlabels)), self.label_font_size) self._x_labels_height = self.spacing + max( w * sin(rad(self.x_label_rotation)), h) if xlabels is self._x_labels: self.margin.bottom += self._x_labels_height else: self.margin.top += self._x_labels_height if self.x_label_rotation: self.margin.right = max( w * cos(rad(self.x_label_rotation)), self.margin.right) if self.show_y_labels: for ylabels in (self._y_labels, self._y_2nd_labels): if ylabels: h, w = get_texts_box( cut(ylabels), self.label_font_size) if ylabels is self._y_labels: self.margin.left += self.spacing + max( w * cos(rad(self.y_label_rotation)), h) else: self.margin.right += self.spacing + max( w * cos(rad(self.y_label_rotation)), h) self.title = split_title( self.title, self.width, self.title_font_size) if self.title: h, _ = get_text_box(self.title[0], self.title_font_size) self.margin.top += len(self.title) * (self.spacing + h) self.x_title = split_title( self.x_title, self.width - self.margin.x, self.title_font_size) self._x_title_height = 0 if self.x_title: h, _ = get_text_box(self.x_title[0], self.title_font_size) height = len(self.x_title) * (self.spacing + h) self.margin.bottom += height self._x_title_height = height + self.spacing self.y_title = split_title( self.y_title, self.height - self.margin.y, self.title_font_size) self._y_title_height = 0 if self.y_title: h, _ = get_text_box(self.y_title[0], self.title_font_size) height = len(self.y_title) * (self.spacing + h) self.margin.left += height self._y_title_height = height + self.spacing
def _legend(self): """Make the legend box""" if not self.show_legend: return truncation = self.truncate_legend if self.legend_at_bottom: x = self.margin.left + self.spacing y = (self.margin.top + self.view.height + self._x_title_height + self._x_labels_height + self.spacing) cols = ceil(sqrt(self._order)) or 1 if not truncation: available_space = self.view.width / cols - ( self.legend_box_size + 5) truncation = reverse_text_len( available_space, self.legend_font_size) else: x = self.spacing y = self.margin.top + self.spacing cols = 1 if not truncation: truncation = 15 legends = self.svg.node( self.nodes['graph'], class_='legends', transform='translate(%d, %d)' % (x, y)) h = max(self.legend_box_size, self.legend_font_size) x_step = self.view.width / cols if self.legend_at_bottom: # if legends at the bottom, we dont split the windows # gen structure - (i, (j, (l, tf))) # i - global serie number - used for coloring and identification # j - position within current legend box # l - label # tf - whether it is secondary label gen = enumerate(enumerate(chain( zip(self._legends, repeat(False)), zip(self._secondary_legends, repeat(True))))) secondary_legends = legends # svg node is the same else: gen = enumerate(chain( enumerate(zip(self._legends, repeat(False))), enumerate(zip(self._secondary_legends, repeat(True))))) # draw secondary axis on right x = self.margin.left + self.view.width + self.spacing if self._y_2nd_labels: h, w = get_texts_box( cut(self._y_2nd_labels), self.label_font_size) x += self.spacing + max(w * cos(rad(self.y_label_rotation)), h) y = self.margin.top + self.spacing secondary_legends = self.svg.node( self.nodes['graph'], class_='legends', transform='translate(%d, %d)' % (x, y)) for (global_serie_number, (i, (title, is_secondary))) in gen: col = i % cols row = i // cols legend = self.svg.node( secondary_legends if is_secondary else legends, class_='legend reactive activate-serie', id="activate-serie-%d" % global_serie_number) self.svg.node( legend, 'rect', x=col * x_step, y=1.5 * row * h + ( self.legend_font_size - self.legend_box_size if self.legend_font_size > self.legend_box_size else 0 ) / 2, width=self.legend_box_size, height=self.legend_box_size, class_="color-%d reactive" % ( global_serie_number % len(self.style['colors'])) ) if isinstance(title, dict): node = decorate(self.svg, legend, title) title = title['title'] else: node = legend truncated = truncate(title, truncation) self.svg.node( node, 'text', x=col * x_step + self.legend_box_size + 5, y=1.5 * row * h + .5 * h + .3 * self.legend_font_size ).text = truncated if truncated != title: self.svg.node(legend, 'title').text = title
def _legend(self): """Make the legend box""" if not self.show_legend: return truncation = self.truncate_legend if self.legend_at_bottom: x = self.margin.left + self.spacing y = (self.margin.top + self.view.height + self._x_title_height + self._x_labels_height + self.spacing) cols = self.legend_at_bottom_columns or ceil(sqrt( self._order)) or 1 if not truncation: available_space = self.view.width / cols - ( self.legend_box_size + 5) truncation = reverse_text_len(available_space, self.legend_font_size) else: x = self.spacing y = self.margin.top + self.spacing cols = 1 if not truncation: truncation = 15 legends = self.svg.node(self.nodes['graph'], class_='legends', transform='translate(%d, %d)' % (x, y)) h = max(self.legend_box_size, self.legend_font_size) x_step = self.view.width / cols if self.legend_at_bottom: # if legends at the bottom, we dont split the windows # gen structure - (i, (j, (l, tf))) # i - global serie number - used for coloring and identification # j - position within current legend box # l - label # tf - whether it is secondary label gen = enumerate( enumerate( chain(zip(self._legends, repeat(False)), zip(self._secondary_legends, repeat(True))))) secondary_legends = legends # svg node is the same else: gen = enumerate( chain(enumerate(zip(self._legends, repeat(False))), enumerate(zip(self._secondary_legends, repeat(True))))) # draw secondary axis on right x = self.margin.left + self.view.width + self.spacing if self._y_2nd_labels: h, w = get_texts_box(cut(self._y_2nd_labels), self.label_font_size) x += self.spacing + max(w * cos(rad(self.y_label_rotation)), h) y = self.margin.top + self.spacing secondary_legends = self.svg.node(self.nodes['graph'], class_='legends', transform='translate(%d, %d)' % (x, y)) for (global_serie_number, (i, (title, is_secondary))) in gen: col = i % cols row = i // cols legend = self.svg.node( secondary_legends if is_secondary else legends, class_='legend reactive activate-serie', id="activate-serie-%d" % global_serie_number) self.svg.node( legend, 'rect', x=col * x_step, y=1.5 * row * h + (self.legend_font_size - self.legend_box_size if self.legend_font_size > self.legend_box_size else 0) / 2, width=self.legend_box_size, height=self.legend_box_size, class_="color-%d reactive" % (global_serie_number % len(self.style['colors']))) if isinstance(title, dict): node = decorate(self.svg, legend, title) title = title['title'] else: node = legend truncated = truncate(title, truncation) self.svg.node(node, 'text', x=col * x_step + self.legend_box_size + 5, y=1.5 * row * h + .5 * h + .3 * self.legend_font_size).text = truncated if truncated != title: self.svg.node(legend, 'title').text = title
def _compute_margin(self): """Compute graph margins from set texts""" self._legend_at_left_width = 0 for series_group in (self.series, self.secondary_series): if self.show_legend and series_group: h, w = get_texts_box( map( lambda x: truncate(x, self.truncate_legend or 15), [ serie.title['title'] if isinstance(serie.title, dict) else serie.title or '' for serie in series_group ] ), self.style.legend_font_size ) if self.legend_at_bottom: h_max = max(h, self.legend_box_size) cols = ( self._order // self.legend_at_bottom_columns if self.legend_at_bottom_columns else ceil(sqrt(self._order)) or 1 ) self.margin_box.bottom += self.spacing + h_max * round( cols - 1 ) * 1.5 + h_max else: if series_group is self.series: legend_width = self.spacing + w + self.legend_box_size self.margin_box.left += legend_width self._legend_at_left_width += legend_width else: self.margin_box.right += ( self.spacing + w + self.legend_box_size ) self._x_labels_height = 0 if (self._x_labels or self._x_2nd_labels) and self.show_x_labels: for xlabels in (self._x_labels, self._x_2nd_labels): if xlabels: h, w = get_texts_box( map( lambda x: truncate(x, self.truncate_label or 25), cut(xlabels) ), self.style.label_font_size ) self._x_labels_height = self.spacing + max( w * abs(sin(rad(self.x_label_rotation))), h ) if xlabels is self._x_labels: self.margin_box.bottom += self._x_labels_height else: self.margin_box.top += self._x_labels_height if self.x_label_rotation: if self.x_label_rotation % 180 < 90: self.margin_box.right = max( w * abs(cos(rad(self.x_label_rotation))), self.margin_box.right ) else: self.margin_box.left = max( w * abs(cos(rad(self.x_label_rotation))), self.margin_box.left ) if self.show_y_labels: for ylabels in (self._y_labels, self._y_2nd_labels): if ylabels: h, w = get_texts_box( cut(ylabels), self.style.label_font_size ) if ylabels is self._y_labels: self.margin_box.left += self.spacing + max( w * abs(cos(rad(self.y_label_rotation))), h ) else: self.margin_box.right += self.spacing + max( w * abs(cos(rad(self.y_label_rotation))), h ) self._title = split_title( self.title, self.width, self.style.title_font_size ) if self.title: h, _ = get_text_box(self._title[0], self.style.title_font_size) self.margin_box.top += len(self._title) * (self.spacing + h) self._x_title = split_title( self.x_title, self.width - self.margin_box.x, self.style.title_font_size ) self._x_title_height = 0 if self._x_title: h, _ = get_text_box(self._x_title[0], self.style.title_font_size) height = len(self._x_title) * (self.spacing + h) self.margin_box.bottom += height self._x_title_height = height + self.spacing self._y_title = split_title( self.y_title, self.height - self.margin_box.y, self.style.title_font_size ) self._y_title_height = 0 if self._y_title: h, _ = get_text_box(self._y_title[0], self.style.title_font_size) height = len(self._y_title) * (self.spacing + h) self.margin_box.left += height self._y_title_height = height + self.spacing # Inner margin if self.print_values_position == 'top': gh = self.height - self.margin_box.y alpha = 1.1 * (self.style.value_font_size / gh) * self._box.height if self._max and self._max > 0: self._box.ymax += alpha if self._min and self._min < 0: self._box.ymin -= alpha
def _legend(self): """Make the legend box""" if not self.show_legend: return truncation = self.truncate_legend if self.legend_at_bottom: x = self.margin_box.left + self.spacing y = ( self.margin_box.top + self.view.height + self._x_title_height + self._x_labels_height + self.spacing ) cols = self.legend_at_bottom_columns or ceil(sqrt(self._order) ) or 1 if not truncation: available_space = self.view.width / cols - ( self.legend_box_size + 5 ) truncation = reverse_text_len( available_space, self.style.legend_font_size ) else: x = self.spacing y = self.margin_box.top + self.spacing cols = 1 if not truncation: truncation = 15 legends = self.svg.node( self.nodes['graph'], class_='legends', transform='translate(%d, %d)' % (x, y) ) h = max(self.legend_box_size, self.style.legend_font_size) x_step = self.view.width / cols if self.legend_at_bottom: secondary_legends = legends # svg node is the same else: # draw secondary axis on right x = self.margin_box.left + self.view.width + self.spacing if self._y_2nd_labels: h, w = get_texts_box( cut(self._y_2nd_labels), self.style.label_font_size ) x += self.spacing + max( w * abs(cos(rad(self.y_label_rotation))), h ) y = self.margin_box.top + self.spacing secondary_legends = self.svg.node( self.nodes['graph'], class_='legends', transform='translate(%d, %d)' % (x, y) ) serie_number = -1 i = 0 for titles, is_secondary in ((self._legends, False), (self._secondary_legends, True)): if not self.legend_at_bottom and is_secondary: i = 0 for title in titles: serie_number += 1 if title is None: continue col = i % cols row = i // cols legend = self.svg.node( secondary_legends if is_secondary else legends, class_='legend reactive activate-serie', id="activate-serie-%d" % serie_number ) self.svg.node( legend, 'rect', x=col * x_step, y=1.5 * row * h + ( self.style.legend_font_size - self.legend_box_size if self.style.legend_font_size > self.legend_box_size else 0 ) / 2, width=self.legend_box_size, height=self.legend_box_size, class_="color-%d reactive" % serie_number ) if isinstance(title, dict): node = decorate(self.svg, legend, title) title = title['title'] else: node = legend truncated = truncate(title, truncation) self.svg.node( node, 'text', x=col * x_step + self.legend_box_size + 5, y=1.5 * row * h + .5 * h + .3 * self.style.legend_font_size ).text = truncated if truncated != title: self.svg.node(legend, 'title').text = title i += 1
def _compute_margin(self): """Compute graph margins from set texts""" self._legend_at_left_width = 0 for series_group in (self.series, self.secondary_series): if self.show_legend and series_group: h, w = get_texts_box( map(lambda x: truncate(x, self.truncate_legend or 15), [serie.title['title'] if isinstance(serie.title, dict) else serie.title or '' for serie in series_group]), self.style.legend_font_size) if self.legend_at_bottom: h_max = max(h, self.legend_box_size) cols = (self._order // self.legend_at_bottom_columns if self.legend_at_bottom_columns else ceil(sqrt(self._order)) or 1) self.margin_box.bottom += self.spacing + h_max * round( cols - 1) * 1.5 + h_max else: if series_group is self.series: legend_width = self.spacing + w + self.legend_box_size self.margin_box.left += legend_width self._legend_at_left_width += legend_width else: self.margin_box.right += ( self.spacing + w + self.legend_box_size) self._x_labels_height = 0 if (self._x_labels or self._x_2nd_labels) and self.show_x_labels: for xlabels in (self._x_labels, self._x_2nd_labels): if xlabels: h, w = get_texts_box( map(lambda x: truncate(x, self.truncate_label or 25), cut(xlabels)), self.style.label_font_size) self._x_labels_height = self.spacing + max( w * abs(sin(rad(self.x_label_rotation))), h) if xlabels is self._x_labels: self.margin_box.bottom += self._x_labels_height else: self.margin_box.top += self._x_labels_height if self.x_label_rotation: if self.x_label_rotation % 180 < 90: self.margin_box.right = max( w * abs(cos(rad(self.x_label_rotation))), self.margin_box.right) else: self.margin_box.left = max( w * abs(cos(rad(self.x_label_rotation))), self.margin_box.left) if self.show_y_labels: for ylabels in (self._y_labels, self._y_2nd_labels): if ylabels: h, w = get_texts_box( cut(ylabels), self.style.label_font_size) if ylabels is self._y_labels: self.margin_box.left += self.spacing + max( w * abs(cos(rad(self.y_label_rotation))), h) else: self.margin_box.right += self.spacing + max( w * abs(cos(rad(self.y_label_rotation))), h) self._title = split_title( self.title, self.width, self.style.title_font_size) if self.title: h, _ = get_text_box(self._title[0], self.style.title_font_size) self.margin_box.top += len(self._title) * (self.spacing + h) self._x_title = split_title( self.x_title, self.width - self.margin_box.x, self.style.title_font_size) self._x_title_height = 0 if self._x_title: h, _ = get_text_box(self._x_title[0], self.style.title_font_size) height = len(self._x_title) * (self.spacing + h) self.margin_box.bottom += height self._x_title_height = height + self.spacing self._y_title = split_title( self.y_title, self.height - self.margin_box.y, self.style.title_font_size) self._y_title_height = 0 if self._y_title: h, _ = get_text_box(self._y_title[0], self.style.title_font_size) height = len(self._y_title) * (self.spacing + h) self.margin_box.left += height self._y_title_height = height + self.spacing # Inner margin if self.print_values_position == 'top': gh = self.height - self.margin_box.y alpha = 1.1 * (self.style.value_font_size / gh) * self._box.height if self._max > 0: self._box.ymax += alpha if self._min < 0: self._box.ymin -= alpha
def _legend(self): """Make the legend box""" if not self.show_legend: return truncation = self.truncate_legend if self.legend_at_bottom: x = self.margin_box.left + self.spacing y = (self.margin_box.top + self.view.height + self._x_title_height + self._x_labels_height + self.spacing) cols = self.legend_at_bottom_columns or ceil( sqrt(self._order)) or 1 if not truncation: available_space = self.view.width / cols - ( self.legend_box_size + 5) truncation = reverse_text_len( available_space, self.style.legend_font_size) else: x = self.spacing y = self.margin_box.top + self.spacing cols = 1 if not truncation: truncation = 15 legends = self.svg.node( self.nodes['graph'], class_='legends', transform='translate(%d, %d)' % (x, y)) h = max(self.legend_box_size, self.style.legend_font_size) x_step = self.view.width / cols if self.legend_at_bottom: secondary_legends = legends # svg node is the same else: # draw secondary axis on right x = self.margin_box.left + self.view.width + self.spacing if self._y_2nd_labels: h, w = get_texts_box( cut(self._y_2nd_labels), self.style.label_font_size) x += self.spacing + max(w * abs(cos(rad( self.y_label_rotation))), h) y = self.margin_box.top + self.spacing secondary_legends = self.svg.node( self.nodes['graph'], class_='legends', transform='translate(%d, %d)' % (x, y)) serie_number = -1 i = 0 for titles, is_secondary in ( (self._legends, False), (self._secondary_legends, True)): if not self.legend_at_bottom and is_secondary: i = 0 for title in titles: serie_number += 1 if title is None: continue col = i % cols row = i // cols legend = self.svg.node( secondary_legends if is_secondary else legends, class_='legend reactive activate-serie', id="activate-serie-%d" % serie_number) self.svg.node( legend, 'rect', x=col * x_step, y=1.5 * row * h + ( self.style.legend_font_size - self.legend_box_size if self.style.legend_font_size > self.legend_box_size else 0 ) / 2, width=self.legend_box_size, height=self.legend_box_size, class_="color-%d reactive" % ( serie_number % len(self.style.colors)) ) if isinstance(title, dict): node = decorate(self.svg, legend, title) title = title['title'] else: node = legend truncated = truncate(title, truncation) self.svg.node( node, 'text', x=col * x_step + self.legend_box_size + 5, y=1.5 * row * h + .5 * h + .3 * self.style.legend_font_size ).text = truncated if truncated != title: self.svg.node(legend, 'title').text = title i += 1