예제 #1
0
    def __init__(self, parent, giface, title=_("GRASS GIS 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)

        self.SetIcon(
            wx.Icon(
                os.path.join(
                    globalvar.ICONDIR,
                    'grass_map.ico'),
                wx.BITMAP_TYPE_ICO))

        # Make sure the temporal database exists
        tgis.init()

        # create temporal directory and ensure it's deleted after programs ends
        # (stored in MAPSET/.tmp/)
        global TMP_DIR
        TMP_DIR = gcore.tempdir()

        self.animations = [Animation() for i in range(MAX_COUNT)]
        self.windows = []
        self.animationPanel = AnimationsPanel(
            self, self.windows, initialCount=MAX_COUNT)
        bitmapPool = BitmapPool()
        mapFilesPool = MapFilesPool()

        self._progressDlg = None
        self._progressDlgMax = None

        self.provider = BitmapProvider(
            bitmapPool=bitmapPool,
            mapFilesPool=mapFilesPool,
            tempDir=TMP_DIR)
        self.animationSliders = {}
        self.animationSliders['nontemporal'] = SimpleAnimationSlider(self)
        self.animationSliders['temporal'] = TimeAnimationSlider(self)
        self.controller = AnimationController(frame=self,
                                              sliders=self.animationSliders,
                                              animations=self.animations,
                                              mapwindows=self.windows,
                                              provider=self.provider,
                                              bitmapPool=bitmapPool,
                                              mapFilesPool=mapFilesPool)
        for win in self.windows:
            win.Bind(wx.EVT_SIZE, self.FrameSizeChanged)
            self.provider.mapsLoaded.connect(lambda: self.SetStatusText(''))
            self.provider.renderingStarted.connect(self._showRenderingProgress)
            self.provider.renderingContinues.connect(self._updateProgress)
            self.provider.renderingFinished.connect(self._closeProgress)
            self.provider.compositionStarted.connect(
                self._showRenderingProgress)
            self.provider.compositionContinues.connect(self._updateProgress)
            self.provider.compositionFinished.connect(self._closeProgress)

        self.InitStatusbar()
        self._mgr = wx.aui.AuiManager(self)

        # toolbars
        self.toolbars = {}
        tb = ['miscToolbar', 'animationToolbar', 'mainToolbar']
        if sys.platform == 'win32':
            tb.reverse()
        for toolb in tb:
            self._addToolbar(toolb)

        self._addPanes()
        self._mgr.Update()

        self.dialogs = dict()
        self.dialogs['speed'] = None
        self.dialogs['preferences'] = None

        self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
예제 #2
0
class AnimationFrame(wx.Frame):

    def __init__(self, parent, giface, title=_("GRASS GIS 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)

        self.SetIcon(
            wx.Icon(
                os.path.join(
                    globalvar.ICONDIR,
                    'grass_map.ico'),
                wx.BITMAP_TYPE_ICO))

        # Make sure the temporal database exists
        tgis.init()

        # create temporal directory and ensure it's deleted after programs ends
        # (stored in MAPSET/.tmp/)
        global TMP_DIR
        TMP_DIR = gcore.tempdir()

        self.animations = [Animation() for i in range(MAX_COUNT)]
        self.windows = []
        self.animationPanel = AnimationsPanel(
            self, self.windows, initialCount=MAX_COUNT)
        bitmapPool = BitmapPool()
        mapFilesPool = MapFilesPool()

        self._progressDlg = None
        self._progressDlgMax = None

        self.provider = BitmapProvider(
            bitmapPool=bitmapPool,
            mapFilesPool=mapFilesPool,
            tempDir=TMP_DIR)
        self.animationSliders = {}
        self.animationSliders['nontemporal'] = SimpleAnimationSlider(self)
        self.animationSliders['temporal'] = TimeAnimationSlider(self)
        self.controller = AnimationController(frame=self,
                                              sliders=self.animationSliders,
                                              animations=self.animations,
                                              mapwindows=self.windows,
                                              provider=self.provider,
                                              bitmapPool=bitmapPool,
                                              mapFilesPool=mapFilesPool)
        for win in self.windows:
            win.Bind(wx.EVT_SIZE, self.FrameSizeChanged)
            self.provider.mapsLoaded.connect(lambda: self.SetStatusText(''))
            self.provider.renderingStarted.connect(self._showRenderingProgress)
            self.provider.renderingContinues.connect(self._updateProgress)
            self.provider.renderingFinished.connect(self._closeProgress)
            self.provider.compositionStarted.connect(
                self._showRenderingProgress)
            self.provider.compositionContinues.connect(self._updateProgress)
            self.provider.compositionFinished.connect(self._closeProgress)

        self.InitStatusbar()
        self._mgr = wx.aui.AuiManager(self)

        # toolbars
        self.toolbars = {}
        tb = ['miscToolbar', 'animationToolbar', 'mainToolbar']
        if sys.platform == 'win32':
            tb.reverse()
        for toolb in tb:
            self._addToolbar(toolb)

        self._addPanes()
        self._mgr.Update()

        self.dialogs = dict()
        self.dialogs['speed'] = None
        self.dialogs['preferences'] = None

        self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)

    def InitStatusbar(self):
        """Init statusbar."""
        self.CreateStatusBar(number=1, style=0)

    def _addPanes(self):
        self._mgr.AddPane(self.animationPanel,
                          wx.aui.AuiPaneInfo().CentrePane().
                          Name('animPanel').CentrePane().CaptionVisible(False).PaneBorder(False).
                          Floatable(False).BestSize((-1, -1)).
                          CloseButton(False).DestroyOnClose(True).Layer(0))
        for name, slider in six.iteritems(self.animationSliders):
            self._mgr.AddPane(
                slider,
                wx.aui.AuiPaneInfo().PaneBorder(False).Name(
                    'slider_' +
                    name). Layer(1).CaptionVisible(False).BestSize(
                    slider.GetBestSize()). DestroyOnClose(True).CloseButton(False).Bottom())
            self._mgr.GetPane('slider_' + name).Hide()

    def _addToolbar(self, name):
        """Add defined toolbar to the window

        Currently known toolbars are:
         - 'mainToolbar'          - data management
         - 'animationToolbar'     - animation controls
         - 'miscToolbar'          - help, close
        """
        if name == "mainToolbar":
            self.toolbars[name] = MainToolbar(self)
            self._mgr.AddPane(self.toolbars[name],
                              wx.aui.AuiPaneInfo().
                              Name('mainToolbar').Caption(_("Main Toolbar")).
                              ToolbarPane().Top().
                              LeftDockable(False).RightDockable(False).
                              BottomDockable(True).TopDockable(True).
                              CloseButton(False).Layer(2).Row(1).
                              BestSize((self.toolbars['mainToolbar'].GetBestSize())))
        elif name == 'animationToolbar':
            self.toolbars[name] = AnimationToolbar(self)
            self._mgr.AddPane(self.toolbars[name],
                              wx.aui.AuiPaneInfo().
                              Name('animationToolbar').Caption(_("Animation Toolbar")).
                              ToolbarPane().Top().
                              LeftDockable(False).RightDockable(False).
                              BottomDockable(True).TopDockable(True).
                              CloseButton(False).Layer(2).Row(1).
                              BestSize((self.toolbars['animationToolbar'].GetBestSize())))
            self.controller.SetAnimationToolbar(
                self.toolbars['animationToolbar'])
        elif name == 'miscToolbar':
            self.toolbars[name] = MiscToolbar(self)
            self._mgr.AddPane(self.toolbars[name],
                              wx.aui.AuiPaneInfo().
                              Name('miscToolbar').Caption(_("Misc Toolbar")).
                              ToolbarPane().Top().
                              LeftDockable(False).RightDockable(False).
                              BottomDockable(True).TopDockable(True).
                              CloseButton(False).Layer(2).Row(1).
                              BestSize((self.toolbars['miscToolbar'].GetBestSize())))

    def SetAnimations(self, layerLists):
        """Set animation data

        :param layerLists: list of layerLists
        """
        self.controller.SetAnimations(layerLists)

    def OnAddAnimation(self, event):
        self.controller.AddAnimation()

    def AddWindow(self, index):
        self.animationPanel.AddWindow(index)

    def RemoveWindow(self, index):
        self.animationPanel.RemoveWindow(index)

    def IsWindowShown(self, index):
        return self.animationPanel.IsWindowShown(index)

    def OnEditAnimation(self, event):
        self.controller.EditAnimations()

    def SetSlider(self, name):
        if name == 'nontemporal':
            self._mgr.GetPane('slider_nontemporal').Show()
            self._mgr.GetPane('slider_temporal').Hide()

        elif name == 'temporal':
            self._mgr.GetPane('slider_temporal').Show()
            self._mgr.GetPane('slider_nontemporal').Hide()
        else:
            self._mgr.GetPane('slider_temporal').Hide()
            self._mgr.GetPane('slider_nontemporal').Hide()
        self._mgr.Update()

    def OnPlayForward(self, event):
        self.controller.SetOrientation(Orientation.FORWARD)
        self.controller.StartAnimation()

    def OnPlayBack(self, event):
        self.controller.SetOrientation(Orientation.BACKWARD)
        self.controller.StartAnimation()

    def OnPause(self, event):
        self.controller.PauseAnimation(paused=event.IsChecked())

    def OnStop(self, event):
        self.controller.EndAnimation()

    def OnOneDirectionReplay(self, event):
        if event.IsChecked():
            mode = ReplayMode.REPEAT
        else:
            mode = ReplayMode.ONESHOT
        self.controller.SetReplayMode(mode)

    def OnBothDirectionReplay(self, event):
        if event.IsChecked():
            mode = ReplayMode.REVERSE
        else:
            mode = ReplayMode.ONESHOT
        self.controller.SetReplayMode(mode)

    def OnAdjustSpeed(self, event):
        win = self.dialogs['speed']
        if win:
            win.SetTemporalMode(self.controller.GetTemporalMode())
            win.SetTimeGranularity(self.controller.GetTimeGranularity())
            win.InitTimeSpin(self.controller.GetTimeTick())
            if win.IsShown():
                win.SetFocus()
            else:
                win.Show()
        else:  # start
            win = SpeedDialog(
                self, temporalMode=self.controller.GetTemporalMode(),
                timeGranularity=self.controller.GetTimeGranularity(),
                initialSpeed=self.controller.timeTick)
            win.CenterOnParent()
            self.dialogs['speed'] = win
            win.speedChanged.connect(self.ChangeSpeed)
            win.Show()

    def ChangeSpeed(self, ms):
        self.controller.timeTick = ms

    def Reload(self, event):
        self.controller.Reload()

    def _showRenderingProgress(self, count):
        # the message is not really visible, it's there for the initial dlg
        # size
        self._progressDlg = wx.ProgressDialog(
            title=_("Loading data"),
            message="Loading data started, please be patient.",
            maximum=count,
            parent=self,
            style=wx.PD_CAN_ABORT | wx.PD_APP_MODAL | wx.PD_AUTO_HIDE | wx.PD_SMOOTH)
        self._progressDlgMax = count

    def _updateProgress(self, current, text):
        text += _(" ({c} out of {p})").format(c=current,
                                              p=self._progressDlgMax)
        keepGoing, skip = self._progressDlg.Update(current, text)
        if not keepGoing:
            self.provider.RequestStopRendering()

    def _closeProgress(self):
        self._progressDlg.Destroy()
        self._progressDlg = None

    def OnExportAnimation(self, event):
        self.controller.Export()

    def FrameSizeChanged(self, event):
        maxWidth = maxHeight = 0
        for win in self.windows:
            w, h = win.GetClientSize()
            if w >= maxWidth and h >= maxHeight:
                maxWidth, maxHeight = w, h
        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.formatChanged.connect(
                lambda: self.controller.UpdateAnimations())
            dlg.CenterOnParent()

        self.dialogs['preferences'].ShowModal()

    def OnHelp(self, event):
        RunCommand('g.manual',
                   quiet=True,
                   entry='wxGUI.animation')

    def OnCloseWindow(self, event):
        if self.controller.timer.IsRunning():
            self.controller.timer.Stop()
        CleanUp(TMP_DIR)()
        self._mgr.UnInit()
        self.Destroy()

    def __del__(self):
        """It might not be called, therefore we try to clean it all in OnCloseWindow."""
        if hasattr(self, 'controller') and hasattr(self.controller, 'timer'):
            if self.controller.timer.IsRunning():
                self.controller.timer.Stop()
        CleanUp(TMP_DIR)()