2 # -*- coding: UTF-8 -*-
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 */
25 from __future__ import division
28 from wx.lib.pubsub import Publisher
29 from lib.embeddedimage import PyEmbeddedImage
32 import lib.images as images
36 ID_INVERT_SELECTION = wx.NewId()
37 ID_SELECT_ODD = wx.NewId()
38 ID_SELECT_EVEN = wx.NewId()
39 ID_ONE_PAGE_PER_FILE = wx.NewId()
41 ID_DOC_INFO = wx.NewId()
42 ID_PREVIEW_TYPE = wx.NewId()
45 class _AppendThumbnailThread:
46 def __init__(self, win, thumbs):
48 self.__thumbs = thumbs
51 self.__keep_running = self.running = True
52 thread.start_new_thread(self.Run, ())
58 self.__keep_running = False
61 thumbs = self.__thumbs
62 different_sizes = False
63 for pos, thumb in enumerate(thumbs):
65 width, height = thumb.width, thumb.height
67 if not different_sizes:
68 if abs(width - thumb.width) > 2 or \
69 abs(height - thumb.height) > 2:
70 different_sizes = True
71 wx.CallAfter(Publisher.sendMessage, "DIFF_SIZES")
73 wx.CallAfter(self.__win.AppendThumbnail, pos,
74 thumb.asImage(ICON_SIZE, ICON_SIZE), thumb)
75 wx.CallAfter(Publisher.sendMessage, "THUMBNAIL_ADDED",
78 if not self.__keep_running:
81 wx.CallAfter(Publisher.sendMessage, "THUMBNAIL_DONE")
86 class FileDropTarget(wx.FileDropTarget):
87 def __init__(self, window):
88 wx.FileDropTarget.__init__(self)
91 def OnDropFiles(self, x, y, filenames):
92 if len(filenames) == 1:
93 Publisher.sendMessage("FILE_DROPED",
94 {'filename': filenames[0]}
97 Publisher.sendMessage("FILES_DROPED",
98 {'filenames': filenames}
101 class PagePreviewWindow(wx.ScrolledWindow):
102 def __init__(self, parent):
103 wx.ScrolledWindow.__init__(self, parent)
104 self.SetBackgroundColour('grey')
105 self.SetScrollRate(20, 20)
107 self.__buffer = wx.EmptyBitmap(1, 1)
109 self.Bind(wx.EVT_PAINT, self.__OnPaint)
111 def DisplayPage(self, page):
112 thread.start_new_thread(self.__DisplayPageThread, (page,))
115 self.__buffer = wx.EmptyBitmap(1, 1)
118 def __OnPaint(self, event):
119 dc = wx.BufferedPaintDC(self, self.__buffer, wx.BUFFER_VIRTUAL_AREA)
121 def __DisplayPage(self, w, h, page):
122 self.SetVirtualSize((w, h))
123 self.__buffer = wx.EmptyBitmap(w+2, h+2)
124 dc = wx.BufferedDC(None, self.__buffer)
126 dc.DrawRectangle(0, 0, w+2, h+2)
127 #dc.DrawBitmap(wx.BitmapFromBuffer(w, h, page), 1, 1, True)
128 dc.DrawBitmap(wx.BitmapFromImage(
129 wx.ImageFromData(w, h, page)), 1, 1, True)
133 def __DisplayPageThread(self, page):
137 page = page["page"].asImage(w, h)
138 wx.CallAfter(self.__DisplayPage, w, h, page)
141 class PageListCtrl(wx.ListView):
142 def __init__(self, parent):
143 wx.ListView.__init__(self, parent, style=wx.LC_ICON)
144 self.Bind(wx.EVT_CONTEXT_MENU, self.OnContextMenu)
146 def OnContextMenu(self, event):
147 if self.GetItemCount():
149 menu.Append(wx.ID_SELECTALL, u"Select All\tCTRL-A")
150 menu.AppendSeparator()
151 menu.Append(wx.ID_SAVE, u"Save SWF (all pages)\tCTRL-W")
152 menu.Append(wx.ID_SAVEAS, u"Save SWF (selected pages)\tCTRL-S")
156 def DisplayEmptyThumbnails(self, pages):
157 self.DeleteAllItems()
158 self.imglist = wx.ImageList(ICON_SIZE, ICON_SIZE, mask=True)
159 self.AssignImageList(self.imglist, wx.IMAGE_LIST_NORMAL)
160 bmp = images.getblankBitmap()
161 for pos in range(pages):
162 self.imglist.Add(bmp)
163 self.InsertImageStringItem(pos, u"Page %s" % (pos+1), pos)
165 def DisplayThumbnails(self, thumbs):
166 t = _AppendThumbnailThread(self, thumbs)
170 def AppendThumbnail(self, pos, thumb, page):
171 #bmp = wx.BitmapFromBuffer(ICON_SIZE, ICON_SIZE, thumb)
172 bmp = wx.BitmapFromImage(
173 wx.ImageFromData(ICON_SIZE, ICON_SIZE,
175 self.imglist.Replace(pos, bmp)
176 self.SetItemText(pos, u"Page %s\n(%sx%s)" % (pos+1,
177 page.width, page.height))
179 wx.CallAfter(self.Select, 0)
180 self.RefreshItem(pos)
183 class StatusBar(wx.StatusBar):
184 def __init__(self, parent):
185 wx.StatusBar.__init__(self, parent, -1)
187 self.sizeChanged = False
188 self.Bind(wx.EVT_SIZE, self.OnSize)
189 self.Bind(wx.EVT_IDLE, self.OnIdle)
191 self.gauge = wx.Gauge(self)
193 bmp = images.getstopBitmap()
194 self.btn_cancel = wx.BitmapButton(self, bitmap=bmp,
195 style = wx.NO_BORDER)
197 self.btn_cancel.Hide()
201 def SetGaugeValue(self, value):
204 self.btn_cancel.Hide()
205 self.gauge.SetValue(value)
207 def SetGaugeRange(self, pages):
209 self.btn_cancel.Show()
210 self.gauge.SetRange(pages)
212 def OnSize(self, evt):
214 self.sizeChanged = True
216 def OnIdle(self, evt):
220 def Reposition(self):
221 rect = self.GetFieldRect(0)
222 of = rect.width // 1.5
223 self.gauge.SetPosition((rect.x+of , rect.y+2))
224 self.gauge.SetSize((rect.width-of-24, rect.height-4))
225 self.btn_cancel.SetPosition((rect.width-22, rect.y+1))
226 self.btn_cancel.SetSize((22, rect.height-2))
227 self.sizeChanged = False
230 class PdfFrame(wx.Frame):
232 wx.Frame.__init__(self, None, size=(750,550), title=u"gpdf2swf")
234 icon = self.__MakeIcon()
237 self.__CreateToolbar()
238 self.statusbar = StatusBar(self)
239 self.SetStatusBar(self.statusbar)
241 dt = FileDropTarget(self)
242 self.SetDropTarget(dt)
244 hsplit = wx.SplitterWindow(self, style=wx.SP_3D|wx.SP_LIVE_UPDATE)
245 self.page_list = PageListCtrl(hsplit)
246 self.page_preview = PagePreviewWindow(hsplit)
247 hsplit.SplitVertically(self.page_list, self.page_preview,
248 sashPosition=ICON_SIZE*2)
249 hsplit.SetMinimumPaneSize(ICON_SIZE*2)
251 def __MakeIcon(self):
252 img = images.getgpdf2swfImage()
253 if "wxMSW" in wx.PlatformInfo:
254 img = img.Scale(16, 16)
255 #elif "wxGTK" in wx.PlatformInfo:
256 # img = img.Scale(22, 22)
257 # wxMac and wxGTK???? can be any size up to 128x128,
258 # so leave the source img alone....
259 icon = wx.IconFromBitmap(img.ConvertToBitmap())
262 def __CreateMenu(self):
263 menubar = wx.MenuBar()
265 menu_recent = wx.Menu()
266 menu_save = wx.Menu()
267 menu_save.AppendCheckItem(ID_ONE_PAGE_PER_FILE, u"One Page Per File")
268 menu_save.AppendSeparator()
269 menu_save.Append(wx.ID_SAVE, u"All Pages\tCTRL-W",
271 menu_save.Append(wx.ID_SAVEAS, u"Selected Pages\tCTRL-S",
272 u"Save selected pages")
275 menu.Append(wx.ID_OPEN, u"Open PDF\tCTRL-O", u"Open a PDF document")
276 menu.AppendMenu(wx.ID_ANY, u"Save SWF", menu_save)
277 menu.AppendSeparator()
278 menu.AppendMenu(wx.ID_ANY, u"Recent", menu_recent)
279 menu.AppendSeparator()
280 menu.Append(wx.ID_EXIT, u"Exit\tCTRL-Q")
281 menubar.Append(menu, u"&File")
283 self.filehistory = wx.FileHistory()
284 self.filehistory.UseMenu(menu_recent)
287 menu.Append(wx.ID_SELECTALL, u"Select All\tCTRL-A",
289 menu.Append(ID_INVERT_SELECTION, u"Invert Selection",
290 u"Invert current selection")
291 menu.Append(ID_SELECT_ODD, u"Select Odd",
293 menu.Append(ID_SELECT_EVEN, u"Select Even",
294 u"Select even pages")
295 menu.AppendSeparator()
296 menu.Append(wx.ID_PREFERENCES, u"Options\tCTRL-R",
297 u"Show options dialog")
298 menubar.Append(menu, u"&Edit")
301 menu.Append(wx.ID_ZOOM_IN, u"Zoom In\tCTRL-+")
302 menu.Append(wx.ID_ZOOM_OUT, u"Zoom Out\tCTRL--")
303 menu.Append(wx.ID_ZOOM_100, u"Normal Size\tCTRL-0")
304 menu.Append(wx.ID_ZOOM_FIT, u"Fit\tCTRL-1")
305 menu.AppendSeparator()
306 menu.Append(ID_DOC_INFO, u"Document Info\tCTRL-I")
307 menubar.Append(menu, u"&View")
310 menu.Append(wx.ID_ABOUT, u"About")
311 menubar.Append(menu, u"&Help")
312 self.SetMenuBar(menubar)
314 def __CreateToolbar(self):
316 wxart = wx.ArtProvider.GetBitmap
317 self.toolbar = self.CreateToolBar(wx.TB_HORIZONTAL |
318 wx.NO_BORDER | wx.TB_FLAT)
319 self.toolbar.AddSimpleTool(wx.ID_OPEN,
320 wxart(wx.ART_FILE_OPEN,
321 wx.ART_TOOLBAR, tsize),
323 self.toolbar.AddSimpleTool(wx.ID_SAVE,
324 wxart(wx.ART_FILE_SAVE,
325 wx.ART_TOOLBAR, tsize),
326 u"Save SWF (all pages)")
327 self.toolbar.AddSeparator()
329 self.toolbar.AddSimpleTool(wx.ID_PREFERENCES,
330 wxart(wx.ART_LIST_VIEW,
331 wx.ART_TOOLBAR, tsize),
333 self.toolbar.AddSeparator()
335 self.toolbar.AddSimpleTool(ID_DOC_INFO,
337 wx.ART_TOOLBAR, tsize),
340 self.toolbar.AddSeparator()
342 self.toolbar_preview_type = wx.Choice(
343 self.toolbar, ID_PREVIEW_TYPE,
344 choices=["everything to bitmaps",
345 "fonts to fonts, everything else to bitmaps",
346 "polygons to polygons and fonts to fonts"],
347 size=(350,-1), style=wx.CB_DROPDOWN
349 # I'm not sure about the utility of this, so Show False
350 self.toolbar_preview_type.Show(False)
351 self.toolbar.AddControl(self.toolbar_preview_type)
353 self.toolbar.Realize()