diff --git a/gramps2/src/DrawDoc.py b/gramps2/src/DrawDoc.py index 658ac7ad1..18c272ea1 100644 --- a/gramps2/src/DrawDoc.py +++ b/gramps2/src/DrawDoc.py @@ -18,6 +18,8 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # +from math import cos,sin,pi + #------------------------------------------------------------------------ # # gramps modules @@ -182,11 +184,62 @@ class DrawDoc: def center_text(self,style,text,x1,y1): pass + def rotate_text(self,style,text,x,y,angle): + pass + def draw_line(self,style,x1,y1,x2,y2): pass - def draw_wedge(self, style, centerx, centery, radius, start_angle, end_angle): - pass + def draw_wedge(self, style, centerx, centery, radius, start_angle, + end_angle, short_radius=0): + + while end_angle < start_angle: + end_angle += 360 + + p = [] + + degreestoradians = pi/180.0 + radiansdelta = degreestoradians/2 + sangle = start_angle*degreestoradians + eangle = end_angle*degreestoradians + while eangle=sangle: + x = centerx + cos(angle)*short_radius + y = centery + sin(angle)*short_radius + p.append((x,y)) + angle = angle-radiansdelta + self.draw_path(style,p) + + delta = (eangle - sangle)/2.0 + rad = short_radius + (radius-short_radius)/2.0 + + return ( (centerx + cos(sangle+delta) * rad), + (centery + sin(sangle+delta) * rad)) def start_path(self,style,x,y): pass diff --git a/gramps2/src/docgen/OpenDrawDoc.py b/gramps2/src/docgen/OpenDrawDoc.py index e27894a80..bb6853d18 100644 --- a/gramps2/src/docgen/OpenDrawDoc.py +++ b/gramps2/src/docgen/OpenDrawDoc.py @@ -27,6 +27,7 @@ import os import tempfile import string import zipfile +from math import sin, cos, pi, fabs #------------------------------------------------------------------------- # @@ -438,6 +439,35 @@ class OpenDrawDoc(DrawDoc.DrawDoc): def end_page(self): self.f.write('\n') + def rotate_text(self,style,text,x,y,angle): + + stype = self.draw_styles[style] + pname = stype.get_paragraph_style() + p = self.style_list[pname] + font = p.get_font() + size = font.get_size() + + height = size*(len(text)) + width = 0 + for line in text: + width = max(width,FontScale.string_width(font,line)) + wcm = (width/72.0)*2.54 + hcm = (height/72.0)*2.54 + + rangle = -((pi/180.0) * angle) + + self.f.write('') + self.f.write('' % pname) + self.write_text(string.join(text,'\n')) + self.f.write('\n') + def draw_path(self,style,path): stype = self.draw_styles[style] @@ -560,4 +590,4 @@ class OpenDrawDoc(DrawDoc.DrawDoc): # Register document generator # #------------------------------------------------------------------------- -Plugins.register_draw_doc(_("OpenOffice.org/StarOffice 6"),OpenDrawDoc,1,1,".sxd"); +Plugins.register_draw_doc(_("OpenOffice.org Draw"),OpenDrawDoc,1,1,".sxd"); diff --git a/gramps2/src/docgen/PSDrawDoc.py b/gramps2/src/docgen/PSDrawDoc.py index 6639d4e23..232583dda 100644 --- a/gramps2/src/docgen/PSDrawDoc.py +++ b/gramps2/src/docgen/PSDrawDoc.py @@ -202,8 +202,6 @@ class PSDrawDoc(DrawDoc.DrawDoc): return ( (centerx + cos(sangle+delta) * rad), (centery + sin(sangle+delta) * rad)) -# return ( (centerx + cos(sangle+delta) * rad)-self.lmargin, -# (centery + sin(sangle+delta) * rad)-self.tmargin) def rotate_text(self,style,text,x,y,angle): diff --git a/gramps2/src/docgen/PdfDrawDoc.py b/gramps2/src/docgen/PdfDrawDoc.py index d53a76584..7c71d21b3 100644 --- a/gramps2/src/docgen/PdfDrawDoc.py +++ b/gramps2/src/docgen/PdfDrawDoc.py @@ -159,74 +159,6 @@ class PdfDrawDoc(DrawDoc.DrawDoc): else: self.f.drawPath(p,stroke=1,fill=0) - def draw_wedge(self, style, centerx, centery, radius, start_angle, - end_angle, short_radius=0): - - centerx += self.lmargin - centery += self.bmargin - - def rnd(val): - return val*cm - - while end_angle < start_angle: - end_angle += 360 - - stype = self.draw_styles[style] - if stype.get_line_style() == DrawDoc.SOLID: - self.f.setDash([],0) - else: - self.f.setDash([2,4],0) - - degreestoradians = pi/180.0 - radiansdelta = degreestoradians/2 - sangle = start_angle*degreestoradians - eangle = end_angle*degreestoradians - while eangle=sangle: - x = centerx + cos(angle)*short_radius - y = centery + sin(angle)*short_radius - p.lineTo(rnd(x),rnd(y)) - angle = angle-radiansdelta - p.close() - self.f.drawPath(p,stroke=1,fill=1) - - delta = (eangle - sangle)/2.0 - rad = short_radius + (radius-short_radius)/2.0 - - return ( (centerx + cos(sangle+delta) * rad)-self.lmargin, - (centery + sin(sangle+delta) * rad)-self.tmargin) - - def draw_box(self,style,text,x,y): x = x + self.lmargin y = y + self.tmargin diff --git a/gramps2/src/docgen/SvgDrawDoc.py b/gramps2/src/docgen/SvgDrawDoc.py index a9c4e055c..0a5e74877 100644 --- a/gramps2/src/docgen/SvgDrawDoc.py +++ b/gramps2/src/docgen/SvgDrawDoc.py @@ -24,6 +24,7 @@ # #------------------------------------------------------------------------- import string +from math import pi, cos, sin, fabs #------------------------------------------------------------------------- # @@ -35,6 +36,7 @@ from intl import gettext as _ import TextDoc import DrawDoc import Errors +import FontScale #------------------------------------------------------------------------- # @@ -88,13 +90,57 @@ class SvgDrawDoc(DrawDoc.DrawDoc): self.f.write('"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">\n') self.f.write('\n') - if self.orientation != TextDoc.PAPER_PORTRAIT: - self.f.write('\n' % self.height) + + def rotate_text(self,style,text,x,y,angle): + + stype = self.draw_styles[style] + pname = stype.get_paragraph_style() + p = self.style_list[pname] + font = p.get_font() + size = font.get_size() + + height = size*(len(text)) + width = 0 + for line in text: + width = max(width,FontScale.string_width(font,line)) + + rangle = -((pi/180.0) * angle) + + centerx,centery = units((x+self.lmargin,y+self.tmargin)) + + yh = 0 + for line in text: + xw = FontScale.string_width(font,line) + xpos = (centerx - (xw/2.0)) + ypos = (centery) + xd = 0 + yd = yh +# xd = yh * sin(-rangle) + # yd = yh * cos(-rangle) + + print centerx, centery, xpos, ypos, angle, line + + self.f.write('') + self.f.write(line) + self.f.write('\n') + yh += size + def end_page(self): - if self.orientation != TextDoc.PAPER_PORTRAIT: - self.f.write('\n') self.f.write('\n') self.f.close() @@ -118,7 +164,7 @@ class SvgDrawDoc(DrawDoc.DrawDoc): point = path[0] self.f.write('= 32: + return + self.map[index-1] = person + + self.text[index-1] = [] + + subst = SubstKeywords(person) + + for line in self.display: + self.text[index-1].append(subst.replace(line)) + + self.font = self.doc.style_list["Normal"].get_font() + for line in self.text[index-1]: + self.box_width = max(self.box_width,string_width(self.font,line)) + + self.lines = max(self.lines,len(self.text[index-1])) + + family = person.getMainParents() + if family != None: + self.filter(family.getFather(),index*2) + self.filter(family.getMother(),(index*2)+1) + + def write_report(self): + + self.filter(self.start,1) + + block_size = self.doc.get_usable_width()/14.0 + try: + self.doc.open(self.output) + except Errors.ReportError, val: + (m1,m2) = val.messages() + ErrorDialog(m1,m2) + + size = min(self.doc.get_usable_width(),self.doc.get_usable_height()*2.0)/2.0 + y = self.doc.get_usable_height() + max_lines = int(size/block_size) + center = (self.doc.get_usable_width()/2.0) + + self.doc.start_page() + + n = self.start.getPrimaryName().getRegularName() + self.doc.center_text('t', _('Five Generation Fan Chart for %s') % n, center, 0) + + self.circle_5(center,y,block_size) + self.circle_4(center,y,block_size) + self.circle_3(center,y,block_size) + self.circle_2(center,y,block_size) + self.circle_1(center,y,block_size) + + self.doc.end_page() + try: + self.doc.close() + except: + import DisplayTrace + DisplayTrace.DisplayTrace() + + def get_info(self,person): + pn = person.getPrimaryName() + b = person.getBirth().getDateObj().getYear() + d = person.getDeath().getDateObj().getYear() + if b == Calendar.UNDEF: + b = "" + if d == Calendar.UNDEF: + d = "" + + if b or d: + val = "%s - %s" % (str(b),str(d)) + else: + val = "" + + return [ pn.getFirstName(), pn.getSurname(), val ] + + def circle_1(self,center,y,size): + (xc,yc) = self.doc.draw_wedge("c1", center, y, size, 180, 360) + print center, y, xc, yc + self.doc.rotate_text("c1n", self.get_info(self.map[0]), xc, yc ,0) + + def circle_2(self,center,y,size): + (xc,yc) = self.doc.draw_wedge("c2", center, y, size*2, 180, 270, size) + if self.map[1]: + self.doc.rotate_text("c2n", self.get_info(self.map[1]), xc, yc, -45) + + (xc,yc) = self.doc.draw_wedge("c2", center, y, size*2, 270, 360, size) + if self.map[2]: + self.doc.rotate_text("c2n", self.get_info(self.map[2]), xc,yc ,45) + + def circle_3(self,center,y,size): + delta = 45 + sangle = -67.5 + for index in range(3,7): + start = 180+(index-3)*45 + stop = start+45 + (xc,yc) = self.doc.draw_wedge("c3", center, y, size*3, start, stop, size*2) + if self.map[index]: + self.doc.rotate_text("c3n", self.get_info(self.map[index]), + xc,yc ,sangle) + sangle += 45 + + def circle_4(self,center,y,size): + delta = 22.5 + sangle = -78.75 + 90 + for i in range(0,8): + start_angle = 180 + (i * delta) + end_angle = 180 + ((i+1) * delta) + (xc,yc) = self.doc.draw_wedge("c4", center, y, size*5, start_angle, + end_angle, size*3) + if i == 4: + sangle += 180 + if self.map[i+7]: + self.doc.rotate_text("c4n", self.get_info(self.map[i+7]), + xc,yc ,sangle) + sangle += 22.5 + + def circle_5(self,center,y,size): + delta = 11.25 + sangle = -84.625 + 90 + for i in range(0,16): + start_angle = 180 + (i * delta) + end_angle = 180 + ((i+1) * delta) + (xc,yc) = self.doc.draw_wedge("c5", center, y, size*7, start_angle, + end_angle, size*5) + if i == 8: + sangle += 180 + if self.map[i+15]: + self.doc.rotate_text("c5n", self.get_info(self.map[i+15]), + xc,yc ,sangle) + sangle += 11.25 + +#------------------------------------------------------------------------ +# +# FanChartDialog +# +#------------------------------------------------------------------------ +class FanChartDialog(Report.DrawReportDialog): + + def __init__(self,database,person): + Report.DrawReportDialog.__init__(self,database,person) + + def get_title(self): + """The window title for this dialog""" + return "%s - %s - GRAMPS" % (_("Fan Chart"),_("Graphical Reports")) + + def get_header(self, name): + """The header line at the top of the dialog contents.""" + return _("Fan Chart for %s") % name + + def get_target_browser_title(self): + """The title of the window created when the 'browse' button is + clicked in the 'Save As' frame.""" + return _("Save Fan Chart") + + def get_stylesheet_savefile(self): + """Where to save user defined styles for this report.""" + return "fan_chart.xml" + + def get_report_generations(self): + """Default to 10 generations, no page breaks.""" + return (0, 0) + + def make_default_style(self): + """Make the default output style for the Ancestor Chart report.""" + f = TextDoc.FontStyle() + f.set_size(8) + f.set_type_face(TextDoc.FONT_SANS_SERIF) + p = TextDoc.ParagraphStyle() + p.set_font(f) + p.set_alignment(TextDoc.PARA_ALIGN_CENTER) + self.default_style.add_style("Normal",p) + + f = TextDoc.FontStyle() + f.set_size(20) + f.set_bold(1) + f.set_type_face(TextDoc.FONT_SANS_SERIF) + p = TextDoc.ParagraphStyle() + p.set_font(f) + p.set_alignment(TextDoc.PARA_ALIGN_CENTER) + self.default_style.add_style("Title",p) + + def make_report(self): + """Create the object that will produce the Ancestor Chart. + All user dialog has already been handled and the output file + opened.""" + + try: + MyReport = FanChart(self.db, self.person, self.target_path,self.doc,"%n") + MyReport.write_report() + except Errors.FilterError, msg: + (m1,m2) = msg.messages() + ErrorDialog(m1,m2) + except: + import DisplayTrace + DisplayTrace.DisplayTrace() + +#------------------------------------------------------------------------ +# +# Entry point of the report. Takes the database and the active person +# as its arguments. +# +#------------------------------------------------------------------------ +def report(database,person): + FanChartDialog(database,person) + +#------------------------------------------------------------------------ +# +# Register the report with the plugin system. If this is not done, then +# GRAMPS will not know that the report exists. +# +#------------------------------------------------------------------------ +from Plugins import register_report + +register_report( + report, + _("Fan Chart"), + category=_("Graphical Reports"), + status=(_("Alpha")), + description=_("Produces a five generation fan chart") + ) +