[GRASS-SVN] r53611 - grass-addons/grass7/gui/wxpython/wx.animation/animation
svn_grass at osgeo.org
svn_grass at osgeo.org
Mon Oct 29 14:48:12 PDT 2012
Author: annakrat
Date: 2012-10-29 14:48:11 -0700 (Mon, 29 Oct 2012)
New Revision: 53611
Modified:
grass-addons/grass7/gui/wxpython/wx.animation/animation/animation.py
grass-addons/grass7/gui/wxpython/wx.animation/animation/controller.py
grass-addons/grass7/gui/wxpython/wx.animation/animation/dialogs.py
grass-addons/grass7/gui/wxpython/wx.animation/animation/frame.py
grass-addons/grass7/gui/wxpython/wx.animation/animation/mapwindow.py
grass-addons/grass7/gui/wxpython/wx.animation/animation/toolbars.py
grass-addons/grass7/gui/wxpython/wx.animation/animation/utils.py
Log:
wx.animation: export animation to image sequence added
Modified: grass-addons/grass7/gui/wxpython/wx.animation/animation/animation.py
===================================================================
--- grass-addons/grass7/gui/wxpython/wx.animation/animation/animation.py 2012-10-29 17:52:19 UTC (rev 53610)
+++ grass-addons/grass7/gui/wxpython/wx.animation/animation/animation.py 2012-10-29 21:48:11 UTC (rev 53611)
@@ -48,6 +48,10 @@
"""
self.frames = frames
+ def GetFrame(self, index):
+ """!Returns animation frame"""
+ return self.frames[index]
+
def GetCount(self):
"""!Get frame count."""
return len(self.frames)
Modified: grass-addons/grass7/gui/wxpython/wx.animation/animation/controller.py
===================================================================
--- grass-addons/grass7/gui/wxpython/wx.animation/animation/controller.py 2012-10-29 17:52:19 UTC (rev 53610)
+++ grass-addons/grass7/gui/wxpython/wx.animation/animation/controller.py 2012-10-29 21:48:11 UTC (rev 53611)
@@ -13,14 +13,15 @@
@author Anna Kratochvilova <kratochanna gmail.com>
"""
+import os
import wx
from core.gcmd import GException, GError, GMessage
import grass.script as grass
from temporal_manager import TemporalManager
-from dialogs import InputDialog, EditDialog, AnimationData
-from utils import TemporalMode, Orientation
+from dialogs import InputDialog, EditDialog, AnimationData, ExportDialog
+from utils import TemporalMode, Orientation, RenderText
class AnimationController(wx.EvtHandler):
def __init__(self, frame, sliders, animations, mapwindows, providers, bitmapPool):
@@ -448,8 +449,105 @@
region['cols'], region['rows'] = loadSize
self.mapwindows[anim.windowIndex].SetRegion(region)
+ def Export(self):
+ if not self.animationData:
+ GMessage(parent = self.frame, message = _("No animation to export."))
+ return
+ dlg = ExportDialog(self.frame, temporal = self.temporalMode)
+ if dlg.ShowModal() == wx.ID_OK:
+ decorations = dlg.GetDecorations()
+ exportInfo = dlg.GetExportInformation()
+ dlg.Destroy()
+ else:
+ dlg.Destroy()
+ return
+ self._export(exportInfo, decorations)
+ def _export(self, exportInfo, decorations):
+ size = self.frame.animationPanel.GetSize()
+ if self.temporalMode == TemporalMode.TEMPORAL:
+ timeLabels, mapNamesDict = self.temporalManager.GetLabelsAndMaps()
+ frameCount = len(timeLabels)
+ else:
+ frameCount = len(self.animationData[0].mapData) # should be the same for all
+
+ animWinSize = []
+ animWinPos = []
+ animWinIndex = []
+ # determine position and sizes of bitmaps
+ for i, (win, anim) in enumerate(zip(self.mapwindows, self.animations)):
+ if anim.IsActive():
+ pos = tuple([pos1 + pos2 for pos1, pos2 in zip(win.GetPosition(), win.GetAdjustedPosition())])
+ animWinPos.append(pos)
+ animWinSize.append(win.GetAdjustedSize())
+ animWinIndex.append(i)
+
+ images = []
+ for frameIndex in range(frameCount):
+ image = wx.EmptyImage(*size)
+ image.Replace(0, 0, 0, 255, 255, 255)
+ # collect bitmaps of all windows and paste them into the one
+ for i in range(len(animWinSize)):
+ frameId = self.animations[animWinIndex[i]].GetFrame(frameIndex)
+ bitmap = self.bitmapProviders[animWinIndex[i]].GetBitmap(frameId)
+ im = wx.ImageFromBitmap(bitmap)
+ if im.GetSize() != animWinSize[i]:
+ im.Rescale(*animWinSize[i])
+ image.Paste(im, *animWinPos[i])
+ # paste decorations
+ for decoration in decorations:
+ # add image
+ x = decoration['pos'][0] / 100. * size[0]
+ y = decoration['pos'][1] / 100. * size[1]
+ if decoration['name'] == 'image':
+ decImage = wx.Image(decoration['file'])
+ elif decoration['name'] == 'time':
+ timeLabel = timeLabels[frameIndex]
+ if timeLabel[1]:
+ text = _("%(from)s %(dash)s %(to)s") % \
+ {'from': timeLabel[0], 'dash': u"\u2013", 'to': timeLabel[1]}
+ else:
+ text = _("%(start)s %(unit)s") % \
+ {'start': timeLabel[0], 'unit': timeLabel[2]}
+
+ decImage = RenderText(text, decoration['font']).ConvertToImage()
+ elif decoration['name'] == 'text':
+ text = decoration['text']
+ decImage = RenderText(text, decoration['font']).ConvertToImage()
+
+ image.Paste(decImage, x, y)
+
+ images.append(image)
+
+ # export
+ if exportInfo['method'] == 'sequence':
+ busy = wx.BusyInfo(message = _("Exporting images, please wait..."), parent = self.frame)
+ wx.Yield()
+ zeroPadding = len(str(len(images)))
+ for i, image in enumerate(images):
+ filename = "%s_%s.%s" % (exportInfo['prefix'], str(i + 1).zfill(zeroPadding),
+ exportInfo['format']['ext'])
+ image.SaveFile(os.path.join(exportInfo['directory'], filename), exportInfo['format']['type'])
+
+ busy.Destroy()
+
+
+
+ # image.SaveFile('/home/anna/testy/grass/export/export_%s.png' % frameIndex, wx.BITMAP_TYPE_PNG)
+
+
+
+
+
+
+
+ # for anim in self.animationData
+
+
+
+
+
#def test():
# import gettext
# gettext.install('grasswxpy', os.path.join(os.getenv("GISBASE"), 'locale'), unicode = True)
Modified: grass-addons/grass7/gui/wxpython/wx.animation/animation/dialogs.py
===================================================================
--- grass-addons/grass7/gui/wxpython/wx.animation/animation/dialogs.py 2012-10-29 17:52:19 UTC (rev 53610)
+++ grass-addons/grass7/gui/wxpython/wx.animation/animation/dialogs.py 2012-10-29 21:48:11 UTC (rev 53611)
@@ -33,7 +33,7 @@
from core.gcmd import GMessage, GError, GException
from core import globalvar
from gui_core import gselect
-from gui_core.dialogs import MapLayersDialog, EVT_APPLY_MAP_LAYERS
+from gui_core.dialogs import MapLayersDialog, EVT_APPLY_MAP_LAYERS, GetImageHandlers
from core.settings import UserSettings
from utils import TemporalMode, validateTimeseriesName, validateMapNames
@@ -782,6 +782,381 @@
return "%s(%r)" % (self.__class__, self.__dict__)
+
+class ExportDialog(wx.Dialog):
+ def __init__(self, parent, temporal):
+ wx.Dialog.__init__(self, parent = parent, id = wx.ID_ANY, title = _("Export animation"),
+ style = wx.DEFAULT_DIALOG_STYLE)
+ self.decorations = []
+
+ self.temporal = temporal
+ self._layout()
+
+ self.OnFormatRadio(event = None)
+ wx.CallAfter(self._hideAll)
+
+ def _layout(self):
+ notebook = wx.Notebook(self, id = wx.ID_ANY)
+ mainSizer = wx.BoxSizer(wx.VERTICAL)
+
+ notebook.AddPage(page = self._createExportFormatPanel(notebook), text = _("Format"))
+ notebook.AddPage(page = self._createDecorationsPanel(notebook), text = _("Decorations"))
+ mainSizer.Add(item = notebook, proportion = 0,
+ flag = wx.EXPAND | wx.ALL | wx.ALIGN_RIGHT, border = 5)
+
+
+ self.btnExport = wx.Button(self, wx.ID_OK)
+ self.btnExport.SetLabel(_("Export"))
+ self.btnCancel = wx.Button(self, wx.ID_CANCEL)
+ self.btnExport.SetDefault()
+
+ self.btnExport.Bind(wx.EVT_BUTTON, self.OnExport)
+
+ # button sizer
+ btnStdSizer = wx.StdDialogButtonSizer()
+ btnStdSizer.AddButton(self.btnExport)
+ btnStdSizer.AddButton(self.btnCancel)
+ btnStdSizer.Realize()
+
+ mainSizer.Add(item = btnStdSizer, proportion = 0,
+ flag = wx.EXPAND | wx.ALL | wx.ALIGN_RIGHT, border = 5)
+ self.SetSizer(mainSizer)
+
+ # set the longest option to fit
+ self.hidevbox.Show(self.fontBox, True)
+ self.hidevbox.Show(self.imageBox, False)
+ self.hidevbox.Show(self.textBox, True)
+ self.hidevbox.Show(self.posBox, True)
+ self.hidevbox.Show(self.informBox, False)
+ mainSizer.Fit(self)
+
+ def _createDecorationsPanel(self, notebook):
+ panel = wx.Panel(notebook, id = wx.ID_ANY)
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ sizer.Add(self._createDecorationsList(panel), proportion = 0, flag = wx.ALL | wx.EXPAND, border = 10)
+ sizer.Add(self._createDecorationsProperties(panel), proportion = 0, flag = wx.ALL | wx.EXPAND, border = 10)
+ panel.SetSizer(sizer)
+ sizer.Fit(panel)
+ return panel
+
+ def _createDecorationsList(self, panel):
+ gridBagSizer = wx.GridBagSizer(hgap = 5, vgap = 5)
+
+ gridBagSizer.AddGrowableCol(0)
+
+ self.listbox = wx.ListBox(panel, id = wx.ID_ANY, choices = [], style = wx.LB_SINGLE|wx.LB_NEEDED_SB)
+ self.listbox.Bind(wx.EVT_LISTBOX, self.OnSelectionChanged)
+
+ gridBagSizer.Add(self.listbox, pos = (0, 0), span = (4, 1),
+ flag = wx.ALIGN_CENTER_VERTICAL| wx.EXPAND, border = 0)
+
+ buttonNames = ['time', 'image', 'text']
+ buttonLabels = [_("Add time stamp"), _("Add image"), _("Add text")]
+ i = 0
+ for buttonName, buttonLabel in zip(buttonNames, buttonLabels):
+ if buttonName == 'time' and self.temporal == TemporalMode.NONTEMPORAL:
+ continue
+ btn = wx.Button(panel, id = wx.ID_ANY, name = buttonName, label = buttonLabel)
+ btn.Bind(wx.EVT_BUTTON, lambda evt, temp = buttonName: self.OnAddDecoration(evt, temp))
+ gridBagSizer.Add(btn, pos = (i ,1), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)
+ i += 1
+ removeButton = wx.Button(panel, id = wx.ID_ANY, label = _("Remove"))
+ removeButton.Bind(wx.EVT_BUTTON, self.OnRemove)
+ gridBagSizer.Add(removeButton, pos = (i, 1), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0)
+
+ return gridBagSizer
+
+ def _createDecorationsProperties(self, panel):
+ self.hidevbox = wx.BoxSizer(wx.VERTICAL)
+ # inform label
+ self.informBox = wx.BoxSizer(wx.HORIZONTAL)
+ if self.temporal == TemporalMode.TEMPORAL:
+ label = _("Add time stamp, image or text decoration by one of the buttons above.")
+ else:
+ label = _("Add image or text decoration by one of the buttons above.")
+
+ label = wx.StaticText(panel, id = wx.ID_ANY, label = label)
+ label.Wrap(400)
+ self.informBox.Add(label, proportion = 1, flag = wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, border = 5)
+ self.hidevbox.Add(self.informBox, proportion = 0, flag = wx.EXPAND | wx.BOTTOM, border = 5)
+
+ # font
+ self.fontBox = wx.BoxSizer(wx.HORIZONTAL)
+ self.fontBox.Add(wx.StaticText(panel, id = wx.ID_ANY, label = _("Font settings:")),
+ proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, border = 5)
+ self.sampleLabel = wx.StaticText(panel, id = wx.ID_ANY, label = _("Sample text"))
+ self.fontBox.Add(self.sampleLabel, proportion = 1,
+ flag = wx.ALIGN_CENTER | wx.RIGHT | wx.LEFT, border = 5)
+ fontButton = wx.Button(panel, id = wx.ID_ANY, label = _("Set font"))
+ fontButton.Bind(wx.EVT_BUTTON, self.OnFont)
+ self.fontBox.Add(fontButton, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL)
+ self.hidevbox.Add(self.fontBox, proportion = 0, flag = wx.EXPAND | wx.BOTTOM, border = 5)
+
+ # image
+ self.imageBox = wx.BoxSizer(wx.HORIZONTAL)
+ filetype, ltype = GetImageHandlers(wx.EmptyImage(10, 10))
+ self.browse = filebrowse.FileBrowseButton(parent = panel, id = wx.ID_ANY, fileMask = filetype,
+ labelText = _("Image file:"),
+ dialogTitle = _('Choose image file'),
+ buttonText = _('Browse'),
+ startDirectory = os.getcwd(), fileMode = wx.OPEN,
+ changeCallback = self.OnSetImage)
+ self.imageBox.Add(self.browse, proportion = 1, flag = wx.EXPAND)
+ self.hidevbox.Add(self.imageBox, proportion = 0, flag = wx.EXPAND | wx.BOTTOM, border = 5)
+ # text
+ self.textBox = wx.BoxSizer(wx.HORIZONTAL)
+ self.textBox.Add(wx.StaticText(panel, id = wx.ID_ANY, label = _("Text:")),
+ proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, border = 5)
+ self.textCtrl = wx.TextCtrl(panel, id = wx.ID_ANY)
+ self.textCtrl.Bind(wx.EVT_TEXT, self.OnText)
+ self.textBox.Add(self.textCtrl, proportion = 1, flag = wx.EXPAND)
+ self.hidevbox.Add(self.textBox, proportion = 0, flag = wx.EXPAND)
+
+ self.posBox = self._positionWidget(panel)
+ self.hidevbox.Add(self.posBox, proportion = 0, flag = wx.EXPAND | wx.TOP, border = 5)
+ return self.hidevbox
+
+ def _positionWidget(self, panel):
+ grid = wx.GridBagSizer(vgap = 5, hgap = 5)
+ label = wx.StaticText(panel, id = wx.ID_ANY, label = _("Placement as percentage of"
+ " screen coordinates (X: 0, Y: 0 is top left):"))
+ label.Wrap(400)
+ self.spinX = wx.SpinCtrl(panel, id = wx.ID_ANY, min = 0, max = 100, initial = 10)
+ self.spinY = wx.SpinCtrl(panel, id = wx.ID_ANY, min = 0, max = 100, initial = 10)
+ self.spinX.Bind(wx.EVT_SPINCTRL, lambda evt, temp = 'X': self.OnPosition(evt, temp))
+ self.spinY.Bind(wx.EVT_SPINCTRL, lambda evt, temp = 'Y': self.OnPosition(evt, temp))
+
+ grid.Add(label, pos = (0, 0), span = (1, 4), flag = wx.EXPAND)
+ grid.Add(wx.StaticText(panel, id = wx.ID_ANY, label = _("X:")), pos = (1, 0),
+ flag = wx.ALIGN_CENTER_VERTICAL)
+ grid.Add(wx.StaticText(panel, id = wx.ID_ANY, label = _("Y:")), pos = (1, 2),
+ flag = wx.ALIGN_CENTER_VERTICAL)
+ grid.Add(self.spinX, pos = (1, 1))
+ grid.Add(self.spinY, pos = (1, 3))
+
+ return grid
+
+ def _createExportFormatPanel(self, notebook):
+ panel = wx.Panel(notebook, id = wx.ID_ANY)
+ borderSizer = wx.BoxSizer(wx.VERTICAL)
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ self.gifRadio = wx.RadioButton(panel, id = wx.ID_ANY,
+ label = _("Export to animated GIF (not supported yet):"),
+ style = wx.RB_GROUP)
+
+ self.dirRadio = wx.RadioButton(panel, id = wx.ID_ANY, label = _("Export as image sequence:"))
+ self.dirRadio.SetValue(True)
+ self.gifRadio.Bind(wx.EVT_RADIOBUTTON, self.OnFormatRadio)
+ self.dirRadio.Bind(wx.EVT_RADIOBUTTON, self.OnFormatRadio)
+
+ prefixLabel = wx.StaticText(panel, id = wx.ID_ANY, label = _("File prefix:"))
+ self.prefixCtrl = wx.TextCtrl(panel, id = wx.ID_ANY, value = _("animation"))
+
+ formatLabel = wx.StaticText(panel, id = wx.ID_ANY, label = _("File format:"))
+ self.formatChoice = wx.Choice(panel, id = wx.ID_ANY)
+ wildcard, ltype = GetImageHandlers(wx.EmptyImage(10, 10))
+ formats = [format for format in wildcard.split('|') if 'file' in format]
+ for format, cdata in zip(formats, ltype):
+ self.formatChoice.Append(format, cdata)
+
+ self.formatChoice.SetSelection(0)
+
+ self.dirBrowse = filebrowse.DirBrowseButton(parent = panel, id = wx.ID_ANY,
+ labelText = _("Export directory:"),
+ dialogTitle = _("Choose directory for export"),
+ buttonText = _("Browse"),
+ startDirectory = os.getcwd())
+ self.gifBrowse = filebrowse.FileBrowseButton(parent = panel, id = wx.ID_ANY,
+ fileMask = "GIF file (*.gif)|*.gif",
+ labelText = _("GIF file:"),
+ dialogTitle = _("Choose image file"),
+ buttonText = _("Browse"),
+ startDirectory = os.getcwd(), fileMode = wx.SAVE)
+
+ sizer.Add(self.gifRadio, proportion = 0, flag = wx.EXPAND)
+ gifSizer = wx.BoxSizer(wx.HORIZONTAL)
+ gifSizer.AddStretchSpacer(prop = 1)
+ gifSizer.Add(self.gifBrowse, proportion = 6, flag = wx.EXPAND)
+ sizer.Add(gifSizer, proportion = 0, flag = wx.EXPAND)
+
+ sizer.Add(self.dirRadio, proportion = 0, flag = wx.EXPAND)
+
+ dirSizer = wx.BoxSizer(wx.HORIZONTAL)
+ dirSizer.AddStretchSpacer(prop = 1)
+ self.dirGridSizer = wx.GridBagSizer(hgap = 5, vgap = 5)
+ self.dirGridSizer.AddGrowableCol(1)
+ self.dirGridSizer.Add(prefixLabel, pos = (0, 0), flag = wx.ALIGN_CENTER_VERTICAL)
+ self.dirGridSizer.Add(self.prefixCtrl, pos = (0, 1), flag = wx.EXPAND)
+ self.dirGridSizer.Add(formatLabel, pos = (1, 0), flag = wx.ALIGN_CENTER_VERTICAL)
+ self.dirGridSizer.Add(self.formatChoice, pos = (1, 1), flag = wx.EXPAND)
+ self.dirGridSizer.Add(self.dirBrowse, pos = (2, 0), flag = wx.EXPAND, span = (1, 2))
+ dirSizer.Add(self.dirGridSizer, proportion = 6, flag = wx.EXPAND)
+
+ sizer.Add(dirSizer, proportion = 0, flag = wx.EXPAND)
+ borderSizer.Add(sizer, proportion = 0, flag = wx.EXPAND | wx.ALL, border = 10)
+ panel.SetSizer(borderSizer)
+ borderSizer.Fit(panel)
+
+ return panel
+
+ def OnFormatRadio(self, event):
+ self.gifBrowse.Enable(self.gifRadio.GetValue())
+ for child in self.dirGridSizer.GetChildren():
+ child.GetWindow().Enable(self.dirRadio.GetValue())
+
+ def OnFont(self, event):
+ index = self.listbox.GetSelection()
+ # should not happen
+ if index == wx.NOT_FOUND:
+ return
+ cdata = self.listbox.GetClientData(index)
+ font = cdata['font']
+
+ fontdata = wx.FontData()
+ fontdata.EnableEffects(True)
+ fontdata.SetColour('black')
+ fontdata.SetInitialFont(font)
+
+ dlg = wx.FontDialog(self, fontdata)
+
+ if dlg.ShowModal() == wx.ID_OK:
+ newfontdata = dlg.GetFontData()
+ font = newfontdata.GetChosenFont()
+ self.sampleLabel.SetFont(font)
+ cdata['font'] = font
+ self.Layout()
+
+
+ def OnPosition(self, event, coord):
+ index = self.listbox.GetSelection()
+ # should not happen
+ if index == wx.NOT_FOUND:
+ return
+ cdata = self.listbox.GetClientData(index)
+ cdata['pos'][coord == 'Y'] = event.GetInt()
+
+ def OnSetImage(self, event):
+ index = self.listbox.GetSelection()
+ # should not happen
+ if index == wx.NOT_FOUND:
+ return
+ cdata = self.listbox.GetClientData(index)
+ cdata['file'] = event.GetString()
+
+ def OnAddDecoration(self, event, name):
+ if name == 'time':
+ timeInfo = {'name': name, 'font': self.GetFont(), 'pos': [10, 10]}
+ self.decorations.append(timeInfo)
+ elif name == 'image':
+ imageInfo = {'name': name, 'file': '', 'pos': [10, 10]}
+ self.decorations.append(imageInfo)
+ elif name == 'text':
+ textInfo = {'name': name, 'font': self.GetFont(), 'text': '', 'pos': [10, 10]}
+ self.decorations.append(textInfo)
+
+ self._updateListBox()
+ self.listbox.SetSelection(self.listbox.GetCount() - 1)
+ self.OnSelectionChanged(event = None)
+
+ def OnSelectionChanged(self, event):
+ index = self.listbox.GetSelection()
+ if index == wx.NOT_FOUND:
+ self._hideAll()
+ return
+ cdata = self.listbox.GetClientData(index)
+ self.hidevbox.Show(self.fontBox, (cdata['name'] in ('time', 'text')))
+ self.hidevbox.Show(self.imageBox, (cdata['name'] == 'image'))
+ self.hidevbox.Show(self.textBox, (cdata['name'] == 'text'))
+ self.hidevbox.Show(self.posBox, True)
+ self.hidevbox.Show(self.informBox, False)
+
+ self.spinX.SetValue(cdata['pos'][0])
+ self.spinY.SetValue(cdata['pos'][1])
+ if cdata['name'] == 'image':
+ self.browse.SetValue(cdata['file'])
+ elif cdata['name'] in ('time', 'text'):
+ self.sampleLabel.SetFont(cdata['font'])
+ if cdata['name'] == 'text':
+ self.textCtrl.SetValue(cdata['text'])
+
+ self.hidevbox.Layout()
+ # self.Layout()
+
+ def OnText(self, event):
+ index = self.listbox.GetSelection()
+ # should not happen
+ if index == wx.NOT_FOUND:
+ return
+ cdata = self.listbox.GetClientData(index)
+ cdata['text'] = event.GetString()
+
+ def OnRemove(self, event):
+ index = self.listbox.GetSelection()
+ if index == wx.NOT_FOUND:
+ return
+
+ decData = self.listbox.GetClientData(index)
+ self.decorations.remove(decData)
+
+ self._updateListBox()
+ if self.listbox.GetCount():
+ self.listbox.SetSelection(0)
+ self.OnSelectionChanged(event = None)
+
+ def OnExport(self, event):
+ for decor in self.decorations:
+ if decor['name'] == 'image':
+ if not os.path.exists(decor['file']):
+ if decor['file']:
+ GError(parent = self, message = _("File %s not found.") % decor['file'])
+ else:
+ GError(parent = self, message = _("Decoration image file is missing."))
+ return
+
+ if self.dirRadio.GetValue():
+ name = self.dirBrowse.GetValue()
+ if not os.path.exists(name):
+ if name:
+ GError(parent = self, message = _("Directory %s not found.") % name)
+ else:
+ GError(parent = self, message = _("Export directory is missing."))
+ return
+ elif self.gifRadio.GetValue():
+ if not self.gifBrowse.GetValue():
+ GError(parent = self, message = _("Export file is missing."))
+ return
+
+ self.EndModal(wx.ID_OK)
+
+ def GetDecorations(self):
+ return self.decorations
+
+ def GetExportInformation(self):
+ info = {}
+ if self.gifRadio.GetValue():
+ info['method'] = 'gif'
+ info['file'] = self.gifBrowse.GetValue()
+ else:
+ info['method'] = 'sequence'
+ info['directory'] = self.dirBrowse.GetValue()
+ info['prefix'] = self.prefixCtrl.GetValue()
+ info['format'] = self.formatChoice.GetClientData(self.formatChoice.GetSelection())
+ return info
+
+ def _updateListBox(self):
+ self.listbox.Clear()
+ names = {'time': _("Time stamp"), 'image': _("Image"), 'text': _("Text")}
+ for decor in self.decorations:
+ self.listbox.Append(names[decor['name']], clientData = decor)
+
+ def _hideAll(self):
+ self.hidevbox.Show(self.fontBox, False)
+ self.hidevbox.Show(self.imageBox, False)
+ self.hidevbox.Show(self.textBox, False)
+ self.hidevbox.Show(self.posBox, False)
+ self.hidevbox.Show(self.informBox, True)
+ self.hidevbox.Layout()
+
def test():
import wx.lib.inspection
import gettext
@@ -790,22 +1165,38 @@
import grass.script as grass
app = wx.PySimpleApp()
+
+ testExport()
+ # wx.lib.inspection.InspectionTool().Show()
+
+
+
+ app.MainLoop()
+
+def testAnimInput():
anim = AnimationData()
anim.SetDefaultValues(animationIndex = 0, windowIndex = 0)
dlg = InputDialog(parent = None, mode = 'add', animationData = anim)
- # dlg = EditDialog(parent = None, animationData = [anim])
- wx.lib.inspection.InspectionTool().Show()
+ dlg.Show()
+def testAnimEdit():
+ anim = AnimationData()
+ anim.SetDefaultValues(animationIndex = 0, windowIndex = 0)
+
+ dlg = EditDialog(parent = None, animationData = [anim])
dlg.Show()
- # if val == wx.ID_OK:
- # dlg.Update()
- # # print anim
-
- # dlg.Destroy()
- print anim
- app.MainLoop()
+def testExport():
+ dlg = ExportDialog(parent = None, temporal = TemporalMode.TEMPORAL)
+ if dlg.ShowModal() == wx.ID_OK:
+ print dlg.GetDecorations()
+ print dlg.GetExportInformation()
+ dlg.Destroy()
+ else:
+ dlg.Destroy()
+
+
if __name__ == '__main__':
test()
\ No newline at end of file
Modified: grass-addons/grass7/gui/wxpython/wx.animation/animation/frame.py
===================================================================
--- grass-addons/grass7/gui/wxpython/wx.animation/animation/frame.py 2012-10-29 17:52:19 UTC (rev 53610)
+++ grass-addons/grass7/gui/wxpython/wx.animation/animation/frame.py 2012-10-29 21:48:11 UTC (rev 53611)
@@ -64,7 +64,8 @@
providers = self.providers,
bitmapPool = bitmapPool)
for win, provider in zip(self.windows, self.providers):
- win.Bind(wx.EVT_SIZE, lambda event, prov = provider: prov.WindowSizeChanged(event))
+ win.Bind(wx.EVT_SIZE, lambda event, prov = provider,
+ sizeMethod = win.GetClientSize: prov.WindowSizeChanged(event, sizeMethod))
self.InitStatusbar()
self._mgr = wx.aui.AuiManager(self)
@@ -228,6 +229,9 @@
def Reload(self, event):
self.controller.Reload()
+ def OnExportAnimation(self, event):
+ self.controller.Export()
+
def OnHelp(self, event):
RunCommand('g.manual',
quiet = True,
@@ -283,6 +287,8 @@
return self.mainSizer.IsShown(self.windows[index])
+
+
class AnimationSliderBase(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent = parent, id = wx.ID_ANY)
Modified: grass-addons/grass7/gui/wxpython/wx.animation/animation/mapwindow.py
===================================================================
--- grass-addons/grass7/gui/wxpython/wx.animation/animation/mapwindow.py 2012-10-29 17:52:19 UTC (rev 53610)
+++ grass-addons/grass7/gui/wxpython/wx.animation/animation/mapwindow.py 2012-10-29 21:48:11 UTC (rev 53611)
@@ -21,6 +21,7 @@
import grass.script as grass
from core.gcmd import RunCommand
+from utils import ComputeScaledRect
class BufferedWindow(wx.Window):
"""
@@ -163,23 +164,10 @@
cols = self.region['cols']
rows = self.region['rows']
-
- ratioB = cols / float(rows)
- ww, wh = self.GetClientSize()
- try:
- ratioW = ww / float(wh)
- except ZeroDivisionError:
- self.x = self.y = 0
- self.size = (0, 0)
- return
- if ratioW > ratioB:
- self.size = (wh * ratioB, wh)
- self.y = 0
- self.x = (ww - wh * ratioB) / 2
- else:
- self.size = (ww, ww / ratioB)
- self.x = 0
- self.y = (wh - ww / ratioB) / 2
+ params = ComputeScaledRect((cols, rows), self.GetClientSize())
+ self.x = params['x']
+ self.y = params['y']
+ self.size = (params['width'], params['height'])
def SetRegion(self, region):
"""!Sets region for size computations.
@@ -188,6 +176,12 @@
self.region = region
self._computeBitmapCoordinates()
+ def GetAdjustedSize(self):
+ return self.size
+
+ def GetAdjustedPosition(self):
+ return self.x, self.y
+
class BitmapProvider(object):
"""!Class responsible for loading data and providing bitmaps"""
def __init__(self, frame, bitmapPool):
@@ -245,9 +239,10 @@
def GetLoadSize(self):
return self.loadSize
- def WindowSizeChanged(self, event):
+ def WindowSizeChanged(self, event, sizeMethod):
"""!Sets size when size of related window changes."""
- self.size = event.GetSize()
+ # sizeMethod is GetClientSize, must be used instead of GetSize
+ self.size = sizeMethod()
event.Skip()
def _createNoDataBitmap(self, ncols, nrows):
@@ -310,22 +305,10 @@
"""!Computes parameters for creating bitmaps."""
region = grass.region()
ncols, nrows = region['cols'], region['rows']
- if nrows > ncols:
- longdim = nrows
- size = self.size[1]
- else:
- longdim = ncols
- size = self.size[0]
- scale = 1.0
+ params = ComputeScaledRect((ncols, nrows), self.size)
- if longdim > size:
- scale = float(size) / longdim
- elif longdim < size:
- scale = float(size) / longdim
- size = (int(ncols * scale), int(nrows * scale))
+ return ((params['width'], params['height']), params['scale'])
- return (size, scale)
-
def _dryLoad(self, rasters, names, force):
"""!Tries how many bitmaps will be loaded.
Used for progress dialog.
@@ -359,12 +342,15 @@
region = grass.region()
for key in ('rows', 'cols', 'cells'):
region.pop(key)
+ # sometimes it renderes nonsense - depends on resolution
+ # should we set the resolution of the raster?
region['nsres'] /= scale
region['ewres'] /= scale
os.environ['GRASS_REGION'] = grass.region_env(**region)
ncols, nrows = size
self.loadSize = size
count = 0
+
# create no data bitmap
if None not in self.bitmapPool or force:
self.bitmapPool[None] = self._createNoDataBitmap(ncols, nrows)
Modified: grass-addons/grass7/gui/wxpython/wx.animation/animation/toolbars.py
===================================================================
--- grass-addons/grass7/gui/wxpython/wx.animation/animation/toolbars.py 2012-10-29 17:52:19 UTC (rev 53610)
+++ grass-addons/grass7/gui/wxpython/wx.animation/animation/toolbars.py 2012-10-29 21:48:11 UTC (rev 53611)
@@ -35,6 +35,8 @@
desc = _("Add new animation")),
'editAnimation': MetaIcon(img = 'layer-more', label = _("Add, edit or remove animation"),
desc = _("Add, edit or remove animation")),
+ 'exportAnimation': MetaIcon(img = 'layer-export', label = _("Export animation"),
+ desc = _("Export animation"))
}
class MainToolbar(BaseToolbar):
@@ -60,7 +62,9 @@
("editAnimation", icons["editAnimation"],
self.parent.OnEditAnimation),
("reload", BaseIcons["render"],
- self.parent.Reload)
+ self.parent.Reload),
+ ("exportAnimation", icons["exportAnimation"],
+ self.parent.OnExportAnimation),
))
class AnimationToolbar(BaseToolbar):
"""!Animation toolbar (to control animation)
Modified: grass-addons/grass7/gui/wxpython/wx.animation/animation/utils.py
===================================================================
--- grass-addons/grass7/gui/wxpython/wx.animation/animation/utils.py 2012-10-29 17:52:19 UTC (rev 53610)
+++ grass-addons/grass7/gui/wxpython/wx.animation/animation/utils.py 2012-10-29 21:48:11 UTC (rev 53611)
@@ -17,6 +17,7 @@
@author Anna Kratochvilova <kratochanna gmail.com>
"""
+import wx
import grass.temporal as tgis
import grass.script as grass
@@ -84,3 +85,49 @@
if not found:
raise GException(_("Map <%s> not found.") % name)
return newNames
+
+def ComputeScaledRect(sourceSize, destSize):
+ """!Fits source rectangle into destination rectangle
+ by scaling and centering.
+
+ @code
+
+ >>> ComputeScaledRect(sourceSize = (10, 40), destSize = (100, 50))
+ {'height': 50, 'scale': 1.25, 'width': 13, 'x': 44, 'y': 0}
+
+ @endcode
+
+ @param sourceSize size of source rectangle
+ @param destSize size of destination rectangle
+ """
+ ratio1 = destSize[0] / float(sourceSize[0])
+ ratio2 = destSize[1] / float(sourceSize[1])
+ if ratio1 < ratio2:
+ scale = ratio1
+ width = int(sourceSize[0] * scale + 0.5)
+ height = int(sourceSize[1] * scale + 0.5)
+ x = 0
+ y = int((destSize[1] - height) / 2. + 0.5)
+ else:
+ scale = ratio2
+ width = int(sourceSize[0] * scale + 0.5)
+ height = int(sourceSize[1] * scale + 0.5)
+ y = 0
+ x = int((destSize[0] - width) / 2. + 0.5)
+
+ return {'width': width, 'height': height, 'x': x, 'y': y, 'scale': scale}
+
+def RenderText(text, font):
+ """!Renderes text with given font to bitmap."""
+ dc = wx.MemoryDC()
+ dc.SetFont(font)
+ w, h = dc.GetTextExtent(text)
+ bmp = wx.EmptyBitmap(w + 2, h + 2)
+ dc.SelectObject(bmp)
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.SetBackgroundMode(wx.TRANSPARENT)
+ dc.Clear()
+ dc.DrawText(text, 1, 1)
+ dc.SelectObject(wx.NullBitmap)
+
+ return bmp
More information about the grass-commit
mailing list