2 # -*- coding: ISO-8859-15 -*-
5 # graphical user interface for pdf2swf
7 # Part of the swftools package.
9 # Copyright (c) 2008,2009 Matthias Kramm <kramm@quiss.org>
11 # This program is free software; you can redistribute it and/or modify
12 # it under the terms of the GNU General Public License as published by
13 # the Free Software Foundation; either version 2 of the License, or
14 # (at your option) any later version.
16 # This program is distributed in the hope that it will be useful,
17 # but WITHOUT ANY WARRANTY; without even the implied warranty of
18 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 # GNU General Public License for more details.
21 # You should have received a copy of the GNU General Public License
22 # along with this program; if not, write to the Free Software
23 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
29 sys.path+=["../lib/python"]
39 # gfx.setparameter("wxwindowparams", "1")
41 # gfx.setoption("wxwindowparams", "1")
45 self.simpleviewer_bitmap = wx.BitmapFromImage(wx.ImageFromData(images.simpleviewer_width,images.simpleviewer_height,images.simpleviewer_data))
46 self.raw_bitmap = wx.BitmapFromImage(wx.ImageFromData(images.raw_width,images.raw_height,images.raw_data))
47 self.motionpaper_bitmap = wx.BitmapFromImage(wx.ImageFromData(images.motionpaper_width,images.motionpaper_height,images.motionpaper_data))
48 self.rfxview_bitmap = wx.BitmapFromImage(wx.ImageFromData(images.rfxview_width,images.rfxview_height,images.rfxview_data))
51 HTMLTEMPLATE = """<html>
52 <body style="padding: 0px; margin: 0px">
53 <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
56 codebase="http://active.macromedia.com/flash5/cabs/swflash.cab#version=%(version)d,0,0,0">
57 <param name="MOVIE" value="%(swffilename)s">
58 <param name="PLAY" value="true">
59 <param name="LOOP" value="true">
60 <param name="QUALITY" value="high">
61 <param name="FLASHVARS" value="%(flashvars)s">
62 <embed src="%(swffilename)s" width="%(width)s" height="%(height)s"
63 play="true" ALIGN="" loop="true" quality="high"
64 type="application/x-shockwave-flash"
65 flashvars="%(flashvars)s"
66 pluginspage="http://www.macromedia.com/go/getflashplayer">
74 dlg = wx.MessageDialog(None, msg, "Error", style=wx.OK, pos=wx.DefaultPosition)
78 def savefilestatus(msg):
79 dlg = wx.MessageDialog(None, msg, "Save file status", style=wx.OK, pos=wx.DefaultPosition)
83 def swfcombine(params):
85 if os.path.sep == '/':
86 locations = [os.path.join(basedir, "swfcombine"),
87 "/usr/local/bin/swfcombine",
91 locations = [os.path.join(basedir, "swfcombine.exe"),
92 "c:\\swftools\\swfcombine.exe"]
93 params = ['"'+p+'"' for p in params]
100 if hasattr(os,"spawnv"):
101 print "spawnv",exe,params
104 ret = os.spawnv(os.P_WAIT, exe, ["swfcombine"]+params)
110 cmd = '"' + exe + '"' + " " + (" ".join(params))
114 error("Couldn't execute swfcombine.exe- error code "+str(ret))
118 EVENT_PAGE_CHANGE = 1
119 EVENT_FILE_CHANGE = 2
120 EVENT_STATUS_TEXT = 4
122 class ProgressFrame(wx.Dialog):
123 def __init__(self, parent, message=""):
124 wx.Dialog.__init__(self, parent, -1, "Progress", size=(350, 150))
125 panel = wx.Panel(self, -1)
128 self.msg = wx.StaticText(panel, -1, message, (20,25))
129 self.gauge = wx.Gauge(panel, -1, 100, (20, 50), (250, 25))
131 self.gauge.SetBezelFace(3)
132 self.gauge.SetShadowWidth(3)
134 self.Bind(wx.EVT_WINDOW_DESTROY, self.close, id=wx.ID_CLOSE)
136 def setProgress(self, num):
137 self.gauge.SetValue(int(num))
139 def close(self, event):
143 def swapextension(filename,newext):
144 basename,ext = os.path.splitext(filename)
145 return basename + "." + newext
147 def has_different_size_pages(doc):
149 for i in range(1,doc.pages+1):
150 page = doc.getPage(i)
152 width,height = page.width,page.height
154 if abs(width-page.width)>2 or \
155 abs(height-page.height)>2:
164 def __init__(self, parameter, text, options, default, mapping=None):
165 self.parameter = parameter
167 self.options = options
168 self.default = default
169 self.mapping = mapping
174 def generateControl(self, panel):
175 if type(self.options) == type((0,)):
176 control = wx.Choice(panel, -1, choices=self.options)
177 control.SetSelection(self.default)
178 elif self.options == "slider":
179 control = wx.Slider(panel, -1, self.default, 0, 100, size=(100, -1), style=wx.SL_HORIZONTAL|wx.SL_LABELS|wx.SL_TOP)
180 elif self.options == "spinner":
181 control = wx.SpinCtrl(panel, -1, str(self.default))
183 control = wx.Choice(panel, -1, choices=["broken"])
184 control.SetSelection(0)
186 self.control = control
189 def getSettings(self):
191 if type(self.options) == type((0,)):
192 value = self.options[self.control.GetCurrentSelection()]
193 if self.mapping and value in self.mapping:
194 value = str(self.mapping[value])
199 return {self.parameter:value}
200 elif self.options == "slider" or self.options == "spinner":
201 value = str(self.control.GetValue())
202 return {self.parameter:value}
208 class Option2(Option):
210 def __init__(self, parameter, text, options, default, mapping=None):
211 Option.__init__(self, parameter, text, options, default, mapping)
214 def generateControl(self, panel):
215 p = wx.Panel(panel, -1)
216 #p.SetOwnBackgroundColour('#ff0000')
217 h = wx.BoxSizer(wx.HORIZONTAL)
218 control = wx.Choice(p, -1, choices=self.options)
219 control.SetSelection(self.default)
220 text = wx.StaticText(p, -1, self.text)
221 h.Add(text,1,wx.EXPAND|wx.ALIGN_LEFT|wx.TOP, 5)
222 h.Add(control,1,wx.EXPAND|wx.ALIGN_RIGHT|wx.ALIGN_TOP)
223 self.control = control
235 self.control.Disable()
240 self.control.Enable()
242 def getSettings(self):
245 return Option.getSettings(self)
247 class ChooseAndText(Option):
248 def __init__(self, parameter, text, options, default, editselection, textvalue=""):
249 Option.__init__(self, parameter, text, options, default)
250 self.editselection = editselection
251 self.selection = default
252 self.textvalue = textvalue
256 def generateControl(self, panel):
257 p = wx.Panel(panel, -1)
258 h = wx.BoxSizer(wx.HORIZONTAL)
259 control = wx.Choice(p, -1, choices=self.options)
260 p.Bind(wx.EVT_CHOICE, self.OnChoice, control)
261 control.SetSelection(self.default)
262 text = wx.StaticText(p, -1, self.text)
263 if self.selection == self.editselection:
264 edittext = wx.TextCtrl(p, -1, self.textvalue)
267 edittext = wx.TextCtrl(p, -1, "")
269 p.Bind(wx.EVT_TEXT, self.OnText, edittext)
270 h.Add(text,1,wx.EXPAND|wx.ALIGN_LEFT|wx.TOP, 5)
271 h.Add(control,1,wx.EXPAND|wx.ALIGN_RIGHT)
272 h.Add(edittext,1,wx.EXPAND|wx.ALIGN_RIGHT)
273 self.choice = control
274 self.edittext = edittext
283 def OnText(self, event):
284 text = self.edittext.GetValue()
285 text2 = "".join(c for c in text if c.isdigit())
287 self.edittext.SetValue(text2)
289 def OnChoice(self, event):
290 self.selection = self.choice.GetCurrentSelection()
291 if self.selection != self.editselection:
292 if not self.textvalue and self.edittext.GetValue():
293 self.textvalue = self.edittext.GetValue()
294 self.edittext.SetValue("")
295 self.edittext.Disable()
297 if self.textvalue and not self.edittext.GetValue():
298 self.edittext.SetValue(self.textvalue)
300 self.edittext.Enable()
306 self.choice.Disable()
307 self.edittext.Disable()
314 if self.choice.GetCurrentSelection() == self.editselection:
315 if self.textvalue and not self.edittext.GetValue():
316 self.edittext.SetValue(self.textvalue)
318 self.edittext.Enable()
320 self.edittext.Disable()
322 def getSettings(self):
325 if self.choice.GetCurrentSelection() != self.editselection:
326 value = self.options[self.choice.GetCurrentSelection()]
328 value = self.edittext.GetValue().strip()
329 return {self.parameter:value}
332 def __init__(self, parameter, label, default=""):
333 self.parameter = parameter
335 self.default = default
338 def generateControl(self, panel):
339 v = wx.BoxSizer(wx.VERTICAL)
340 self.control = wx.TextCtrl(panel, -1, self.default, size=(250, -1))
344 def getSettings(self):
346 for items in self.control.GetValue().split(" "):
350 settings[l[0]] = l[1]
357 class RadioOption(Option):
358 def __init__(self, text, options):
360 self.options = options
361 self.selected = "==nothing=="
365 def generateControl(self, panel):
366 control = wx.Panel(panel, -1)
367 vsplit = wx.BoxSizer(wx.VERTICAL)
368 for i in range(len(self.options)/2):
369 text = self.options[i*2]
371 c = wx.RadioButton(control, -1, text, style=wx.RB_GROUP)
373 c = wx.RadioButton(control, -1, text)
374 control.Bind(wx.EVT_RADIOBUTTON, self.OnRadio, c)
377 control.SetSizer(vsplit)
379 self.control = control
382 def OnRadio(self, event):
383 self.selected = event.GetEventObject().GetLabel()
385 def getSettings(self):
386 for i in range(len(self.options)/2):
387 if self.options[i*2] == self.selected:
388 return self.options[i*2+1]
389 return self.options[1]
391 class BitmapWindow(wx.Window):
392 def __init__(self, parent, image):
393 wx.Window.__init__(self, parent, -1)
395 self.SetMinSize((image.GetWidth()+2, image.GetHeight()+2))
396 self.SetMaxSize((image.GetWidth()+2, image.GetHeight()+2))
397 self.SetSize((image.GetWidth()+2, image.GetHeight()+2))
398 self.Bind(wx.EVT_PAINT, self.OnPaint)
400 def OnPaint(self, event):
401 dc = wx.PaintDC(self)
403 def Draw(self,dc=None):
405 dc = wx.ClientDC(self)
406 dc.DrawRectangleRect((0, 0, self.image.GetWidth()+2, self.image.GetHeight()+2))
407 dc.DrawBitmap(self.image, 1, 1, False)
409 class ImageRadioOption(Option):
410 def __init__(self, text, options):
412 self.options = options
413 self.selected = "==nothing=="
418 def generateControl(self, panel):
419 control = wx.Panel(panel, -1)
420 vsplit = wx.BoxSizer(wx.VERTICAL)
422 for image,text,params,selected,extraoptions in self.options:
423 hsplit = wx.BoxSizer(wx.HORIZONTAL)
425 v = wx.BoxSizer(wx.VERTICAL)
427 name,text = text.split("- ")
429 c = wx.CheckBox(control, -1, name)
430 control.Bind(wx.EVT_CHECKBOX, self.OnRadio, c)
432 # radio buttons crash windows when clicked on- even without event bindings.
433 # This is caused by the subpanel which is created for extra options
434 # (I tried this with a empty Panel(), and even that crashed)
436 # c = wx.RadioButton(control, -1, name, style=wx.RB_GROUP)
438 # c = wx.RadioButton(control, -1, name)
439 #control.Bind(wx.EVT_RADIOBUTTON, self.OnRadio, c)
441 self.ids += [c.GetId()]
445 if "disable" in text:
448 self.selected = c.GetId()
454 bitmap = BitmapWindow(control, image)
455 t = wx.StaticText(control, -1, text, size=(400,50))
457 v.Add(c, 0, wx.EXPAND)
458 v.Add(t, 0, wx.EXPAND|wx.LEFT, 20)
460 for o in extraoptions:
461 cx = o.generateControl(control)
466 v.Add(cx, 0, wx.EXPAND|wx.LEFT, 20)
468 v.SetMinSize((330,170))
470 hsplit.Add(bitmap, 0, wx.LEFT|wx.RIGHT|wx.BOTTOM|wx.ALIGN_TOP, 5)
471 hsplit.Add(v, 0, wx.EXPAND)
472 vsplit.Add(hsplit, 0, wx.EXPAND)
474 control.SetSizer(vsplit)
476 self.control = control
479 def OnRadio(self, event):
480 self.selected = event.GetEventObject().GetId()
481 for c in self.radios:
482 if c.GetId() == self.selected:
487 for image,text,params,selected,extraoptions in self.options:
488 if self.ids[i] == self.selected:
489 for xo in extraoptions:
493 for xo in extraoptions:
497 event.ResumePropagation(0)
499 def getSettings(self):
501 for image,text,params,s,extraoptions in self.options:
504 if id == self.selected:
509 class OptionFrame(wx.Dialog):
511 def __init__(self, parent):
512 wx.Dialog.__init__(self, parent, -1, "Options")
514 #self.nb = wx.Notebook(self, -1)#, wx.Point(0,0), wx.Size(0,0), wxNB_FIXEDWIDTH)
515 self.nb = wx.Notebook(self, -1)
519 options0 = [RadioOption('Rendering mode',
520 ["Convert polygons to polygons and fonts to fonts", {},
521 "Convert fonts to fonts, everything else to bitmaps", {"poly2bitmap":"1"},
522 "Convert everthing to bitmaps", {"poly2bitmap":"1", "bitmapfonts":"1"}
526 sv_options = [Option2('flashversion', 'Flash version:', ('4','5','6','7','8'), 2),
527 Option2('transparent', 'Make SWF file transparent:', ('no','yes'), 0),
530 raw_options = [Option2('flashversion', 'Flash version:', ('4','5','6','7','8','9'), 2),
531 Option2('insertstop', 'Insert stop after each frame:', ('no','yes'), 0),
532 Option2('transparent', 'Make SWF file transparent:', ('no','yes'), 0),
534 rfxview_options = [ChooseAndText('rfxwidth', 'Width:', ('same as PDF','fullscreen','custom'),1,2,"600"),
535 ChooseAndText('rfxheight', 'Height:', ('same as PDF','fullscreen','custom'),1,2,"800"),
536 Option2('rfxzoomtype', 'Initial zoom level:', ('Original resolution','Show all','Maximum width/height'),2),
539 options4 = [ImageRadioOption('Select Paging GUI',
540 [(staticdata.raw_bitmap, "No Viewer- The SWF will be in \"raw\" format, with each page a seperate frame. Use this if you want to add a viewer yourself afterwards.", {}, 0, raw_options),
541 (staticdata.simpleviewer_bitmap, "SimpleViewer- A tiny viewer, which attaches directly to the SWF, and provides small previous/next buttons in the upper left corner", {"simpleviewer":"1", "insertstop":"1"}, 0, sv_options),
542 (staticdata.rfxview_bitmap, "rfxView- A more sophisticated viewer with zooming and scrolling.", {"rfxview":"1", "flashversion":"8"}, 1, rfxview_options),
543 #(staticdata.motionpaper_bitmap, "MotionPaper- A highly sophisticated viewer with page flipping. (disabled in this evaluation version)", {}, 0, mp_options),
544 #(staticdata.motionpaper_bitmap, "Your advertisement here- Are you are company who developed a viewer for pdf2swf, or who offers commercial PDF hosting service? Place your advertisement or demo viewer here, or allow pdf2swf to upload SWFs directly to your site! contact sales@swftools.org for details.", {}, 0, mp_options),
547 options1 = [Option('zoom', 'Resolution (in dpi):', "spinner", 72),
548 Option('fontquality', 'Font quality:', "slider", 20),
549 Option('storeallcharacters', 'Insert full fonts in SWF file:', ('no','yes'), 0),
550 Option('splinequality', 'Polygon quality:', "slider", 100),
551 Option('jpegquality', 'JPEG quality:', "slider", 75),
552 Option('jpegsubpixels', 'JPEG image resolution:', ('same as in PDF', '1x', '2x', '4x'), 0, {"same as in PDF": 0, "1x": 1, "2x": 2, "3x": 3}),
553 Option('ppmsubpixels', 'non-JPEG image resolution:', ('same as in PDF', '1x', '2x', '4x'), 0, {"same as in PDF": 0, "1x": 1, "2x": 2, "3x": 3}),
557 options3 = [TextOption('_additional_', 'Additional options')]
559 panel1 = [('Rendering options', options0,''),
560 ('Quality',options1,'v')]
561 panel3 = [('Select paging GUI', options4,'')]
562 panel4 = [('Additional options', options3,'')]
564 panels = [('Quality', panel1),
566 ('Advanced', panel4)]
568 for name,poptions in panels:
569 panel = wx.Panel(self.nb, -1)
570 self.nb.AddPage(panel, name)
572 vsplit = wx.BoxSizer(wx.VERTICAL)
574 for name,options,align in poptions:
575 optiongroup = wx.StaticBox(panel, -1, name)
576 optiongroupsizer= wx.StaticBoxSizer(optiongroup, wx.VERTICAL)
577 optiongroup.SetSizer(optiongroupsizer)
580 grid = wx.GridSizer(rows=len(options), cols=2, hgap=3, vgap=3)
581 optiongroupsizer.Add(grid, 1, wx.EXPAND, 0)
583 grid = wx.GridSizer(rows=len(options), cols=1, hgap=3, vgap=3)
584 optiongroupsizer.Add(grid, 1, wx.EXPAND, 0)
586 for option in options:
588 t = wx.StaticText(panel, -1, option.text)
589 grid.Add(t, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT)
590 optionbox = option.generateControl(panel)
591 grid.Add(optionbox, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT)
593 vsplit.Add(optiongroupsizer, 0, wx.EXPAND, 0)
595 #hs = wx.BoxSizer(wx.HORIZONTAL)
596 #hs.Add(gobutton, 0, wx.ALIGN_CENTER, 0)
597 gobutton = wx.Button(panel, -1, "Apply")
598 self.Bind(wx.EVT_BUTTON, self.Apply, gobutton)
600 vsplit.Add(gobutton, 0, wx.ALIGN_CENTER|wx.ALL, 0)
602 panel.SetSizer(vsplit)
610 def updateOptions(self):
611 global options,gfx_options
614 # FIXME: we clear *our* options- but gfx will still have
615 # stored the old ones. Critical for options in the "imageradio" section.
618 print "----- options ------"
619 for option in options:
620 for k,v in option.getSettings().items():
622 gfx.setparameter(k,v)
626 # TODO: filter out "global" options, and do this only if
627 # pdf layer is affected
629 def Apply(self, event):
640 self.pagebitmap = None
641 self.bitmap_width = 0
642 self.bitmap_height = 0
645 self.status_text = None
646 self.lastsavefile = "output.swf"
647 self.lasthtmlfile = "index.html"
651 def onEvent(self,event_type, function):
652 self.listeners += [(event_type,function)]
653 def loadPDF(self,filename):
654 self.filename = filename
655 self.lastsavefile = swapextension(filename,"swf")
656 self.lasthtmlfile = swapextension(filename,"html")
658 self.pdf = gfx.open("pdf",filename)
659 if(has_different_size_pages(self.pdf)):
660 # just let the user know- for now, we can't handle this properly
661 dlg = wx.MessageDialog(app.frame, """In this PDF, width or height are not the same for each page. This might cause problems if you export pages of different dimensions into the same SWF file.""", "Notice", style=wx.OK, pos=wx.DefaultPosition)
667 for type,f in self.listeners:
668 if type&EVENT_PAGE_CHANGE or type&EVENT_FILE_CHANGE:
670 self.setStatus("File loaded successfully.")
672 def saveSWF(self, filename, progress, pages=None, html=0):
674 basename,ext = os.path.splitext(filename)
676 html = basename + ".html"
677 filename = basename + ".swf"
678 elif ext.lower() != ".swf":
680 filename = basename + ".swf"
682 html = basename + ".html"
685 steps = 100.0 / (self.pdf.pages*2 + 3)
688 self.lastsavefile = filename
690 self.lasthtmlfile = html
693 for k,v in gfx_options.items():
694 swf.setparameter(k,v)
696 pages = range(1,self.pdf.pages+1)
697 pdfwidth,pdfheight=0,0
699 page = self.pdf.getPage(pagenr)
700 pdfwidth = page.width
701 pdfheight = page.height
702 swf.startpage(page.width, page.height)
706 if not os.path.isfile(filename):
707 error("Couldn't create file "+filename)
709 if gfx_options.get("rfxview",None):
710 rfxview = os.path.join(basedir, "rfxview.swf")
711 if not os.path.isfile(rfxview):
712 error("File rfxview.swf not found in working directory")
714 size1 = os.stat(filename)[stat.ST_SIZE]
715 swfcombine([rfxview,"viewport="+filename,"-o",filename])
716 size2 = os.stat(filename)[stat.ST_SIZE]
718 error("Couldn't add viewer to file "+filename)
721 version = int(gfx_options.get("flashversion", "8"))
722 swf = gfx.open("swf", filename)
723 page1 = swf.getPage(1)
725 width,height = str(page1.width),str(page1.height)
728 w = gfx_options.get("rfxwidth","")
729 if w == "fullscreen": width = "100%"
730 elif w == "same as PDF": width = pdfwidth+40
731 elif w.isdigit(): width = w
732 else: width = pdfwidth
734 h = gfx_options.get("rfxheight","")
735 if h == "fullscreen": height = "100%"
736 elif h == "same as PDF": height = pdfheight+70
737 elif h.isdigit(): height = h
738 else: height = pdfwidth
741 zoomtype = gfx_options.get("rfxzoomtype","")
742 if zoomtype=="Original resolution":
743 flashvars = "zoomtype=1"
744 elif zoomtype=="Show all":
745 flashvars = "zoomtype=2"
746 elif zoomtype=="Maximum width/height":
747 flashvars = "zoomtype=3"
749 swffilename = os.path.basename(filename)
750 fi = open(html, "wb")
751 fi.write(HTMLTEMPLATE % locals())
755 def changePage(self,page):
757 self.page = self.pdf.getPage(self.pagenr)
758 for type,f in self.listeners:
759 if type&EVENT_PAGE_CHANGE:
762 def getPageIcon(self,pagenr):
763 page = self.pdf.getPage(pagenr)
764 return wx.BitmapFromImage(wx.ImageFromData(ICON_SIZE,ICON_SIZE,page.asImage(ICON_SIZE,ICON_SIZE)))
765 #return wx.BitmapFromImage(wx.ImageFromData(8,8,"0"*(64*3)))
767 def getPageImage(self, width, height):
768 if self.bitmap_width == width and self.bitmap_height == height and self.bitmap_page == self.pagenr:
769 return self.pagebitmap
771 self.bitmap_width = width
772 self.bitmap_height = height
773 self.bitmap_page = self.pagenr
774 self.pagebitmap = wx.BitmapFromImage(wx.ImageFromData(width,height,self.page.asImage(width,height)))
775 #self.pagebitmap = wx.BitmapFromImage(wx.ImageFromData(8,8,"0"*(64*3)))
776 return self.pagebitmap
778 def setStatus(self,text):
779 self.status_text = text
780 for type,f in self.listeners:
781 if type&EVENT_STATUS_TEXT:
786 class PageListWidget(wx.ListCtrl):
787 def __init__(self,parent):
788 wx.ListCtrl.__init__(self,parent,style=wx.LC_ICON|wx.LC_AUTOARRANGE)
789 #self.SetMinSize((ICON_SIZE+8,-1))
790 #self.SetMaxSize((ICON_SIZE+8,-1))
791 #self.SetSize((ICON_SIZE+8,-1))
792 self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.SelectItem)
793 state.onEvent(EVENT_FILE_CHANGE, self.reload)
794 state.onEvent(EVENT_PAGE_CHANGE, self.switchPage)
797 #self.Bind(wx.EVT_IDLE, self.OnIdle)
800 def processFiles(self):
801 if self.filepos >= 0 and self.filepos < state.pdf.pages:
802 icon = state.getPageIcon(self.filepos+1)
803 self.imglist.Add(icon)
804 self.InsertImageStringItem(self.filepos, str(self.filepos+1), self.filepos)
805 self.filepos = self.filepos + 1
808 def OnIdle(self,event):
810 event.ResumePropagation(0)
814 self.DeleteAllItems()
815 self.imglist = wx.ImageList(ICON_SIZE,ICON_SIZE,mask=False)
816 self.AssignImageList(self.imglist,wx.IMAGE_LIST_NORMAL)
818 while state.pdf and self.filepos < state.pdf.pages:
821 def switchPage(self):
825 for i in range(0,self.GetItemCount()):
826 self.Select(i, False)
827 self.Select(state.pagenr-1, True)
828 self.Focus(state.pagenr-1)
831 def SelectItem(self,event):
832 self.dontcare = 1 #ignore next change event
833 state.changePage(event.GetIndex()+1)
837 This is the SWF preview window.
838 Here, you will see how the SWF file generated from
839 the PDF file will look like. Changing parameters in
840 the configuration which affect the appeareance of
841 the final SWF will affect this preview, too, so you
842 can always evaluate the final output beforehand.
846 class OnePageWidget(wx.Window):
847 def __init__(self,parent):
848 wx.Window.__init__(self, parent)
849 self.SetSize((160,100))
850 self.SetMinSize((160,100))
852 self.Bind(wx.EVT_PAINT, self.OnPaint)
853 self.Bind(wx.EVT_SIZE, self.OnSize)
854 self.Bind(wx.EVT_KEY_DOWN, self.key_down)
855 state.onEvent(EVENT_PAGE_CHANGE, self.OnPageChange)
857 def key_down(self, event):
859 if event.GetKeyCode() == 312 and state.pagenr>1:
860 state.changePage(state.pagenr-1)
861 elif event.GetKeyCode() == 313 and state.pagenr<state.pdf.pages:
862 state.changePage(state.pagenr+1)
864 def OnPageChange(self):
867 def OnSize(self, event):
870 def Draw(self,dc=None):
873 dc = wx.ClientDC(self)
876 window_width,window_height = self.GetSize()
879 if not state.pdf or not state.page:
882 if state.page.width * window_height > state.page.height * window_width:
884 height = window_width * state.page.height / state.page.width
885 posy = (window_height - height) / 2
887 width = window_height * state.page.width / state.page.height
888 height = window_height
889 posx = (window_width - width) / 2
891 dc.DrawBitmap(state.getPageImage(width,height), posx,posy, False)
894 def OnPaint(self, event):
895 dc = wx.PaintDC(self)
898 class Pdf2swfFrame(wx.Frame):
900 #wx.Window.__init__(self, None, id=-1, pos=wx.DefaultPosition, size=wx.DefaultSize)
901 def __init__(self,application):
902 wx.Frame.__init__(self, None, -1, style = wx.DEFAULT_FRAME_STYLE)
903 self.application = application
905 self.SetTitle("pdf2swf")
908 self.createStatusBar()
909 self.createMainFrame()
911 self.SetSize((800,600))
913 self.options = OptionFrame(None)
914 self.options.Show(False)
915 self.options.updateOptions()
917 state.onEvent(EVENT_STATUS_TEXT, self.status_change)
920 #self.table = wx.AcceleratorTable([(wx.ACCEL_ALT, ord('X'), 333),])
921 #self.SetAcceleratorTable(self.table)
923 self.Bind(wx.EVT_IDLE, self.OnIdle)
924 self.Bind(wx.EVT_CLOSE, self.menu_exit)
927 def menu_open(self,event):
930 dlg = wx.FileDialog(self, "Choose PDF File:", style = wx.DD_DEFAULT_STYLE, defaultFile = state.filename, wildcard = "PDF files (*.pdf)|*.pdf|all files (*.*)|*.*")
932 dlg = wx.FileDialog(self, "Choose PDF File:", style = wx.DD_DEFAULT_STYLE, wildcard = "PDF files (*.pdf)|*.pdf|all files (*.*)|*.*")
934 if dlg.ShowModal() == wx.ID_OK:
935 self.filename = dlg.GetFilename()
936 state.loadPDF(self.filename)
938 def menu_save(self,event,pages=None):
939 html,self.html = self.html,0
945 defaultFile = state.lastsavefile
947 defaultFile = state.lasthtmlfile
948 dlg = wx.FileDialog(self, "Choose Save Filename:", style = wx.SAVE | wx.OVERWRITE_PROMPT, defaultFile = defaultFile, wildcard = "all files (*.*)|*.*|SWF files (*.swf)|*.swf|HTML template (*.html)|*.html")
950 if dlg.ShowModal() == wx.ID_OK:
951 filename = os.path.join(dlg.GetDirectory(),dlg.GetFilename())
953 #progress = ProgressFrame(self, "Saving %s File '%s'..." % (html and "HTML" or "SWF", filename))
956 state.saveSWF(filename, progress, pages, html)
959 def menu_save_selected(self,event):
963 for i in range(0,self.pagelist.GetItemCount()):
964 if self.pagelist.IsSelected(i):
966 self.menu_save(event, pages=p)
968 def menu_save_html(self,event):
970 return self.menu_save(event)
972 def menu_save_selected_html(self,event):
974 return self.menu_save_selected(event)
976 def menu_exit(self,event):
977 self.application.Exit()
979 def menu_selectall(self,event):
980 for i in range(0,self.pagelist.GetItemCount()):
981 self.pagelist.Select(i, True)
982 def menu_options(self,event):
983 self.options.Show(True)
985 def status_change(self):
986 self.statusbar.SetStatusText(state.status_text)
988 def OnIdle(self,event):
989 if self.options.needreload:
990 self.options.needreload = 0
993 state.loadPDF(state.filename)
995 def createMenu(self):
996 menubar = wx.MenuBar()
998 menu = wx.Menu();menubar.Append(menu, "&File")
999 menu.Append(wx.ID_OPEN, "Open PDF\tCTRL-O");self.Bind(wx.EVT_MENU, self.menu_open, id=wx.ID_OPEN)
1000 menu.AppendSeparator()
1001 menu.Append(wx.ID_SAVE, "Save SWF (all pages)\tCTRL-W");self.Bind(wx.EVT_MENU, self.menu_save, id=wx.ID_SAVE)
1002 menu.Append(wx.ID_SAVEAS, "Save SWF (selected pages)\tCTRL-S");self.Bind(wx.EVT_MENU, self.menu_save_selected, id=wx.ID_SAVEAS)
1003 menu.AppendSeparator()
1004 menu.Append(2001, "Save HTML template (all pages)\tCTRL-H");self.Bind(wx.EVT_MENU, self.menu_save_html, id=2001)
1005 menu.Append(2002, "Save HTML template (selected pages)");self.Bind(wx.EVT_MENU, self.menu_save_selected_html, id=2002)
1006 menu.AppendSeparator()
1007 menu.Append(wx.ID_EXIT, "Exit\tCTRL-Q");self.Bind(wx.EVT_MENU, self.menu_exit, id=wx.ID_EXIT)
1009 menu = wx.Menu();menubar.Append(menu, "&Edit")
1010 menu.Append(wx.ID_SELECTALL, "Select All\tCTRL-A");self.Bind(wx.EVT_MENU, self.menu_selectall, id=wx.ID_SELECTALL)
1011 menu.AppendSeparator()
1012 menu.Append(wx.ID_PREFERENCES, "Options\tCTRL-R");self.Bind(wx.EVT_MENU, self.menu_options, id=wx.ID_PREFERENCES)
1014 menu = wx.Menu();menubar.Append(menu, "&Help")
1016 self.SetMenuBar(menubar)
1019 def createToolbar(self):
1022 self.toolbar = self.CreateToolBar(wx.TB_HORIZONTAL | wx.NO_BORDER | wx.TB_FLAT)
1024 self.toolbar.AddSimpleTool(wx.ID_OPEN,
1025 wx.ArtProvider.GetBitmap(wx.ART_FILE_OPEN, wx.ART_TOOLBAR, tsize),
1027 self.toolbar.AddSimpleTool(wx.ID_SAVE,
1028 wx.ArtProvider.GetBitmap(wx.ART_FILE_SAVE, wx.ART_TOOLBAR, tsize),
1029 "Save selected pages")
1030 self.toolbar.AddSimpleTool(wx.ID_PREFERENCES,
1031 wx.ArtProvider.GetBitmap(wx.ART_LIST_VIEW, wx.ART_TOOLBAR, tsize),
1033 #self.toolbar.AddSeparator()
1034 self.toolbar.Realize()
1036 def createStatusBar(self):
1037 self.statusbar = self.CreateStatusBar(1)
1039 def createMainFrame(self):
1042 self.pagelist = PageListWidget(self)
1043 self.onepage = OnePageWidget(self)
1044 hsplit = wx.BoxSizer(wx.HORIZONTAL)
1045 pagelistbox = wx.StaticBox(self, -1, "Pages")
1046 pagelistboxsizer= wx.StaticBoxSizer(pagelistbox, wx.VERTICAL)
1047 pagelistboxsizer.Add(self.pagelist, proportion=1, flag=wx.EXPAND)
1048 onepagebox = wx.StaticBox(self, -1, "Page 1")
1049 onepageboxsizer= wx.StaticBoxSizer(onepagebox, wx.VERTICAL)
1050 onepageboxsizer.Add(self.onepage, proportion=1, flag=wx.EXPAND)
1051 hsplit.Add(pagelistboxsizer, 0, wx.EXPAND, 0)
1052 hsplit.Add(onepageboxsizer, 1, wx.EXPAND, 0)
1053 self.SetAutoLayout(True)
1054 self.SetSizer(hsplit)
1056 hsplit.SetSizeHints(self)
1058 hsplit = wx.SplitterWindow(self, style=wx.SP_3D|wx.SP_LIVE_UPDATE)
1059 #p1 = wx.Panel(hsplit,-1, style=wx.SUNKEN_BORDER)
1060 #p2 = wx.Panel(hsplit,-1, style=wx.SUNKEN_BORDER)
1061 self.pagelist = PageListWidget(hsplit)
1062 self.onepage = OnePageWidget(hsplit)
1063 #hsplit.SplitVertically(p1,p2, sashPosition=64)
1064 hsplit.SplitVertically(self.pagelist, self.onepage, sashPosition=ICON_SIZE*3/2)
1065 hsplit.SetMinimumPaneSize(10)
1067 class MyApp(wx.App):
1069 wx.App.__init__(self, redirect=False, filename=None, useBestVisual=False)
1071 #state.loadPDF("sitis2007.pdf")
1072 #state.loadPDF("wxPython-Advanced-OSCON2004.pdf")
1074 staticdata = StaticData()
1076 self.frame = Pdf2swfFrame(self)
1077 self.SetTopWindow(self.frame)
1078 self.frame.Show(True)
1080 #self.frame = TestFrame(self)
1081 #self.frame.Show(True)