[GRASS-SVN] r58551 - in grass/trunk/gui/wxpython: animation core lmgr
svn_grass at osgeo.org
svn_grass at osgeo.org
Sun Dec 29 15:18:13 PST 2013
Author: annakrat
Date: 2013-12-29 15:18:13 -0800 (Sun, 29 Dec 2013)
New Revision: 58551
Modified:
grass/trunk/gui/wxpython/animation/controller.py
grass/trunk/gui/wxpython/animation/dialogs.py
grass/trunk/gui/wxpython/animation/frame.py
grass/trunk/gui/wxpython/animation/g.gui.animation.html
grass/trunk/gui/wxpython/animation/g.gui.animation.py
grass/trunk/gui/wxpython/animation/temporal_manager.py
grass/trunk/gui/wxpython/animation/toolbars.py
grass/trunk/gui/wxpython/animation/utils.py
grass/trunk/gui/wxpython/core/settings.py
grass/trunk/gui/wxpython/lmgr/frame.py
Log:
wxGUI/animation: create application settings (bgcolor, time format)
Modified: grass/trunk/gui/wxpython/animation/controller.py
===================================================================
--- grass/trunk/gui/wxpython/animation/controller.py 2013-12-29 23:09:07 UTC (rev 58550)
+++ grass/trunk/gui/wxpython/animation/controller.py 2013-12-29 23:18:13 UTC (rev 58551)
@@ -19,10 +19,11 @@
from core.gcmd import GException, GError, GMessage
from core.utils import _
from grass.imaging import writeAvi, writeGif, writeIms, writeSwf
+from core.settings import UserSettings
from animation.temporal_manager import TemporalManager
from animation.dialogs import InputDialog, EditDialog, ExportDialog
-from animation.utils import TemporalMode, Orientation, RenderText, WxImageToPil, \
+from animation.utils import TemporalMode, TemporalType, Orientation, RenderText, WxImageToPil, \
sampleCmdMatrixAndCreateNames, layerListToCmdsMatrix, HashCmds, getCpuCount
from animation.data import AnimationData
@@ -131,10 +132,12 @@
def UpdateFrame(self, index, win, dataId):
bitmap = self.bitmapProvider.GetBitmap(dataId)
- if dataId is None:
- dataId = ''
- win.DrawBitmap(bitmap)
- # self.frame.SetStatusText(dataId)
+ if not UserSettings.Get(group='animation', key='temporal',
+ subkey=['nodata', 'enable']):
+ if dataId is not None:
+ win.DrawBitmap(bitmap)
+ else:
+ win.DrawBitmap(bitmap)
self.slider.UpdateFrame(index)
def SliderChanging(self, index):
@@ -356,7 +359,8 @@
else:
self._load3DData(animData)
self._loadLegend(animData)
- self.bitmapProvider.Load(nprocs=getCpuCount())
+ color = UserSettings.Get(group='animation', key='bgcolor', subkey='color')
+ self.bitmapProvider.Load(nprocs=getCpuCount(), bgcolor=color)
# clear pools
self.bitmapPool.Clear()
self.mapFilesPool.Clear()
@@ -431,7 +435,8 @@
def Reload(self):
self.EndAnimation()
- self.bitmapProvider.Load(nprocs=getCpuCount(), force=True)
+ color = UserSettings.Get(group='animation', key='bgcolor', subkey='color')
+ self.bitmapProvider.Load(nprocs=getCpuCount(), bgcolor=color, force=True)
self.EndAnimation()
@@ -479,7 +484,12 @@
# collect bitmaps of all windows and paste them into the one
for i in animWinIndex:
frameId = self.animations[i].GetFrame(frameIndex)
- bitmap = self.bitmapProvider.GetBitmap(frameId)
+ if not UserSettings.Get(group='animation', key='temporal',
+ subkey=['nodata', 'enable']):
+ if frameId is not None:
+ bitmap = self.bitmapProvider.GetBitmap(frameId)
+ else:
+ bitmap = self.bitmapProvider.GetBitmap(frameId)
im = wx.ImageFromBitmap(bitmap)
# add legend if used
@@ -504,12 +514,15 @@
decImage = wx.Image(decoration['file'])
elif decoration['name'] == 'time':
timeLabel = timeLabels[frameIndex]
- if timeLabel[1]:
+ if timeLabel[1]: # interval
text = _("%(from)s %(dash)s %(to)s") % \
- {'from': timeLabel[0], 'dash': u"\u2013", 'to': timeLabel[1]}
+ {'from': timeLabel[0], 'dash': u"\u2013", 'to': timeLabel[1]}
else:
- text = _("%(start)s %(unit)s") % \
- {'start': timeLabel[0], 'unit': timeLabel[2]}
+ if self.temporalManager.GetTemporalType() == TemporalType.ABSOLUTE:
+ text = timeLabel[0]
+ else:
+ text = _("%(start)s %(unit)s") % \
+ {'start': timeLabel[0], 'unit': timeLabel[2]}
decImage = RenderText(text, decoration['font']).ConvertToImage()
elif decoration['name'] == 'text':
Modified: grass/trunk/gui/wxpython/animation/dialogs.py
===================================================================
--- grass/trunk/gui/wxpython/animation/dialogs.py 2013-12-29 23:09:07 UTC (rev 58550)
+++ grass/trunk/gui/wxpython/animation/dialogs.py 2013-12-29 23:18:13 UTC (rev 58551)
@@ -25,6 +25,8 @@
import copy
import datetime
import wx.lib.filebrowsebutton as filebrowse
+import wx.lib.scrolledpanel as SP
+import wx.lib.colourselect as csel
if __name__ == '__main__':
sys.path.append(os.path.join(os.environ['GISBASE'], "etc", "gui", "wxpython"))
@@ -32,6 +34,7 @@
from core.gcmd import GMessage, GError, GException
from core import globalvar
from gui_core.dialogs import MapLayersDialog, GetImageHandlers
+from gui_core.preferences import PreferencesBaseDialog
from gui_core.forms import GUI
from core.settings import UserSettings
from core.utils import _
@@ -1337,6 +1340,135 @@
return self.layer
+class PreferencesDialog(PreferencesBaseDialog):
+ """!Animation preferences dialog"""
+ def __init__(self, parent, giface, title=_("Animation Tool settings"),
+ settings=UserSettings):
+ PreferencesBaseDialog.__init__(self, parent=parent, giface=giface, title=title,
+ settings=settings, size=(-1, 270))
+
+ self._timeFormats = ['%Y-%m-%d %H:%M:%S', # 2013-12-29 11:16:26
+ '%Y-%m-%d', # 2013-12-29
+ '%c', # Sun Dec 29 11:16:26 2013 (locale-dependent)
+ '%x', # 12/29/13 (locale-dependent)
+ '%X', # 11:16:26 (locale-dependent)
+ '%b %d, %Y', # Dec 29, 2013
+ '%B %d, %Y', # December 29, 2013
+ '%B, %Y', # December 2013
+ '%I:%M %p', # 11:16 AM
+ '%I %p', # 11 AM
+ ]
+ self._format = None
+ # create notebook pages
+ self._createGeneralPage(self.notebook)
+ self._createTemporalPage(self.notebook)
+
+ self.SetMinSize(self.GetBestSize())
+ self.SetSize(self.size)
+
+ def _createGeneralPage(self, notebook):
+ """!Create notebook page for general settings"""
+ panel = SP.ScrolledPanel(parent=notebook)
+ panel.SetupScrolling(scroll_x=False, scroll_y=True)
+ notebook.AddPage(page=panel, text=_("General"))
+
+ border = wx.BoxSizer(wx.VERTICAL)
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ gridSizer = wx.GridBagSizer(hgap=3, vgap=3)
+
+ row = 0
+ gridSizer.Add(item=wx.StaticText(parent=panel,
+ label=_("Background color:")),
+ flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
+ color = csel.ColourSelect(parent=panel,
+ colour=UserSettings.Get(group='animation',
+ key='bgcolor', subkey='color'),
+ size=globalvar.DIALOG_COLOR_SIZE)
+ color.SetName('GetColour')
+ self.winId['animation:bgcolor:color'] = color.GetId()
+
+ gridSizer.Add(item=color, pos=(row, 1), flag=wx.ALIGN_RIGHT)
+
+ gridSizer.AddGrowableCol(1)
+ sizer.Add(item=gridSizer, proportion=1, flag=wx.ALL | wx.EXPAND, border=3)
+ border.Add(item=sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=3)
+ panel.SetSizer(border)
+
+ return panel
+
+ def _createTemporalPage(self, notebook):
+ """!Create notebook page for temporal settings"""
+ panel = SP.ScrolledPanel(parent=notebook)
+ panel.SetupScrolling(scroll_x=False, scroll_y=True)
+ notebook.AddPage(page=panel, text=_("Time"))
+
+ border = wx.BoxSizer(wx.VERTICAL)
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ gridSizer = wx.GridBagSizer(hgap=5, vgap=5)
+
+ row = 0
+ gridSizer.Add(item=wx.StaticText(parent=panel,
+ label=_("Absolute time format:")),
+ flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
+ self.tempFormat = wx.ComboBox(parent=panel, name='GetValue')
+ self.tempFormat.SetItems(self._timeFormats)
+ self.tempFormat.SetValue(self.settings.Get(group='animation', key='temporal',
+ subkey='format'))
+ self.winId['animation:temporal:format'] = self.tempFormat.GetId()
+ gridSizer.Add(item=self.tempFormat, pos=(row, 1), flag=wx.ALIGN_RIGHT)
+ self.infoTimeLabel = wx.StaticText(parent=panel)
+ self.tempFormat.Bind(wx.EVT_COMBOBOX, lambda evt: self._setTimeFormat(self.tempFormat.GetValue()))
+ self.tempFormat.Bind(wx.EVT_TEXT, lambda evt: self._setTimeFormat(self.tempFormat.GetValue()))
+ self.tempFormat.SetToolTipString(_("Click and then press key up or down to preview "
+ "different date and time formats. "
+ "Type custom format string."))
+ row += 1
+ gridSizer.Add(item=self.infoTimeLabel, pos=(row, 0), span=(1, 2),
+ flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT)
+ self._setTimeFormat(self.tempFormat.GetValue())
+
+ row += 1
+ link = wx.HyperlinkCtrl(panel, id=wx.ID_ANY, label=_("Learn more about formatting options"),
+ url="http://docs.python.org/2/library/datetime.html#"
+ "strftime-and-strptime-behavior")
+ link.SetNormalColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_GRAYTEXT))
+ link.SetVisitedColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_GRAYTEXT))
+ gridSizer.Add(item=link, pos=(row, 0), span=(1, 2),
+ flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT)
+
+ row += 2
+ noDataCheck = wx.CheckBox(panel, label=_("Display instances with no data"))
+ noDataCheck.SetToolTipString(_("When animating instant-based data which have irregular timestamps "
+ "you can display 'no data frame' (checked option) or "
+ "keep last frame."))
+ noDataCheck.SetValue(self.settings.Get(group='animation', key='temporal',
+ subkey=['nodata', 'enable']))
+ self.winId['animation:temporal:nodata:enable'] = noDataCheck.GetId()
+ gridSizer.Add(item=noDataCheck, pos=(row, 0), span=(1, 2),
+ flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT)
+
+ gridSizer.AddGrowableCol(1)
+ sizer.Add(item=gridSizer, proportion=1, flag=wx.ALL | wx.EXPAND, border=3)
+ border.Add(item=sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=3)
+ panel.SetSizer(border)
+
+ return panel
+
+ def _setTimeFormat(self, formatString):
+ now = datetime.datetime.now()
+ try:
+ label = datetime.datetime.strftime(now, formatString)
+ self._format = formatString
+ except ValueError:
+ label = _("Invalid")
+ self.infoTimeLabel.SetLabel(label)
+ self.infoTimeLabel.GetContainingSizer().Layout()
+
+ def _updateSettings(self):
+ self.tempFormat.SetValue(self._format)
+ return PreferencesBaseDialog._updateSettings(self)
+
+
def test():
import wx.lib.inspection
Modified: grass/trunk/gui/wxpython/animation/frame.py
===================================================================
--- grass/trunk/gui/wxpython/animation/frame.py 2013-12-29 23:09:07 UTC (rev 58550)
+++ grass/trunk/gui/wxpython/animation/frame.py 2013-12-29 23:18:13 UTC (rev 58551)
@@ -37,7 +37,7 @@
from animation.controller import AnimationController
from animation.anim import Animation
from animation.toolbars import MainToolbar, AnimationToolbar, MiscToolbar
-from animation.dialogs import SpeedDialog
+from animation.dialogs import SpeedDialog, PreferencesDialog
from animation.utils import Orientation, ReplayMode, TemporalType
@@ -48,11 +48,11 @@
class AnimationFrame(wx.Frame):
- def __init__(self, parent=None, title=_("Animation tool"),
+ def __init__(self, parent, giface, title=_("Animation tool"),
rasters=None, timeseries=None):
wx.Frame.__init__(self, parent, title=title,
style=wx.DEFAULT_FRAME_STYLE, size=(800, 600))
-
+ self._giface = giface
self.SetClientSize(self.GetSize())
self.iconsize = (16, 16)
@@ -108,6 +108,7 @@
self.dialogs = dict()
self.dialogs['speed'] = None
+ self.dialogs['preferences'] = None
self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
@@ -286,6 +287,14 @@
self.provider.WindowSizeChanged(maxWidth, maxHeight)
event.Skip()
+ def OnPreferences(self, event):
+ if not self.dialogs['preferences']:
+ dlg = PreferencesDialog(parent=self, giface=self._giface)
+ self.dialogs['preferences'] = dlg
+ dlg.CenterOnParent()
+
+ self.dialogs['preferences'].ShowModal()
+
def OnHelp(self, event):
RunCommand('g.manual',
quiet=True,
Modified: grass/trunk/gui/wxpython/animation/g.gui.animation.html
===================================================================
--- grass/trunk/gui/wxpython/animation/g.gui.animation.html 2013-12-29 23:09:07 UTC (rev 58550)
+++ grass/trunk/gui/wxpython/animation/g.gui.animation.html 2013-12-29 23:18:13 UTC (rev 58551)
@@ -17,6 +17,8 @@
<li>visualize space time datasets with unequally spaced intervals</li>
<li>animate 3d view (partially implemented, not supported on Windows)</li>
<li>export animation as a series of images, animated GIF, AVI or SWF</li>
+ <li>choose format of time labels in case of animating maps with absolute time</li>
+ <li>choose background color</li>
</ul>
<p>
Modified: grass/trunk/gui/wxpython/animation/g.gui.animation.py
===================================================================
--- grass/trunk/gui/wxpython/animation/g.gui.animation.py 2013-12-29 23:09:07 UTC (rev 58550)
+++ grass/trunk/gui/wxpython/animation/g.gui.animation.py 2013-12-29 23:18:13 UTC (rev 58551)
@@ -62,6 +62,7 @@
from core.globalvar import CheckWxVersion
from core.utils import _, GuiModuleMain
+from core.giface import StandaloneGrassInterface
from core.layerlist import LayerList
from animation.frame import AnimationFrame, MAX_COUNT
from animation.data import AnimLayer
@@ -117,7 +118,7 @@
if not CheckWxVersion([2, 9]):
wx.InitAllImageHandlers()
- frame = AnimationFrame(parent=None)
+ frame = AnimationFrame(parent=None, giface=StandaloneGrassInterface())
frame.CentreOnScreen()
frame.Show()
if len(layerList) >= 1:
Modified: grass/trunk/gui/wxpython/animation/temporal_manager.py
===================================================================
--- grass/trunk/gui/wxpython/animation/temporal_manager.py 2013-12-29 23:09:07 UTC (rev 58550)
+++ grass/trunk/gui/wxpython/animation/temporal_manager.py 2013-12-29 23:18:13 UTC (rev 58551)
@@ -19,6 +19,7 @@
import os
import sys
+import datetime
if __name__ == '__main__':
sys.path.append(os.path.join(os.environ['GISBASE'], "etc", "gui", "wxpython"))
@@ -27,6 +28,7 @@
import grass.temporal as tgis
from core.gcmd import GException
from core.utils import _
+from core.settings import UserSettings
from animation.utils import validateTimeseriesName, TemporalType
@@ -191,12 +193,11 @@
# no temporal overlap! We would need to sample all datasets
# by a temporary dataset, I don't know how it would work with point data
if self.temporalType == TemporalType.ABSOLUTE:
- # ('1996-01-01 00:00:00', '1997-01-01 00:00:00', 'year'),
timestamps = sorted(list(labelListSet), key=lambda x: x[0])
else:
- # ('15', '16', u'years'),
- timestamps = sorted(list(labelListSet), key=lambda x: float(x[0]))
+ timestamps = sorted(list(labelListSet), key=lambda x: x[0])
+
newMapLists = []
for mapList, labelList in zip(mapLists, labelLists):
newMapList = [None] * len(timestamps)
@@ -211,6 +212,15 @@
for i, dataset in enumerate(self.timeseriesList):
mapDict[dataset] = newMapLists[i]
+ if self.temporalType == TemporalType.ABSOLUTE:
+ # ('1996-01-01 00:00:00', '1997-01-01 00:00:00', 'year'),
+ formatString = UserSettings.Get(group='animation', key='temporal', subkey='format')
+ timestamps = [(datetime.datetime.strftime(st, formatString),
+ datetime.datetime.strftime(end, formatString)
+ if end is not None else None, unit) for (st, end, unit) in timestamps]
+ else:
+ # ('15', '16', u'years'),
+ timestamps = [(str(st), str(end), unit) for st, end, unit in timestamps]
return timestamps, mapDict
def _getLabelsAndMaps(self, timeseries):
@@ -264,7 +274,7 @@
lastTimeseries = series
end = None
else:
- end = str(end)
+ end = end
# interval data
if series:
# map exists, stop point mode
@@ -284,7 +294,7 @@
else:
# append series which is None
listOfMaps.append(series)
- timeLabels.append((str(start), end, unit))
+ timeLabels.append((start, end, unit))
return timeLabels, listOfMaps
Modified: grass/trunk/gui/wxpython/animation/toolbars.py
===================================================================
--- grass/trunk/gui/wxpython/animation/toolbars.py 2013-12-29 23:09:07 UTC (rev 58550)
+++ grass/trunk/gui/wxpython/animation/toolbars.py 2013-12-29 23:18:13 UTC (rev 58551)
@@ -25,7 +25,7 @@
from animation.anim import ReplayMode
ganimIcons = {
- 'speed': MetaIcon(img='settings', label=_("Change animation speed")),
+ 'speed': MetaIcon(img='move', label=_("Change animation speed")),
'playForward': MetaIcon(img='execute', label=_("Play forward")),
'playBack': MetaIcon(img='player-back', label=_("Play back")),
'stop': MetaIcon(img='player-stop', label=_("Stop")),
@@ -215,7 +215,9 @@
def _toolbarData(self):
"""!Toolbar data"""
- return self._getToolbarData((("help", BaseIcons['help'],
+ return self._getToolbarData((("settings", BaseIcons['settings'],
+ self.parent.OnPreferences),
+ ("help", BaseIcons['help'],
self.parent.OnHelp),
("quit", BaseIcons['quit'],
self.parent.OnCloseWindow),
Modified: grass/trunk/gui/wxpython/animation/utils.py
===================================================================
--- grass/trunk/gui/wxpython/animation/utils.py 2013-12-29 23:09:07 UTC (rev 58550)
+++ grass/trunk/gui/wxpython/animation/utils.py 2013-12-29 23:18:13 UTC (rev 58551)
@@ -229,6 +229,7 @@
dc.SetBackgroundMode(wx.TRANSPARENT)
dc.Clear()
dc.DrawText(text, 1, 1)
+ bmp.SetMaskColour(wx.WHITE)
dc.SelectObject(wx.NullBitmap)
return bmp
Modified: grass/trunk/gui/wxpython/core/settings.py
===================================================================
--- grass/trunk/gui/wxpython/core/settings.py 2013-12-29 23:09:07 UTC (rev 58550)
+++ grass/trunk/gui/wxpython/core/settings.py 2013-12-29 23:18:13 UTC (rev 58551)
@@ -799,6 +799,17 @@
}
},
},
+ 'animation': {
+ 'bgcolor': {
+ 'color': (255, 255, 255, 255),
+ },
+ 'temporal': {
+ 'format': '%Y-%m-%d %H:%M:%S',
+ 'nodata': {
+ 'enable': False
+ },
+ },
+ },
}
# quick fix, http://trac.osgeo.org/grass/ticket/1233
Modified: grass/trunk/gui/wxpython/lmgr/frame.py
===================================================================
--- grass/trunk/gui/wxpython/lmgr/frame.py 2013-12-29 23:09:07 UTC (rev 58550)
+++ grass/trunk/gui/wxpython/lmgr/frame.py 2013-12-29 23:18:13 UTC (rev 58551)
@@ -1457,7 +1457,7 @@
"""
from animation.frame import AnimationFrame
- frame = AnimationFrame(parent = self)
+ frame = AnimationFrame(parent=self, giface=self._giface)
frame.CentreOnScreen()
frame.Show()
More information about the grass-commit
mailing list