def _draw_legend(self, categories): """ Draw legend for the given categories. Box in lower right corner Motivation for positioning in right corner: SVG text cannot be centered since the text width cannot be calculated and the first part of each event text is important. ergo: text needs to be left aligned. But then the probability is high that a lot of text is at the left bottom ergo: put the legend to the right. +----------+ | Name O | | Name O | +----------+ """ group = g() group.addElement(self._draw_categories_box(len(categories))) cur_y = self._get_categories_box_y(len(categories)) + OUTER_PADDING for cat in categories: color_box, label = self._draw_category( self._get_categories_box_width(), self._get_categories_item_height(), self._get_categories_box_x(), cur_y, cat) group.addElement(color_box) group.addElement(label) cur_y = cur_y + self._get_categories_item_height() + INNER_PADDING return group
def _get_bg(self): """ Draw background color Draw background Era strips and labels Draw major and minor strips, lines to all event boxes and baseline. Both major and minor strips have divider lines and labels. Draw now line if it is visible """ group = g() group.addElement(self._draw_background()) for era in self._timeline.get_all_periods(): group.addElement(self._draw_era_strip(era)) group.addElement(self._draw_era_text(era)) for strip in self._scene.minor_strip_data: group.addElement( self._draw_minor_strip_divider_line(strip.end_time)) group.addElement(self._draw_minor_strip_label(strip)) for strip in self._scene.major_strip_data: group.addElement( self._draw_major_strip_divider_line(strip.end_time)) group.addElement(self._draw_major_strip_label(strip)) group.addElement(self._draw_divider_line()) self._draw_lines_to_non_period_events(group, self._view_properties) if self._now_line_is_visible(): group.addElement(self._draw_now_line()) return group
def _draw_legend(self, categories): """ Draw legend for the given categories. Box in lower right corner Motivation for positioning in right corner: SVG text cannot be centered since the text width cannot be calculated and the first part of each event text is important. ergo: text needs to be left aligned. But then the probability is high that a lot of text is at the left bottom ergo: put the legend to the right. +----------+ | Name O | | Name O | +----------+ """ group = g() group.addElement(self._draw_categories_box(len(categories))) cur_y = self._get_categories_box_y(len(categories)) + OUTER_PADDING for cat in categories: color_box, label = self._draw_category(self._get_categories_box_width(), self._get_categories_item_height(), self._get_categories_box_x(), cur_y, cat) group.addElement(color_box) group.addElement(label) cur_y = cur_y + self._get_categories_item_height() + INNER_PADDING return group
def rotate(self, angle): group = g() for e in self: group.addElement(e) tb = TransformBuilder() tb.setRotation(angle) group.set_transform(tb.getTransform()) self.items = [group] return self
def translate(elems, x, y): group = g() for e in elems: group.addElement(e) tb = TransformBuilder() #tb.setRotation(rotate(x1, y1, x2, y2)) tb.setTranslation('{0},{1}'.format(x,y)) group.set_transform(tb.getTransform()) return group
def translate(elems, x, y): group = g() for e in elems: group.addElement(e) tb = TransformBuilder() #tb.setRotation(rotate(x1, y1, x2, y2)) tb.setTranslation('{0},{1}'.format(x, y)) group.set_transform(tb.getTransform()) return group
def move(self, x, y): group = g() for item in self: group.addElement(item) tb = TransformBuilder() tb.setTranslation('{0},{1}'.format(x, y)) group.set_transform(tb.getTransform()) self.items = [group] return self
def move(self, x, y): group = g() for item in self: group.addElement(item) tb = TransformBuilder() tb.setTranslation('{0},{1}'.format(x,y)) group.set_transform(tb.getTransform()) self.items = [group] return self
def scale(self, amount): """1 = 100%""" group = g() for e in self: group.addElement(e) tb = TransformBuilder() tb.setScaling(amount, amount) group.set_transform(tb.getTransform()) self.items = [group] return self
def scale(elems, amount): """1 = 100%""" group = g() for e in elems: group.addElement(e) tb = TransformBuilder() #tb.setRotation(rotate(x1, y1, x2, y2)) tb.setScaling(amount, amount) group.set_transform(tb.getTransform()) return group
def __prepareNodeContainer(self, startX, startY, width, height, isReference): nodeGroup = g() nodeGroup.set_style(self.__textStyle.getStyle()) if isReference: color = 'gray'; else: color = 'white'; rect = self.__shapeBuilder.createRect(startX, startY, width, height, strokewidth = self.__frameThickness, stroke='black', fill=color) nodeGroup.addElement(rect) return nodeGroup;
def chair(self, party): style = 'stroke:black;stroke-width:4.0;fill:%s;' head = ShapeBuilder().createCircle(30, 25, 16) head.set_class('head') head.set_style(style % party.head_color) body = ShapeBuilder().createPolygon('12,50,47,50,30,15') body.set_class('body') body.set_style(style % party.body_color) group = g() group.set_id(party.initials) group.addElement(body) group.addElement(head) return group
def write(self, path): """ Writes the page to the SVG file with the provided path. """ # Create a new SVG document doc = svg( x=0, y=0, width=mm_to_px(self.width), height=mm_to_px(self.height) ) # Draw all the content: first the background, then the content, # and finally the labels background_group = g() background_group.setAttribute('id', 'background') content_group = g() content_group.setAttribute('id', 'content') label_group = g() label_group.setAttribute('id', 'labels') contour_group = g() contour_group.setAttribute('id', 'contours') my_defs = defs() for c in self.containers: if c.has_background: c.draw_background(background_group) if c.needs_clipping and (c.has_content or c.has_labels): path_id = random_string(16) clprect = rect( x=mm_to_px(c.x), y=mm_to_px(c.y), width=mm_to_px(c.width), height=mm_to_px(c.height) ) clppath = clipPath(id=path_id) clppath.addElement(clprect) my_defs.addElement(clppath) # Draw content with clipping path if c.has_content: container_grp = g() container_grp.set_clip_path('url(#%s)' % path_id) c.draw_content(container_grp) content_group.addElement(container_grp) # The labels on top of the content if c.has_labels: container_grp = g() container_grp.set_clip_path('url(#%s)' % path_id) c.draw_labels(container_grp) label_group.addElement(container_grp) else: if c.has_content: c.draw_content(content_group) if c.has_labels: c.draw_labels(label_group) if c.has_contour: c.draw_contour(contour_group) # Add each of the base groups doc.addElement(my_defs) doc.addElement(background_group) doc.addElement(content_group) doc.addElement(label_group) doc.addElement(contour_group) # Write the SVG document to the file doc.save(path)
def _draw_event(self, event, rect): if self._scene.center_text(): style = self._small_centered_font_style else: style = self._small_font_style group = g() group.addElement(self._draw_event_rect(event, rect)) text_rect = rect.Get() if event.is_container() and EXTENDED_CONTAINER_HEIGHT.enabled(): text_rect = rect.Get() text_rect = (text_rect[0], text_rect[1] - Y_TEXT_OFFSET, text_rect[2], text_rect[3]) group.addElement(self._svg_clipped_text(event.text, text_rect, style, self._scene.center_text())) if event.has_data(): group.addElement(self._draw_contents_indicator(event, rect)) return group
def chair(self, id_attr, color_1, color_2): head = ShapeBuilder().createCircle(30, 25, 20, stroke='black', strokewidth=5.0, fill=color_1) head.set_class('head') body = path(pathData="M 19.264266,38.267870 C 12.892238,41.659428 9.0221978,48.396703 6.6126745,55.405840 L 51.476471,55.405840 C 49.270169,48.545436 45.682644,41.911786 39.811885,38.267870 C 33.901416,38.010889 26.459633,38.267870 19.264266,38.267870 z ") body.set_style('stroke-width:5.0;stroke:black;fill:%s;' % color_2) body.set_class('body') th = TransformBuilder() th.setScaling('0.8', '0.8') group = g() group.addElement(body) group.addElement(head) group.set_id(id_attr) group.set_transform(th.getTransform()) return group
def svg(self): if not self.chairs: raise SVGError('You need to calculate the chair distribution.') width, height = self.svg_dimention() # SVG doc s = svg(height="100%", width="100%") s.set_viewBox("0 0 %d %d" % (width, height)) t = title() t.appendTextContent('Parlamento') s.addElement(t) # Create the party groups groups = {} for i, party in enumerate(self.parties): groups[i] = g() groups[i].set_id('%s_group' % party.initials) t = title() t.appendTextContent('Grupo Parlamentar %s' % party.initials) groups[i].addElement(t) # Add the chair shape definition s.addElement(self.defs()) # Distribute the chairs for i, row in enumerate(self.chairs): for j, mp in enumerate(row): angle, x, y = self.hc.chair_location(i, j) x = x + width / 2 y = height - y t = title() t.appendTextContent(mp.name) mp_link = a() # TODO This link is a placeholder, it will be more sensible mp_link._attributes['xlink:href'] = 'http://parlamento.pt' mp_link.addElement(t) mp_link.addElement(self.chair_svg(i, j, mp)) groups[mp.party.order].addElement(mp_link) # Insert the party groups into the svg for i, party in enumerate(self.parties): s.addElement(groups[i]) return s.getXML()
def _draw_event(self, event, rect): if self._scene.center_text(): style = self._small_centered_font_style else: style = self._small_font_style group = g() group.addElement(self._draw_event_rect(event, rect)) text_rect = rect.Get() if event.is_container() and EXTENDED_CONTAINER_HEIGHT.enabled(): text_rect = rect.Get() text_rect = (text_rect[0], text_rect[1] - Y_TEXT_OFFSET, text_rect[2], text_rect[3]) group.addElement( self._svg_clipped_text(event.text, text_rect, style, self._scene.center_text())) if event.has_data(): group.addElement(self._draw_contents_indicator(event, rect)) return group
def svg(self): if not self.chairs: raise SVGError('You need to calculate the chair distribution.') width, height = self.svg_dimention() # SVG doc s = svg(height="100%", width="100%") s.set_viewBox("0 0 %d %d" % (width, height)) t = title() t.appendTextContent('Parlamento') s.addElement(t) # Create the party groups groups = {} for i in range(len(self.parties)): party = self.parties[i] groups[i] = g() # groups[i].set_fill(party['color']) groups[i].set_id('%s_group' % party['initials']) t = title() t.appendTextContent('Grupo Parlamentar do %s' % party['initials']) groups[i].addElement(t) # Add the chair shape definition s.addElement(self.defs()) # Distribute the chairs for row in range(len(self.chairs)): for col in range(len(self.chairs[row])): angle, x, y = self.hc.chair_location(row, col) x = x + width / 2 y = height - y groups[self.chairs[row][col]].addElement(self.chair_svg( row, col, self.parties[self.chairs[row][col]]['initials'])) # Insert the party groups into the svg for i in range(len(self.parties)): s.addElement(groups[i]) return s.getXML()
def draw_content(self, elem): # Create a new group grp = g() grp.setAttribute('id', 'scalebar') # Find the amount of available width bbox = self.map_container.bbox step_length = (float(self.step) * self.factor) c = [[bbox[0], 0], [bbox[0] + step_length, 0]] px = self.map_container.geo_to_local_coords(c) step_px = abs(px[1][0] - px[0][0]) nsteps = int(floor(float(self.width) / step_px)) # Draw the horizontal line l = path(pathData="M %f %f L %f %f" % ( mm_to_px(self.x), mm_to_px(self.y + self.height), mm_to_px(self.x + nsteps*step_px), mm_to_px(self.y + self.height) ), style=StyleBuilder({'stroke': 'black', 'stroke-width': 0.3}).getStyle()) grp.addElement(l) # Draw the vertical lines and write the text # textsize = int(re.findall('([0-9]+)', # self.style.style_dict.get('font-size', "12") # )[0]) for i in range(nsteps+1): l = path(pathData="M %f %f L %f %f" % ( mm_to_px(self.x + i*step_px), mm_to_px(self.y + self.height), mm_to_px(self.x + i*step_px), mm_to_px(self.y + self.height - 3) ), style=StyleBuilder({'stroke': 'black', 'stroke-width': 0.3}).getStyle()) grp.addElement(l) content = str(i*self.step) if i == nsteps: content += ' ' + self.unit t = text( content=content, x=mm_to_px(self.x + i*step_px), y=mm_to_px(self.y + self.height - 5) ) t.set_style(self.style.getStyle()) grp.addElement(t) elem.addElement(grp)
def _get_bg(self): """ Draw background color Draw background Era strips and labels Draw major and minor strips, lines to all event boxes and baseline. Both major and minor strips have divider lines and labels. Draw now line if it is visible """ group = g() group.addElement(self._draw_background()) for era in self._timeline.get_all_periods(): group.addElement(self._draw_era_strip(era)) group.addElement(self._draw_era_text(era)) for strip in self._scene.minor_strip_data: group.addElement(self._draw_minor_strip_divider_line(strip.end_time)) group.addElement(self._draw_minor_strip_label(strip)) for strip in self._scene.major_strip_data: group.addElement(self._draw_major_strip_divider_line(strip.end_time)) group.addElement(self._draw_major_strip_label(strip)) group.addElement(self._draw_divider_line()) self._draw_lines_to_non_period_events(group, self._view_properties) if self._now_line_is_visible(): group.addElement(self._draw_now_line()) return group
def _svg_clipped_text(self, text, rect, style, center_text=False): group = g() group.set_clip_path("url(#%s)" % self._create_clip_path(rect)) group.addElement(self._draw_text(text, rect, style, center_text)) return group