| 1 | ## Copyright 2005, 2006, 2007, 2008 Virginia Polytechnic Institute and State University |
|---|
| 2 | ## |
|---|
| 3 | ## This file is part of the OSSIE Waveform Application Visualization Environment |
|---|
| 4 | ## |
|---|
| 5 | ## WaveDash is free software; you can redistribute it and/or modify |
|---|
| 6 | ## it under the terms of the GNU General Public License as published by |
|---|
| 7 | ## the Free Software Foundation; either version 2 of the License, or |
|---|
| 8 | ## (at your option) any later version. |
|---|
| 9 | ## |
|---|
| 10 | ## WaveDash is distributed in the hope that it will be useful, but WITHOUT ANY |
|---|
| 11 | ## WARRANTY; without even the implied warranty of |
|---|
| 12 | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 13 | ## GNU General Public License for more details. |
|---|
| 14 | ## |
|---|
| 15 | ## You should have received a copy of the GNU General Public License |
|---|
| 16 | ## along with OSSIE WaveDash; if not, write to the Free Software |
|---|
| 17 | ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|---|
| 18 | |
|---|
| 19 | import wx |
|---|
| 20 | import os |
|---|
| 21 | import WaveformModel |
|---|
| 22 | import WavedashUtils as utils |
|---|
| 23 | from wx.lib import scrolledpanel |
|---|
| 24 | from WaveformModel import WaveformListener |
|---|
| 25 | from ComponentModel import ComponentListener |
|---|
| 26 | from PropertyModel import PropertyListener |
|---|
| 27 | from WavedashButton import WavedashButton |
|---|
| 28 | from WavedashController import Controller |
|---|
| 29 | from WavedashPreferencePage import WavedashPreferencePage |
|---|
| 30 | from NSChoiceDialog import NSChoiceDialog |
|---|
| 31 | from NodeBooterDialog import NodeBooterDialog |
|---|
| 32 | |
|---|
| 33 | OSSIE_WAVEAPP_DIMENSION = (600,600) |
|---|
| 34 | OSSIE_TITLE = 'OSSIE Waveform Workshop: WaveDash Waveform Dashboard' |
|---|
| 35 | START_ICON_FILE = "/resources/start.png" |
|---|
| 36 | STOP_ICON_FILE = "/resources/stop.png" |
|---|
| 37 | UNINSTALL_ICON_FILE = "/resources/LET-U.jpg" |
|---|
| 38 | NAMINGSERVICE_ICON_FILE = "/resources/network.png" |
|---|
| 39 | REFRESH_ICON_FILE = "/resources/refresh.png" |
|---|
| 40 | NODEBOOTER_ICON_FILE = "/resources/nbstart.png" |
|---|
| 41 | |
|---|
| 42 | |
|---|
| 43 | class WavedashView(wx.Frame, WaveformListener, |
|---|
| 44 | ComponentListener, PropertyListener): |
|---|
| 45 | """ This is top level frame that acts as primary UI """ |
|---|
| 46 | def __init__(self, controller, amodel): |
|---|
| 47 | wx.Frame.__init__(self, parent=None, id=-1, title=OSSIE_TITLE ) |
|---|
| 48 | # size = OSSIE_WAVEAPP_DIMENSION) |
|---|
| 49 | #Create the model and register the frame to the listeners of |
|---|
| 50 | #Waveform, Component and Property Models. |
|---|
| 51 | |
|---|
| 52 | self.controller = controller |
|---|
| 53 | self.model = amodel |
|---|
| 54 | self.model.addWaveformListener(self) |
|---|
| 55 | self.model.addComponentListener(self) |
|---|
| 56 | self.model.addPropertyListener(self) |
|---|
| 57 | |
|---|
| 58 | self.toolbar = None |
|---|
| 59 | self.createToolBar() |
|---|
| 60 | |
|---|
| 61 | #notebook to hold the waveform panels |
|---|
| 62 | self.mainPanel = wx.Panel(self) |
|---|
| 63 | self.notebook = wx.Notebook(self.mainPanel) |
|---|
| 64 | #bind notebook to page changed event |
|---|
| 65 | self.notebook.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.OnNbPageChange, self.notebook) |
|---|
| 66 | |
|---|
| 67 | #sizers to manage the notebook |
|---|
| 68 | self.nbSizer = wx.BoxSizer() |
|---|
| 69 | self.nbSizer.Add(self.notebook, 1, wx.EXPAND) |
|---|
| 70 | self.mainPanel.SetSizer(self.nbSizer) |
|---|
| 71 | |
|---|
| 72 | self.statusBar = None |
|---|
| 73 | self.createMenus() |
|---|
| 74 | |
|---|
| 75 | |
|---|
| 76 | |
|---|
| 77 | |
|---|
| 78 | self.wpanels = [] # this list holds the panel objects of the installed waveforms |
|---|
| 79 | self.prpPopupMenus = {} #this dict is of the form {'wPanelRef':{window, popUpMenu}} |
|---|
| 80 | self.compPopupMenus = {} |
|---|
| 81 | self.tempProp = None |
|---|
| 82 | self.tempComp = None |
|---|
| 83 | |
|---|
| 84 | self.configureButtons = [] |
|---|
| 85 | |
|---|
| 86 | self.trueValues = ["t", "true", "yes", "on", "1"] |
|---|
| 87 | |
|---|
| 88 | |
|---|
| 89 | self.Bind(wx.EVT_CLOSE, self.OnClose) |
|---|
| 90 | |
|---|
| 91 | self.SetSize(OSSIE_WAVEAPP_DIMENSION) |
|---|
| 92 | self.Center() |
|---|
| 93 | self.Show() |
|---|
| 94 | |
|---|
| 95 | if not self.controller.namingServiceIsRunning(): |
|---|
| 96 | nscd = NSChoiceDialog(self) |
|---|
| 97 | |
|---|
| 98 | |
|---|
| 99 | def createToolBar(self): |
|---|
| 100 | self.toolbar = self.CreateToolBar() |
|---|
| 101 | rsize = (20, 20) |
|---|
| 102 | refreshImg = wx.ArtProvider.GetBitmap(wx.ART_REDO, wx.ART_TOOLBAR, rsize) |
|---|
| 103 | refresh = self.toolbar.AddSimpleTool(-1,refreshImg ,shortHelpString="Refresh") |
|---|
| 104 | self.Bind(wx.EVT_TOOL, self.OnRefresh, refresh) |
|---|
| 105 | |
|---|
| 106 | root = self.getRoot() |
|---|
| 107 | |
|---|
| 108 | selectNSIcon = wx.Image(root + NAMINGSERVICE_ICON_FILE, wx.BITMAP_TYPE_ANY).ConvertToBitmap() |
|---|
| 109 | selectNS = self.toolbar.AddSimpleTool(-1, selectNSIcon, shortHelpString="Configure Naming Service address") |
|---|
| 110 | |
|---|
| 111 | startIcon = wx.Image(root + START_ICON_FILE, wx.BITMAP_TYPE_ANY).ConvertToBitmap() |
|---|
| 112 | stopIcon = wx.Image(root + STOP_ICON_FILE, wx.BITMAP_TYPE_ANY).ConvertToBitmap() |
|---|
| 113 | uninstallIcon = wx.Image(root + UNINSTALL_ICON_FILE, wx.BITMAP_TYPE_ANY).ConvertToBitmap() |
|---|
| 114 | start = self.toolbar.AddSimpleTool(-1, startIcon, shortHelpString="Start waveform") |
|---|
| 115 | stop = self.toolbar.AddSimpleTool(-1, stopIcon, shortHelpString="Stop Waveform") |
|---|
| 116 | uninstall = self.toolbar.AddSimpleTool(-1, uninstallIcon, shortHelpString="Uninstall waveform") |
|---|
| 117 | |
|---|
| 118 | startNodeBooterIcon = wx.Image(root + NODEBOOTER_ICON_FILE, wx.BITMAP_TYPE_ANY).ConvertToBitmap() |
|---|
| 119 | startNodeBooter = self.toolbar.AddSimpleTool(-1, startNodeBooterIcon, shortHelpString="Start NodeBooter") |
|---|
| 120 | |
|---|
| 121 | |
|---|
| 122 | self.Bind(wx.EVT_TOOL, self.OnStart, start) |
|---|
| 123 | self.Bind(wx.EVT_TOOL, self.OnStop, stop) |
|---|
| 124 | self.Bind(wx.EVT_TOOL, self.OnUninstall, uninstall) |
|---|
| 125 | self.Bind(wx.EVT_TOOL, self.OnSelectNS, selectNS) |
|---|
| 126 | self.Bind(wx.EVT_TOOL, self.OnStartNodeBooter, startNodeBooter) |
|---|
| 127 | |
|---|
| 128 | def OnStart(self, event): |
|---|
| 129 | activeWform = self.model.getActiveWaveform() |
|---|
| 130 | if activeWform is None: |
|---|
| 131 | utils.showMessage("Start Failed!!! No waveform is running now", |
|---|
| 132 | utils.NON_FATAL) |
|---|
| 133 | return |
|---|
| 134 | status = self.controller.startWaveform(activeWform.getName()) |
|---|
| 135 | |
|---|
| 136 | def OnStop(self, event): |
|---|
| 137 | activeWform = self.model.getActiveWaveform() |
|---|
| 138 | if activeWform is None: |
|---|
| 139 | utils.showMessage("Stop Failed!!! No waveform is running now", |
|---|
| 140 | utils.NON_FATAL) |
|---|
| 141 | return |
|---|
| 142 | status = self.controller.stopWaveform(activeWform.getName()) |
|---|
| 143 | |
|---|
| 144 | def OnUninstall(self, event): |
|---|
| 145 | selWform = self.model.getActiveWaveform() |
|---|
| 146 | if selWform is None: |
|---|
| 147 | utils.showMessage("Uninstall Failed!!! No waveform is running now", |
|---|
| 148 | utils.NON_FATAL) |
|---|
| 149 | return |
|---|
| 150 | |
|---|
| 151 | #iterate through a slice of the whole list rather than |
|---|
| 152 | #the list itself so prevent errors |
|---|
| 153 | for button in self.configureButtons[:]: |
|---|
| 154 | if(button.isWaveformButton == True and button.getParentName() == selWform.getName()): |
|---|
| 155 | self.configureButtons.remove(button) |
|---|
| 156 | |
|---|
| 157 | for button in self.configureButtons[:]: |
|---|
| 158 | if(button.isComponentButton == True and button.getGrandParentName() == selWform.getName()): |
|---|
| 159 | self.configureButtons.remove(button) |
|---|
| 160 | |
|---|
| 161 | success = self.model.removeWaveform(selWform) |
|---|
| 162 | |
|---|
| 163 | def OnSelectNS(self, event): |
|---|
| 164 | self.controller.selectNS() |
|---|
| 165 | |
|---|
| 166 | def OnStartNodeBooter(self, event): |
|---|
| 167 | nbd = NodeBooterDialog(self) |
|---|
| 168 | |
|---|
| 169 | if nbd.GetReturnCode() == 0: |
|---|
| 170 | self.controller.CORBAutils.setNamingService('127.0.0.1') |
|---|
| 171 | self.controller.CORBAutils.init_CORBA() |
|---|
| 172 | self.controller.refresh() |
|---|
| 173 | |
|---|
| 174 | def createMenus(self): |
|---|
| 175 | menuBar = wx.MenuBar() |
|---|
| 176 | #These features are not yet implemented in 0.7.3 |
|---|
| 177 | # fileMenu = wx.Menu() |
|---|
| 178 | # openLayout = fileMenu.Append(-1, '&Open Layout') |
|---|
| 179 | # saveLayout = fileMenu.Append(-1, '&Save Layout') |
|---|
| 180 | # saveLayoutAs = fileMenu.Append(-1, 'S&ave Layout As') |
|---|
| 181 | # exit = fileMenu.Append(-1, 'E&xit\tCtrl-Q') |
|---|
| 182 | # |
|---|
| 183 | # self.Bind(wx.EVT_MENU, self.OnOpenLayout, openLayout) |
|---|
| 184 | # self.Bind(wx.EVT_MENU, self.OnSaveLayout, saveLayout) |
|---|
| 185 | # self.Bind(wx.EVT_MENU, self.OnSaveLayoutAs, saveLayoutAs) |
|---|
| 186 | # self.Bind(wx.EVT_MENU, self.OnExit, exit) |
|---|
| 187 | # |
|---|
| 188 | waveformsMenu = wx.Menu() |
|---|
| 189 | componentsMenu = wx.Menu() |
|---|
| 190 | optionsMenu = wx.Menu() |
|---|
| 191 | self.updateOnRefresh = optionsMenu.Append(501, 'Update Properties on Refresh', 'Update Properties on Refresh', kind=wx.ITEM_CHECK) |
|---|
| 192 | self.preferences = optionsMenu.Append(502, 'Wavedash Preferences', 'Wavedash Preferences', kind=wx.ITEM_NORMAL) |
|---|
| 193 | self.updateOnRefresh.Check(False) |
|---|
| 194 | self.Bind(wx.EVT_MENU, self.OnUpdateOnRefreshCheck, self.updateOnRefresh) |
|---|
| 195 | self.Bind(wx.EVT_MENU, self.OpenPreferences, self.preferences) |
|---|
| 196 | |
|---|
| 197 | # preferencesMenu = wx.Menu() |
|---|
| 198 | # widgetSettings = preferencesMenu.Append(-1, '&Widget Settings') |
|---|
| 199 | # self.Bind(wx.EVT_MENU, self.OnWidgetSettings,widgetSettings) |
|---|
| 200 | # |
|---|
| 201 | helpMenu = wx.Menu() |
|---|
| 202 | about = helpMenu.Append(-1,'&About') |
|---|
| 203 | self.Bind(wx.EVT_MENU, self.OnAbout, about) |
|---|
| 204 | |
|---|
| 205 | # menuBar.Append(fileMenu, '&File') |
|---|
| 206 | menuBar.Append(waveformsMenu, '&Waveforms') |
|---|
| 207 | #waveformsMenu.AppendSeparator() |
|---|
| 208 | menuBar.Append(componentsMenu, '&Components') |
|---|
| 209 | #menuBar.Append(preferencesMenu, '&Preferences') |
|---|
| 210 | menuBar.Append(optionsMenu, '&Options') |
|---|
| 211 | menuBar.Append(helpMenu, '&Help') |
|---|
| 212 | |
|---|
| 213 | self.SetMenuBar(menuBar) |
|---|
| 214 | |
|---|
| 215 | def createWaveformPanel(self, parent, waveform, preview = False): |
|---|
| 216 | # if(waveform.name == "w1_1"): |
|---|
| 217 | #print "in createWaveform Panel" |
|---|
| 218 | #for comp in waveform.components: |
|---|
| 219 | # for prop in comp.properties: |
|---|
| 220 | # print str(prop.id) + ": " + str(prop.getValue()) |
|---|
| 221 | |
|---|
| 222 | wPanel = scrolledpanel.ScrolledPanel(parent, -1, name=waveform.getName()) |
|---|
| 223 | wSizer = wx.BoxSizer(wx.VERTICAL) |
|---|
| 224 | componentList = waveform.getAllComponents() |
|---|
| 225 | |
|---|
| 226 | |
|---|
| 227 | |
|---|
| 228 | for component in componentList: |
|---|
| 229 | cPanel = self.createComponentPanel(wPanel,component, preview) |
|---|
| 230 | wSizer.Add(cPanel, 0, wx.ALIGN_LEFT | wx.GROW, 10) |
|---|
| 231 | |
|---|
| 232 | wSizer.AddSpacer(10) |
|---|
| 233 | |
|---|
| 234 | root = self.getRoot() |
|---|
| 235 | refreshIcon = wx.Image(root + REFRESH_ICON_FILE, wx.BITMAP_TYPE_ANY).ConvertToBitmap() |
|---|
| 236 | |
|---|
| 237 | updateWaveformButton = WavedashButton(wPanel, wx.NewId(), refreshIcon) |
|---|
| 238 | updateWaveformButton.setParentName(waveform.getName()) |
|---|
| 239 | updateWaveformButton.setGrandParentName("none") |
|---|
| 240 | updateWaveformButton.setIsWaveformButton() |
|---|
| 241 | updateWaveformButton.Enable(self.updateOnRefresh.IsChecked()) |
|---|
| 242 | wPanel.Bind(wx.EVT_BUTTON, self.OnUpdateWaveformClicked, updateWaveformButton) |
|---|
| 243 | |
|---|
| 244 | self.configureButtons.append(updateWaveformButton) |
|---|
| 245 | wSizer.Add(updateWaveformButton, flag=wx.ALIGN_RIGHT) |
|---|
| 246 | |
|---|
| 247 | wPanel.SetSizer(wSizer) |
|---|
| 248 | wPanel.SetupScrolling(True, True, 20, 20) |
|---|
| 249 | |
|---|
| 250 | #No need to add the panels to the wpanels list when preview is On |
|---|
| 251 | if preview is False: |
|---|
| 252 | self.wpanels.append(wPanel) |
|---|
| 253 | |
|---|
| 254 | wSizer.Fit(wPanel) |
|---|
| 255 | return wPanel |
|---|
| 256 | |
|---|
| 257 | def createComponentPanel(self, wPanel, component, preview = False): |
|---|
| 258 | cPanel = wx.Panel(wPanel, -1, name=component.getName()) |
|---|
| 259 | component.setPanel(cPanel) |
|---|
| 260 | sbox = wx.StaticBox(cPanel, -1, component.getName()) |
|---|
| 261 | sboxSizer = wx.StaticBoxSizer(sbox, wx.VERTICAL) |
|---|
| 262 | prpWidgetList = [] |
|---|
| 263 | |
|---|
| 264 | root = self.getRoot() |
|---|
| 265 | |
|---|
| 266 | if not component.isVisible(): |
|---|
| 267 | cPanel.Hide() |
|---|
| 268 | |
|---|
| 269 | propertyList = component.getAllProperties() |
|---|
| 270 | #properites of a component are laid on the component panel using a gridbag sizer |
|---|
| 271 | #Each widget takes one cell except a Slider which spans across multiple columns |
|---|
| 272 | # if(component.parent.name == "w1_1"): |
|---|
| 273 | # print "in addComponentPanel" |
|---|
| 274 | # for prop in component.properties: |
|---|
| 275 | # print str(prop.id) + ": " + str(prop.getValue()) |
|---|
| 276 | |
|---|
| 277 | for property in propertyList: |
|---|
| 278 | widget = property.getWidget() |
|---|
| 279 | |
|---|
| 280 | plabel = wx.StaticText(cPanel, -1, property.getName(), name = property.getName()) |
|---|
| 281 | pWindow = self.mapWidgetToWindow(cPanel, property, widget) |
|---|
| 282 | pWindow.SetToolTipString(property.getDesc()) |
|---|
| 283 | property.setWindow(pWindow) |
|---|
| 284 | |
|---|
| 285 | if not property.isVisible(): |
|---|
| 286 | plabel.Hide() |
|---|
| 287 | pWindow.Hide() |
|---|
| 288 | |
|---|
| 289 | if preview is True: |
|---|
| 290 | #Don't allow any manipulation on properties in Preview form. |
|---|
| 291 | pWindow.Enable(False) |
|---|
| 292 | |
|---|
| 293 | #Create a popup menu for this property |
|---|
| 294 | self.attachPopupMenuToProp(wPanel, pWindow, property) |
|---|
| 295 | |
|---|
| 296 | windowType = pWindow.__class__ |
|---|
| 297 | eventType = wx.EVT_KILL_FOCUS |
|---|
| 298 | |
|---|
| 299 | #Find the type of event corresponding to the window in use |
|---|
| 300 | if windowType is wx.TextCtrl or windowType is wx.SpinCtrl: |
|---|
| 301 | pWindow.Bind(wx.EVT_TEXT_ENTER, self.OnPropValueChanged, pWindow) |
|---|
| 302 | pWindow.Bind(wx.EVT_KILL_FOCUS, self.OnPropValueChanged, pWindow) |
|---|
| 303 | elif windowType is wx.Slider: |
|---|
| 304 | pWindow.Bind(wx.EVT_COMMAND_SCROLL, self.OnPropValueChanged, pWindow) |
|---|
| 305 | elif windowType is wx.CheckBox: |
|---|
| 306 | pWindow.Bind(wx.EVT_CHECKBOX, self.OnPropValueChanged, pWindow) |
|---|
| 307 | |
|---|
| 308 | #checkbox has a label associated with itself. so no need to add separate label |
|---|
| 309 | if pWindow.__class__ is wx.CheckBox: |
|---|
| 310 | plabel.SetLabel("") |
|---|
| 311 | |
|---|
| 312 | |
|---|
| 313 | |
|---|
| 314 | prpWidgetList.append(plabel) |
|---|
| 315 | prpWidgetList.append(pWindow) |
|---|
| 316 | |
|---|
| 317 | #prpWidgetList contains the label and widgets for all the properties of this component |
|---|
| 318 | #addPropToCompSizer creates a new gridbagsizer and adds the labels and widgets contained |
|---|
| 319 | #in the prpWidgetList |
|---|
| 320 | |
|---|
| 321 | gbagSizer = self.addPropToCompSizer(prpWidgetList) |
|---|
| 322 | |
|---|
| 323 | |
|---|
| 324 | |
|---|
| 325 | sboxSizer.SetMinSize(gbagSizer.GetMinSize()) |
|---|
| 326 | sboxSizer.Add(gbagSizer, 1, wx.ALIGN_CENTER | wx.EXPAND, 10) |
|---|
| 327 | |
|---|
| 328 | refreshIcon = wx.Image(root + REFRESH_ICON_FILE, wx.BITMAP_TYPE_ANY).ConvertToBitmap() |
|---|
| 329 | |
|---|
| 330 | updateComponentButton = WavedashButton(cPanel, wx.NewId(), refreshIcon ) |
|---|
| 331 | updateComponentButton.setParentName(component.getName()) |
|---|
| 332 | updateComponentButton.setGrandParentName(component.getParent().getName()) |
|---|
| 333 | updateComponentButton.setIsComponentButton() |
|---|
| 334 | updateComponentButton.Enable(self.updateOnRefresh.IsChecked()) |
|---|
| 335 | cPanel.Bind(wx.EVT_BUTTON, self.OnUpdateComponentClicked, updateComponentButton) |
|---|
| 336 | self.configureButtons.append(updateComponentButton) |
|---|
| 337 | sboxSizer.Add(updateComponentButton, flag=wx.ALIGN_RIGHT) |
|---|
| 338 | |
|---|
| 339 | |
|---|
| 340 | |
|---|
| 341 | cPanel.SetSizer(sboxSizer) |
|---|
| 342 | |
|---|
| 343 | #After layingout the widgets (labels & controls) for all the properties, |
|---|
| 344 | #attach a popupmenu at component level. i.e. for each component panel |
|---|
| 345 | |
|---|
| 346 | self.attachPopupToComponent(component, cPanel) |
|---|
| 347 | return cPanel |
|---|
| 348 | |
|---|
| 349 | def addPropToCompSizer(self, propList): |
|---|
| 350 | #IMPORTANT NOTE: proplist should have items in the following way. |
|---|
| 351 | #[label, window, label, window, label, window, .... ] |
|---|
| 352 | index = 0 |
|---|
| 353 | gridSizer = wx.GridSizer(2,4,5,5) |
|---|
| 354 | |
|---|
| 355 | while (index < len(propList) ): |
|---|
| 356 | plabel = propList[index] |
|---|
| 357 | pWindow = propList[index+1] |
|---|
| 358 | |
|---|
| 359 | #if the windows are hidden, don't add them to the sizer. |
|---|
| 360 | #They will be added when the user select the properties again. |
|---|
| 361 | if (not plabel.IsShown()) or (not pWindow.IsShown()): |
|---|
| 362 | index = index + 2 |
|---|
| 363 | continue |
|---|
| 364 | gridSizer.Add(plabel, 0) |
|---|
| 365 | gridSizer.Add(pWindow, 0) |
|---|
| 366 | index = index + 2 |
|---|
| 367 | return gridSizer |
|---|
| 368 | |
|---|
| 369 | def attachPopupToComponent(self, component, cPanel): |
|---|
| 370 | cPopup = wx.Menu(title='') |
|---|
| 371 | moveUp = cPopup.Append(wx.NewId(), 'Move up') |
|---|
| 372 | moveDown = cPopup.Append(wx.NewId(), 'Move Down') |
|---|
| 373 | save = cPopup.Append(wx.NewId(), 'Save') |
|---|
| 374 | saveAs = cPopup.Append(wx.NewId(), 'Save As') |
|---|
| 375 | |
|---|
| 376 | #save and saveAs will be implemented in next release.disable for now |
|---|
| 377 | save.Enable(False) |
|---|
| 378 | saveAs.Enable(False) |
|---|
| 379 | |
|---|
| 380 | prpMenu = wx.Menu() |
|---|
| 381 | #All properties are enabled by default. |
|---|
| 382 | prpList = component.getAllProperties() |
|---|
| 383 | for prp in prpList: |
|---|
| 384 | chkMenuItem = prpMenu.AppendCheckItem(wx.NewId(), prp.getName()) |
|---|
| 385 | chkMenuItem.Check(True) |
|---|
| 386 | self.Bind(wx.EVT_MENU, self.OnPropertySelect, chkMenuItem) |
|---|
| 387 | |
|---|
| 388 | cPopup.AppendMenu(wx.NewId(), 'Properties', prpMenu) |
|---|
| 389 | |
|---|
| 390 | wPanel = cPanel.GetParent() |
|---|
| 391 | |
|---|
| 392 | if self.compPopupMenus.has_key(wPanel): |
|---|
| 393 | cPanelDict = self.compPopupMenus[wPanel] |
|---|
| 394 | if cPanelDict.has_key(cPanel.GetName()) is False: |
|---|
| 395 | cPanelDict[str(cPanel.GetName())] = cPopup |
|---|
| 396 | else: |
|---|
| 397 | self.compPopupMenus[wPanel] = {cPanel.GetName():cPopup} |
|---|
| 398 | |
|---|
| 399 | self.Bind(wx.EVT_MENU, self.OnComponentMoveUp, moveUp) |
|---|
| 400 | self.Bind(wx.EVT_MENU, self.OnComponentMoveDown, moveDown) |
|---|
| 401 | |
|---|
| 402 | cPanel.Bind(wx.EVT_RIGHT_DOWN, self.OnComponentRightClick) |
|---|
| 403 | |
|---|
| 404 | |
|---|
| 405 | def OnComponentRightClick(self, event): |
|---|
| 406 | src = event.GetEventObject() |
|---|
| 407 | curWPanel = self.getCurrentPanel() |
|---|
| 408 | #Storing the reference to current component panel in a temp variable |
|---|
| 409 | #This temp will be used to map the context menu and the component menu in |
|---|
| 410 | #the event handler for PropertySelect and other items in Context menu also. |
|---|
| 411 | |
|---|
| 412 | self.tempComp = src |
|---|
| 413 | for wpanel in self.compPopupMenus.keys(): |
|---|
| 414 | if wpanel is curWPanel: |
|---|
| 415 | windowDict = self.compPopupMenus[wpanel] |
|---|
| 416 | src.PopupMenu(windowDict[str(src.GetName())]) |
|---|
| 417 | |
|---|
| 418 | def attachPopupMenuToProp(self, wPanel, window, property): |
|---|
| 419 | pSubMenu = wx.Menu(title='') |
|---|
| 420 | #default = property.getWidget() |
|---|
| 421 | default = self.controller.getDefaultWidget(property.getType()) |
|---|
| 422 | optList = self.controller.getOptionalWidgets(property.getType()) |
|---|
| 423 | |
|---|
| 424 | mItem = pSubMenu.AppendRadioItem(wx.NewId(), default.type) |
|---|
| 425 | self.Bind(wx.EVT_MENU, self.PropPopupHandler, id = mItem.GetId()) |
|---|
| 426 | for optWidget in optList: |
|---|
| 427 | mItem = pSubMenu.AppendRadioItem(wx.NewId(), optWidget.type) |
|---|
| 428 | self.Bind(wx.EVT_MENU, self.PropPopupHandler, id = mItem.GetId()) |
|---|
| 429 | if property.getWidget().type == optWidget.type: |
|---|
| 430 | mItem.Check(True) |
|---|
| 431 | |
|---|
| 432 | pSubMenu.AppendSeparator() |
|---|
| 433 | configure = pSubMenu.Append(wx.NewId(), 'Configure') |
|---|
| 434 | self.Bind(wx.EVT_MENU, self.PropConfigureHandler, id = configure.GetId()) |
|---|
| 435 | |
|---|
| 436 | #Configure shuold be enabled only for slider and spin buttons. |
|---|
| 437 | #If other options are enabled, then disable the Configure Menu Item |
|---|
| 438 | self.propPopUpUpdate(pSubMenu) |
|---|
| 439 | |
|---|
| 440 | chgMenu = wx.Menu(title='') |
|---|
| 441 | chgMenuItem = wx.MenuItem(chgMenu, wx.NewId(), 'Change To', subMenu = pSubMenu) |
|---|
| 442 | chgMenu.AppendItem(chgMenuItem) |
|---|
| 443 | |
|---|
| 444 | #Associate the pop Menu with the window |
|---|
| 445 | cpRef = property.getParent().getName() + '/' + property.getName() |
|---|
| 446 | |
|---|
| 447 | if self.prpPopupMenus.has_key(wPanel): |
|---|
| 448 | subDict = self.prpPopupMenus[wPanel] |
|---|
| 449 | if subDict.has_key(cpRef) is False: |
|---|
| 450 | subDict[cpRef] = chgMenu |
|---|
| 451 | else: |
|---|
| 452 | self.prpPopupMenus[wPanel] = {cpRef:chgMenu} |
|---|
| 453 | |
|---|
| 454 | window.Bind(wx.EVT_RIGHT_DOWN, self.OnPropRightClick) |
|---|
| 455 | |
|---|
| 456 | def OnPropRightClick(self, event): |
|---|
| 457 | src = event.GetEventObject() |
|---|
| 458 | curPanel = self.getCurrentPanel() |
|---|
| 459 | #The widget(actual wxPython windows) on which the Popupmenu is invoked is |
|---|
| 460 | #stored in a temp variable to access it later during the events generated |
|---|
| 461 | #by PopUpMenu |
|---|
| 462 | |
|---|
| 463 | self.tempProp = src |
|---|
| 464 | for wpanel in self.prpPopupMenus.keys(): |
|---|
| 465 | if wpanel is curPanel: |
|---|
| 466 | |
|---|
| 467 | #=============================================================================== |
|---|
| 468 | # A pop-up menu is associated with each property. the member variable prpPopupMenus |
|---|
| 469 | # is a hash object indexed by waveform names. Value of a hash object points to another |
|---|
| 470 | # hash which indexes the popup menus by component_name/property_name. |
|---|
| 471 | #=============================================================================== |
|---|
| 472 | |
|---|
| 473 | windowDict = self.prpPopupMenus[wpanel] |
|---|
| 474 | cpRef = src.GetParent().GetName() + '/' + src.GetName() |
|---|
| 475 | src.GetParent().PopupMenu(windowDict[cpRef]) |
|---|
| 476 | |
|---|
| 477 | |
|---|
| 478 | def PropPopupHandler(self, event): |
|---|
| 479 | srcId = event.GetId() |
|---|
| 480 | mItems = event.GetEventObject().GetMenuItems() |
|---|
| 481 | |
|---|
| 482 | #Enable the configure option only slider and spin box to set their min and |
|---|
| 483 | #max values. |
|---|
| 484 | |
|---|
| 485 | self.propPopUpUpdate(event.GetEventObject()) |
|---|
| 486 | |
|---|
| 487 | for mItem in mItems: |
|---|
| 488 | if mItem.GetId() == srcId: |
|---|
| 489 | #self.tempProp is set to identify the property when Popupmenu is invoked. |
|---|
| 490 | property = self.tempProp |
|---|
| 491 | component = property.GetParent() |
|---|
| 492 | wform = component.GetParent() |
|---|
| 493 | wformRef = self.model.getActiveWaveform() |
|---|
| 494 | compRef = wformRef.getComponent(component.GetName()) |
|---|
| 495 | propRef = compRef.findPropertyByName(property.GetName()) |
|---|
| 496 | self.model.changePropertyWidget(component.GetName(), |
|---|
| 497 | property.GetName(), mItem.GetItemLabel()) |
|---|
| 498 | |
|---|
| 499 | |
|---|
| 500 | def PropConfigureHandler(self, event): |
|---|
| 501 | propertyCtrl = self.tempProp |
|---|
| 502 | cPanel = propertyCtrl.GetParent() |
|---|
| 503 | wPanel = cPanel.GetParent() |
|---|
| 504 | |
|---|
| 505 | #Get reference to the property thruogh its compnent and waveform. |
|---|
| 506 | #Then, get the widget reference from the property |
|---|
| 507 | wform = self.model.getActiveWaveform() |
|---|
| 508 | component = wform.getComponent(cPanel.GetName()) |
|---|
| 509 | property = component.findPropertyByName(propertyCtrl.GetName()) |
|---|
| 510 | |
|---|
| 511 | widget = property.getWidget() |
|---|
| 512 | |
|---|
| 513 | if propertyCtrl.__class__ is wx.SpinCtrl \ |
|---|
| 514 | or propertyCtrl.__class__ is wx.Slider: |
|---|
| 515 | curMin, curMax = property.getRange() |
|---|
| 516 | curValue = property.getValue() |
|---|
| 517 | #curMin = widget.getMin() |
|---|
| 518 | #curMax = widget.getMax() |
|---|
| 519 | title = 'Widget Configuration' |
|---|
| 520 | confDialog = utils.ConfigureWidget(self, title, curValue) |
|---|
| 521 | confDialog.setMin(curMin) |
|---|
| 522 | confDialog.setMax(curMax) |
|---|
| 523 | |
|---|
| 524 | confDialog.ShowModal() |
|---|
| 525 | |
|---|
| 526 | #Get the new min and max once the dialog is destroyed in the |
|---|
| 527 | #event handlers of Ok and Cancel defined in ConfigureWidget |
|---|
| 528 | newMin = confDialog.getMin() |
|---|
| 529 | newMax = confDialog.getMax() |
|---|
| 530 | |
|---|
| 531 | #No need to udpate the model if the values are not changed |
|---|
| 532 | if (newMin == curMin) and (newMax == curMax): |
|---|
| 533 | return |
|---|
| 534 | else: |
|---|
| 535 | # the newMin and newMax values will be updated to the range attribute of the property |
|---|
| 536 | status = self.model.configurePropertyWidget(cPanel.GetName(), propertyCtrl.GetName(), newMin, newMax) |
|---|
| 537 | if status is False: |
|---|
| 538 | utils.showMessage("Invalid range of values (" + str(newMin) + "," + str(newMax) + ")" , utils.NON_FATAL) |
|---|
| 539 | return |
|---|
| 540 | |
|---|
| 541 | def propPopUpUpdate(self, menu): |
|---|
| 542 | menuItems = menu.GetMenuItems() |
|---|
| 543 | confItemId = menu.FindItem('Configure') |
|---|
| 544 | confItem = menu.FindItemById(confItemId) |
|---|
| 545 | confItem.Enable(False) |
|---|
| 546 | |
|---|
| 547 | for mItem in menuItems: |
|---|
| 548 | if mItem.GetItemLabel() == "spin" or mItem.GetItemLabel() == "slider": |
|---|
| 549 | if mItem.IsChecked(): |
|---|
| 550 | confItem.Enable(True) |
|---|
| 551 | |
|---|
| 552 | def mapWidgetToWindow(self, parent, property, widget): |
|---|
| 553 | window = None |
|---|
| 554 | label = None |
|---|
| 555 | pValue = property.getValue() |
|---|
| 556 | |
|---|
| 557 | widgetType = widget.type |
|---|
| 558 | |
|---|
| 559 | if widgetType == "text": |
|---|
| 560 | window = wx.TextCtrl(parent, -1, str(pValue), style = wx.TE_PROCESS_ENTER) |
|---|
| 561 | elif widgetType == "spin": |
|---|
| 562 | minV, maxV = property.getRange() |
|---|
| 563 | window = wx.SpinCtrl(parent, -1, str(pValue), min = minV, max = maxV, style = wx.TE_PROCESS_ENTER) |
|---|
| 564 | elif widgetType == "slider": |
|---|
| 565 | minV, maxV = property.getRange() |
|---|
| 566 | if widget.parameters["style"] == "HORIZONTAL": |
|---|
| 567 | styleV = wx.SL_HORIZONTAL | wx.SL_LABELS |
|---|
| 568 | elif widget.parameters["style"] == "VERTICAL": |
|---|
| 569 | styleV = wx.SL_VERTICAL | wx.SL_LABELS |
|---|
| 570 | window = wx.Slider(parent, -1, int(pValue), minValue = minV, maxValue = maxV, style = styleV, size=(120,35)) |
|---|
| 571 | elif widgetType == "checkbox": |
|---|
| 572 | window = wx.CheckBox(parent, -1, property.getName()) |
|---|
| 573 | elif widgetType == "listbox": |
|---|
| 574 | if (pValue is not None) and (type(pValue) is list): |
|---|
| 575 | window = wx.TextCtrl(parent, -1, str(pValue)) |
|---|
| 576 | else: |
|---|
| 577 | window = wx.TextCtrl(parent, -1, str(None)) |
|---|
| 578 | else: |
|---|
| 579 | window = wx.TextCtrl(parent, -1, str(pValue)) |
|---|
| 580 | |
|---|
| 581 | if window is not None: |
|---|
| 582 | window.SetName(property.getName()) |
|---|
| 583 | return window |
|---|
| 584 | |
|---|
| 585 | def OnPropValueChanged(self, event): |
|---|
| 586 | if(self.updateOnRefresh.IsChecked()): |
|---|
| 587 | return |
|---|
| 588 | src = event.GetEventObject() |
|---|
| 589 | prp = src.GetName() |
|---|
| 590 | comp = src.GetParent().GetName() |
|---|
| 591 | wName = src.GetParent().GetParent().GetName() |
|---|
| 592 | wform = self.model.getWaveform(wName, WaveformModel.INSTANCE_WAVEFORM) |
|---|
| 593 | #This event is triggered whenever a property widget loses its focus. |
|---|
| 594 | #A widget loses its focus when the user switch to another widget in the same window |
|---|
| 595 | #or select a different waveform. |
|---|
| 596 | if wform is None: |
|---|
| 597 | #if event triggered as a result of object destroy or from Waveform Preview Dialog |
|---|
| 598 | #then no need to update the value. Just return |
|---|
| 599 | return |
|---|
| 600 | |
|---|
| 601 | compRef = wform.getComponent(comp) |
|---|
| 602 | prpRef = compRef.findPropertyByName(prp) |
|---|
| 603 | |
|---|
| 604 | curVal = self.formatWidgetToModel(src.GetValue(), prpRef.getType()) |
|---|
| 605 | preVal = prpRef.getValue() |
|---|
| 606 | |
|---|
| 607 | |
|---|
| 608 | if curVal is not None: |
|---|
| 609 | |
|---|
| 610 | #if both the values are equal then no need to call configure() |
|---|
| 611 | if preVal == curVal: |
|---|
| 612 | #in cases where a boolean property was changed to a different |
|---|
| 613 | #text value but the same boolean value (ie True changed to 1) |
|---|
| 614 | #the model won't configure since the actual value didnt change |
|---|
| 615 | #so we have to call formatModelToWidget to change the text back |
|---|
| 616 | # to True or False |
|---|
| 617 | if(prpRef.type[1] == "boolean"): |
|---|
| 618 | self.formatModelToWidget(src, curVal) |
|---|
| 619 | return |
|---|
| 620 | else: |
|---|
| 621 | #print "configuring: wName = " + str(wName) + ", comp = " + str(comp) + ", prp = " + str(prp) + ", curVal = " + str(curVal) |
|---|
| 622 | status = self.model.configure(wName, comp, prp, curVal) |
|---|
| 623 | |
|---|
| 624 | #leave the text box as it is if status is True |
|---|
| 625 | #if the configure operation failed, revert the text value to the value stored in |
|---|
| 626 | #the model. |
|---|
| 627 | if status is False: |
|---|
| 628 | msg = "Could not configure " + prp |
|---|
| 629 | utils.showMessage(msg, utils.NON_FATAL) |
|---|
| 630 | self.formatModelToWidget(src, preVal) |
|---|
| 631 | #src.SetValue(str(preVal)) |
|---|
| 632 | elif prpRef.type[1] == "boolean": |
|---|
| 633 | self.formatModelToWidget(src, curVal) |
|---|
| 634 | |
|---|
| 635 | else: |
|---|
| 636 | msg = "Invalid value for %s/%s" % (comp, prp) + "\nEnter only '" + prpRef.getType()[1] + "' values" |
|---|
| 637 | msg = msg + "\nFor sequence types, enter values separated by comma" |
|---|
| 638 | msg = msg + " and enclosed within [] e.g. [10,20,30]" |
|---|
| 639 | |
|---|
| 640 | utils.showMessage(msg, utils.NON_FATAL) |
|---|
| 641 | self.formatModelToWidget(src, preVal) |
|---|
| 642 | self.Layout() |
|---|
| 643 | |
|---|
| 644 | |
|---|
| 645 | def formatModelToWidget(self, widget, value): |
|---|
| 646 | if widget.__class__ is wx.TextCtrl: |
|---|
| 647 | widget.SetValue(str(value)) |
|---|
| 648 | elif widget.__class__ is wx.SpinCtrl: |
|---|
| 649 | widget.SetValue(int(value)) |
|---|
| 650 | elif widget.__class__ is wx.Slider: |
|---|
| 651 | widget.SetValue(int(value)) |
|---|
| 652 | elif widget.__class__ is wx.CheckBox: |
|---|
| 653 | if value == "True" or value == 1: |
|---|
| 654 | widget.SetValue(True) |
|---|
| 655 | else: |
|---|
| 656 | widget.SetValue(False) |
|---|
| 657 | |
|---|
| 658 | |
|---|
| 659 | |
|---|
| 660 | def formatWidgetToModel(self, curVal, propType): |
|---|
| 661 | """ Converts the string literal into the suitable data type |
|---|
| 662 | as configured for the property""" |
|---|
| 663 | val = None |
|---|
| 664 | #propType is a tuple containing the (xmlType,datatype) |
|---|
| 665 | #e.g. ('simple','short') |
|---|
| 666 | xmlType = propType[0] |
|---|
| 667 | dtype = propType[1] |
|---|
| 668 | |
|---|
| 669 | try: |
|---|
| 670 | if (xmlType == "simple"): |
|---|
| 671 | if dtype == "short" or dtype == "ushort": |
|---|
| 672 | val = int(curVal) |
|---|
| 673 | elif dtype == "int" or dtype == "uint": |
|---|
| 674 | val = int(curVal) |
|---|
| 675 | elif dtype == "long" or dtype == "ulong": |
|---|
| 676 | val = long(curVal) |
|---|
| 677 | elif dtype == "double" or dtype == "float": |
|---|
| 678 | val = float(curVal) |
|---|
| 679 | elif dtype == "char": |
|---|
| 680 | val = str(curVal) |
|---|
| 681 | elif dtype == "boolean": |
|---|
| 682 | if str(curVal).lower() in self.trueValues: |
|---|
| 683 | val = True |
|---|
| 684 | else: |
|---|
| 685 | val = False |
|---|
| 686 | elif dtype == "string": |
|---|
| 687 | val = str(curVal) |
|---|
| 688 | else: |
|---|
| 689 | val = None |
|---|
| 690 | #sequence values are represented as list of values separated |
|---|
| 691 | #by a comma. e.g. '[10,20,30]' |
|---|
| 692 | |
|---|
| 693 | elif (xmlType == "simplesequence"): |
|---|
| 694 | if dtype == "float": |
|---|
| 695 | val = [] |
|---|
| 696 | #strip the open and close bracket |
|---|
| 697 | listVal = curVal.lstrip('[') |
|---|
| 698 | listVal = listVal.rstrip(']') |
|---|
| 699 | for lVal in listVal.split(','): |
|---|
| 700 | val.append(float(lVal)) |
|---|
| 701 | if dtype == "string": |
|---|
| 702 | val = [] |
|---|
| 703 | #strip the open and close bracket |
|---|
| 704 | listVal = curVal.lstrip('[') |
|---|
| 705 | listVal = listVal.rstrip(']') |
|---|
| 706 | for lVal in listVal.split(','): |
|---|
| 707 | val.append(str(lVal)) |
|---|
| 708 | if dtype == "short" or dtype == "int": |
|---|
| 709 | val = [] |
|---|
| 710 | #strip the open and close bracket |
|---|
| 711 | listVal = curVal.lstrip('[') |
|---|
| 712 | listVal = listVal.rstrip(']') |
|---|
| 713 | for lVal in listVal.split(','): |
|---|
| 714 | val.append(int(lVal)) |
|---|
| 715 | |
|---|
| 716 | except(ValueError): |
|---|
| 717 | val = None |
|---|
| 718 | |
|---|
| 719 | return val |
|---|
| 720 | |
|---|
| 721 | def AddToWaveformsMenu(self, newWaveform, type): |
|---|
| 722 | wMenu = self.FindMenuInMenuBar('Waveforms') |
|---|
| 723 | |
|---|
| 724 | if type == WaveformModel.SYSTEM_WAVEFORM: |
|---|
| 725 | wSubMenu = wx.Menu() |
|---|
| 726 | install = wSubMenu.Append(-1, 'Install') |
|---|
| 727 | installAndStart = wSubMenu.Append(-1, 'Install and Start') |
|---|
| 728 | viewWform = wSubMenu.Append(-1, 'Preview') |
|---|
| 729 | properties = wSubMenu.Append(-1, 'Properties') |
|---|
| 730 | |
|---|
| 731 | wMenu.InsertMenu(0,-1, newWaveform, wSubMenu) #insert at the start of the list |
|---|
| 732 | |
|---|
| 733 | self.Bind(wx.EVT_MENU, self.OnWaveformInstall, install) |
|---|
| 734 | self.Bind(wx.EVT_MENU, self.OnWaveformInstallAndStart, installAndStart) |
|---|
| 735 | self.Bind(wx.EVT_MENU, self.OnWaveformPreview, viewWform) |
|---|
| 736 | self.Bind(wx.EVT_MENU, self.OnWaveformProperties, properties) |
|---|
| 737 | |
|---|
| 738 | def AddToComponentsMenu(self, newComponent, isVisible): |
|---|
| 739 | cMenu = self.FindMenuInMenuBar('Components') |
|---|
| 740 | citem = cMenu.AppendCheckItem(-1, newComponent) |
|---|
| 741 | self.Bind(wx.EVT_MENU, self.OnComponentMenuClick, citem) |
|---|
| 742 | |
|---|
| 743 | if isVisible: |
|---|
| 744 | citem.Check(True) |
|---|
| 745 | |
|---|
| 746 | def OnWaveformInstall(self, event): |
|---|
| 747 | chosenMenu = event.GetEventObject() |
|---|
| 748 | parent = chosenMenu.GetParent() |
|---|
| 749 | |
|---|
| 750 | for mItem in parent.GetMenuItems(): |
|---|
| 751 | if mItem.GetSubMenu() is chosenMenu: |
|---|
| 752 | self.controller.installWaveform(mItem.GetItemLabel(), False) |
|---|
| 753 | break |
|---|
| 754 | |
|---|
| 755 | def OnWaveformInstallAndStart(self, event): |
|---|
| 756 | chosenMenu = event.GetEventObject() |
|---|
| 757 | parent = chosenMenu.GetParent() |
|---|
| 758 | |
|---|
| 759 | for mItem in parent.GetMenuItems(): |
|---|
| 760 | if mItem.GetSubMenu() is chosenMenu: |
|---|
| 761 | self.controller.installWaveform(mItem.GetItemLabel(), True) |
|---|
| 762 | break |
|---|
| 763 | |
|---|
| 764 | def OnPropertySelect(self, event): |
|---|
| 765 | srcId = event.GetId() |
|---|
| 766 | pMenu = event.GetEventObject() |
|---|
| 767 | mItemList = pMenu.GetMenuItems() |
|---|
| 768 | for mItem in mItemList: |
|---|
| 769 | if srcId == mItem.GetId(): |
|---|
| 770 | propName = mItem.GetItemLabel() |
|---|
| 771 | #self.tempComp has the reference to the component panel on which |
|---|
| 772 | #the context menu is invoked in ComponentRightClick Handler |
|---|
| 773 | compName = self.tempComp.GetName() |
|---|
| 774 | self.model.updatePropertyState(compName, propName, mItem.IsChecked()) |
|---|
| 775 | break |
|---|
| 776 | |
|---|
| 777 | def OnComponentMoveUp(self, event): |
|---|
| 778 | compName = self.tempComp.GetName() |
|---|
| 779 | wformName = self.tempComp.GetParent().GetName() |
|---|
| 780 | self.model.moveComponentUp(wformName, compName) |
|---|
| 781 | |
|---|
| 782 | def OnComponentMoveDown(self, event): |
|---|
| 783 | compName = self.tempComp.GetName() |
|---|
| 784 | wformName = self.tempComp.GetParent().GetName() |
|---|
| 785 | self.model.moveComponentDown(wformName, compName) |
|---|
| 786 | |
|---|
| 787 | |
|---|
| 788 | def OnWaveformPreview(self, event): |
|---|
| 789 | chosenMenu = event.GetEventObject() |
|---|
| 790 | parent = chosenMenu.GetParent() |
|---|
| 791 | |
|---|
| 792 | for mItem in parent.GetMenuItems(): |
|---|
| 793 | if mItem.GetSubMenu() is chosenMenu: |
|---|
| 794 | wformName = mItem.GetItemLabel() |
|---|
| 795 | waveform = self.model.getWaveform(wformName, WaveformModel.SYSTEM_WAVEFORM) |
|---|
| 796 | title = 'Preview - ' + wformName |
|---|
| 797 | |
|---|
| 798 | previewFrame = wx.Frame(self, -1, title, OSSIE_WAVEAPP_DIMENSION) |
|---|
| 799 | wPanel = self.createWaveformPanel(previewFrame, waveform, preview = True) |
|---|
| 800 | wPanel.Show() |
|---|
| 801 | previewFrame.Show() |
|---|
| 802 | break |
|---|
| 803 | |
|---|
| 804 | def OnWaveformProperties(self, event): |
|---|
| 805 | chosenMenu = event.GetEventObject() |
|---|
| 806 | parent = chosenMenu.GetParent() |
|---|
| 807 | |
|---|
| 808 | for mItem in parent.GetMenuItems(): |
|---|
| 809 | if mItem.GetSubMenu() is chosenMenu: |
|---|
| 810 | wformName = mItem.GetItemLabel() |
|---|
| 811 | wformObj = self.model.getWaveform(wformName, WaveformModel.SYSTEM_WAVEFORM) |
|---|
| 812 | print str(wformObj) |
|---|
| 813 | title = wformName + " - Properties" |
|---|
| 814 | wformProperties = str(wformObj) |
|---|
| 815 | dlg = wx.MessageDialog(None, wformProperties, title, wx.OK | wx.ICON_INFORMATION) |
|---|
| 816 | try: |
|---|
| 817 | dlg.ShowModal() |
|---|
| 818 | finally: |
|---|
| 819 | dlg.Destroy() |
|---|
| 820 | |
|---|
| 821 | #Event Handler for page change. Update the active waveform on each page change |
|---|
| 822 | def OnNbPageChange(self, event): |
|---|
| 823 | pageId = event.GetSelection() |
|---|
| 824 | #GetPage() returns the reference to waveform panel object |
|---|
| 825 | wPanel = self.notebook.GetPage(pageId) |
|---|
| 826 | #update active waveform in the model |
|---|
| 827 | self.model.setActiveWaveform(wPanel.GetName()) |
|---|
| 828 | |
|---|
| 829 | def OnComponentMenuClick(self, event): |
|---|
| 830 | cMenu = event.GetEventObject() |
|---|
| 831 | mItemList = cMenu.GetMenuItems() |
|---|
| 832 | for mItem in mItemList: |
|---|
| 833 | self.model.updateComponentState(mItem.GetItemLabel(), mItem.IsChecked()) |
|---|
| 834 | |
|---|
| 835 | def UpdateComponentMenu(self, wform): |
|---|
| 836 | |
|---|
| 837 | componentList = wform.getAllComponents() |
|---|
| 838 | compMenu = self.FindMenuInMenuBar('Components') |
|---|
| 839 | #clear the existing items in Component Menu |
|---|
| 840 | for mItem in compMenu.GetMenuItems(): |
|---|
| 841 | compMenu.DeleteItem(mItem) |
|---|
| 842 | |
|---|
| 843 | #Now update the component Menu wit the components of currently selected waveform |
|---|
| 844 | for component in componentList: |
|---|
| 845 | self.AddToComponentsMenu(component.getName(), component.isVisible()) |
|---|
| 846 | |
|---|
| 847 | #listeners of WaveformListener interface |
|---|
| 848 | def waveformAdded(self, event): |
|---|
| 849 | wform = event.getSource() |
|---|
| 850 | #if(wform.name == "w1"): |
|---|
| 851 | # print "in waveform Added" |
|---|
| 852 | # for comp in wform.components: |
|---|
| 853 | # for prop in comp.properties: |
|---|
| 854 | # print str(prop.id) + ": " + str(prop.getValue()) |
|---|
| 855 | |
|---|
| 856 | |
|---|
| 857 | |
|---|
| 858 | #create the panel only if it is a instance waveform. |
|---|
| 859 | #For system waveform, just add it to the menu |
|---|
| 860 | wType = wform.getType() |
|---|
| 861 | if wType == WaveformModel.INSTANCE_WAVEFORM: |
|---|
| 862 | wPanel = self.createWaveformPanel(self.notebook, wform) |
|---|
| 863 | self.notebook.AddPage(wPanel, wform.getName()) |
|---|
| 864 | |
|---|
| 865 | self.AddToWaveformsMenu(wform.getName(), wType) |
|---|
| 866 | |
|---|
| 867 | def waveformRemoved(self, event): |
|---|
| 868 | |
|---|
| 869 | srcWform = event.getSource() |
|---|
| 870 | #if waveform removed is a SYSTEM_WAVEFORM, i.e. the one found in /sdr/dom/waveforms, |
|---|
| 871 | #remove the waveform from the Waveforms Menu |
|---|
| 872 | if srcWform is not None and srcWform.getType() == WaveformModel.SYSTEM_WAVEFORM: |
|---|
| 873 | wformsMenu = self.FindMenuInMenuBar('Waveforms') |
|---|
| 874 | menuItems = wformsMenu.GetMenuItems() |
|---|
| 875 | for mItem in menuItems: |
|---|
| 876 | if mItem.GetItemLabel() == srcWform.getName(): |
|---|
| 877 | wformsMenu.DeleteItem(mItem) |
|---|
| 878 | break |
|---|
| 879 | return |
|---|
| 880 | |
|---|
| 881 | curPanelId = self.notebook.GetSelection() |
|---|
| 882 | curPanel = self.notebook.GetCurrentPage() |
|---|
| 883 | wformName = curPanel.GetName() |
|---|
| 884 | self.wpanels.remove(curPanel) |
|---|
| 885 | #remove the panel from the notebook |
|---|
| 886 | self.notebook.RemovePage(curPanelId) |
|---|
| 887 | #destroy the waveform panel object |
|---|
| 888 | curPanel.Destroy() |
|---|
| 889 | |
|---|
| 890 | msg = ("%s Uninstalled !" % wformName) |
|---|
| 891 | utils.showMessage(msg, utils.INFO) |
|---|
| 892 | |
|---|
| 893 | #AdvanceSelection() sets the next available page active |
|---|
| 894 | #and trigger EVT_NOTEBOOK_PAGE_CHANGED event. The event |
|---|
| 895 | #handler OnNbPageChange() would be called that sets the |
|---|
| 896 | #active waveform thruogh model.SetActiveWaveform() |
|---|
| 897 | |
|---|
| 898 | self.notebook.AdvanceSelection(True) |
|---|
| 899 | |
|---|
| 900 | #if no running waveforms on the system? |
|---|
| 901 | if self.notebook.GetPageCount() == 0: |
|---|
| 902 | compMenu = self.FindMenuInMenuBar('Components') |
|---|
| 903 | #clear the existing items in Component Menu |
|---|
| 904 | for mItem in compMenu.GetMenuItems(): |
|---|
| 905 | compMenu.DeleteItem(mItem) |
|---|
| 906 | self.model.setActiveWaveform(None) |
|---|
| 907 | self.SetSize(OSSIE_WAVEAPP_DIMENSION) |
|---|
| 908 | #notebook.AdvanceSelection() will not trigger PAGE_CHANGED event if there is |
|---|
| 909 | #only one panel left. Hence, set the active form explicitly. |
|---|
| 910 | elif self.notebook.GetPageCount() == 1: |
|---|
| 911 | nextActiveWform = self.notebook.GetCurrentPage().GetName() |
|---|
| 912 | self.model.setActiveWaveform(nextActiveWform) |
|---|
| 913 | |
|---|
| 914 | def waveformSelected(self, event): |
|---|
| 915 | wform = event.getSource() |
|---|
| 916 | #If no waveform is there, just update the title and status Bar and return |
|---|
| 917 | if wform is None: |
|---|
| 918 | self.SetTitle(OSSIE_TITLE) |
|---|
| 919 | #self.updateStatusBar() |
|---|
| 920 | return |
|---|
| 921 | self.SetTitle(OSSIE_TITLE + ' (' + wform.getName() + ')') |
|---|
| 922 | #Component menu needs to be updated per waveform basis. |
|---|
| 923 | self.UpdateComponentMenu(wform) |
|---|
| 924 | self.Layout() |
|---|
| 925 | |
|---|
| 926 | def componentStateChanged(self, cEvent): |
|---|
| 927 | """ A listener method of ComponentListener class that is triggerred |
|---|
| 928 | whenever a component is selected/deselected in the Component Menu""" |
|---|
| 929 | |
|---|
| 930 | wPanel = self.getCurrentPanel() |
|---|
| 931 | cPanelList = wPanel.GetChildren() |
|---|
| 932 | wPanelSizer = wPanel.GetSizer() |
|---|
| 933 | componentList = self.model.getActiveWaveform().getAllComponents() |
|---|
| 934 | |
|---|
| 935 | #Detach all the existing panels from the sizer |
|---|
| 936 | for cPanel in cPanelList: |
|---|
| 937 | if wPanelSizer.GetItem(cPanel) != None: |
|---|
| 938 | wPanelSizer.Detach(cPanel) |
|---|
| 939 | cPanel.Hide() |
|---|
| 940 | |
|---|
| 941 | #Update the sizer to be inline with the order of components in Waveform Model |
|---|
| 942 | for cmp in componentList: |
|---|
| 943 | if cmp.isVisible(): |
|---|
| 944 | #print cmp.getPosition() |
|---|
| 945 | for cPanel in cPanelList: |
|---|
| 946 | if cPanel.GetName() == cmp.getName(): |
|---|
| 947 | wPanelSizer.Add(cPanel, 0, wx.ALL | wx.EXPAND, 5) |
|---|
| 948 | cPanel.Show() |
|---|
| 949 | break |
|---|
| 950 | |
|---|
| 951 | wPanelSizer.Layout() |
|---|
| 952 | wPanel.Refresh() |
|---|
| 953 | |
|---|
| 954 | def propertyStateChanged(self, event): |
|---|
| 955 | property = event.getSource() |
|---|
| 956 | component = property.getParent() |
|---|
| 957 | wPanel = self.getCurrentPanel() |
|---|
| 958 | cPanel = wPanel.FindWindowByName(component.getName()) |
|---|
| 959 | cPanelSizer = cPanel.GetSizer() |
|---|
| 960 | #Component Panel sizer is a static box sizer. ACtual widgets are contained in a |
|---|
| 961 | #gridbag sizer which in turn contained in this static box sizer |
|---|
| 962 | |
|---|
| 963 | cgsizer = cPanelSizer.GetChildren()[0].GetSizer() |
|---|
| 964 | propWidgetsList = cgsizer.GetChildren() |
|---|
| 965 | |
|---|
| 966 | #propWidgetsList stores the list of labels and widgets of properties in SizerItem format. |
|---|
| 967 | #Get the actual window from the SizerItem object before acting on the window |
|---|
| 968 | |
|---|
| 969 | #removing all the widgets contained in the sizer |
|---|
| 970 | for prpWid in propWidgetsList: |
|---|
| 971 | #prpWid is of type wx.SizerItem. Use GetWindow() to get the window tracked by this SizerItem |
|---|
| 972 | actW = prpWid.GetWindow() |
|---|
| 973 | if cgsizer.GetItem(actW) != None: |
|---|
| 974 | cgsizer.Detach(actW) |
|---|
| 975 | actW.Hide() |
|---|
| 976 | |
|---|
| 977 | prpList = component.getAllProperties() |
|---|
| 978 | propWidgetsList = cPanel.GetChildren() |
|---|
| 979 | |
|---|
| 980 | #NOTE: The while loop inside the for loop iterates over the children of |
|---|
| 981 | #the component panel. Since StaticBoxSizer is used to layout the properties, |
|---|
| 982 | #the first child of the component panel (cPanel) will always be the StaticBox |
|---|
| 983 | #object which should not be added to the gridbagsizer in addPropToCompSizer |
|---|
| 984 | #method. Hence, iterating from 1 to length of the propWidgetsList. |
|---|
| 985 | # (see the value of index ) |
|---|
| 986 | |
|---|
| 987 | newPrpList = [] |
|---|
| 988 | index = 1 |
|---|
| 989 | for prp in prpList: |
|---|
| 990 | if prp.isVisible(): |
|---|
| 991 | index = 1 |
|---|
| 992 | while ( index < (len(propWidgetsList)) ): |
|---|
| 993 | actW = propWidgetsList[index] |
|---|
| 994 | |
|---|
| 995 | if actW.GetName() == prp.getName(): |
|---|
| 996 | newPrpList.append(actW) |
|---|
| 997 | actW.Show() |
|---|
| 998 | index = index + 1 |
|---|
| 999 | |
|---|
| 1000 | newCgSizer = self.addPropToCompSizer(newPrpList) |
|---|
| 1001 | cPanelSizer.Remove(cgsizer) |
|---|
| 1002 | cPanelSizer.Add(newCgSizer, 1, wx.ALIGN_CENTER | wx.EXPAND, 10) |
|---|
| 1003 | cPanelSizer.Layout() |
|---|
| 1004 | wPanel.GetSizer().Layout() |
|---|
| 1005 | |
|---|
| 1006 | |
|---|
| 1007 | def propertyWidgetChanged(self, event): |
|---|
| 1008 | property = event.getSource() |
|---|
| 1009 | compRef = property.getParent() |
|---|
| 1010 | wPanel = self.getCurrentPanel() |
|---|
| 1011 | |
|---|
| 1012 | |
|---|
| 1013 | # DO NOT CALL replaceComponentPanel() DIRECTLY FROM HERE AS IT INVOLVES |
|---|
| 1014 | # A CALL TO window.Destroy() METHOD. THIS METHOD IS STILL IN THE CONTEXT |
|---|
| 1015 | # OF EVENT HANDLER INVOKED AS A RESULT OF RIGHT CLICK ON PROPERTY WIDGET. |
|---|
| 1016 | # CALLING replaceComponentPanel() DIRECTLY FROM HERE WOULD **CRASH** THE |
|---|
| 1017 | # APPLICATION. |
|---|
| 1018 | |
|---|
| 1019 | wx.CallAfter(self.replaceComponentPanel, wPanel, compRef ) |
|---|
| 1020 | |
|---|
| 1021 | def propertyRangeChanged(self, event): |
|---|
| 1022 | propertyCtrl = self.tempProp |
|---|
| 1023 | propRef = event.getSource() |
|---|
| 1024 | newMin, newMax = propRef.getRange() |
|---|
| 1025 | propertyCtrl.SetRange(newMin, newMax) |
|---|
| 1026 | |
|---|
| 1027 | #if GUI widget's current value is changed because new min, max values |
|---|
| 1028 | #we have to update the new value to the model as well. |
|---|
| 1029 | curWidVal = self.formatWidgetToModel(propertyCtrl.GetValue(), propRef.getType()) |
|---|
| 1030 | preVal = propRef.getValue() |
|---|
| 1031 | if preVal == curWidVal: |
|---|
| 1032 | pass |
|---|
| 1033 | else: |
|---|
| 1034 | pName = propertyCtrl.GetName() |
|---|
| 1035 | cName = propertyCtrl.GetParent().GetName() |
|---|
| 1036 | wName = propertyCtrl.GetParent().GetParent().GetName() |
|---|
| 1037 | |
|---|
| 1038 | status = self.model.configure(wName, cName, pName, curWidVal) |
|---|
| 1039 | #leave the text box as it is if status is True |
|---|
| 1040 | #if the configure operation failed, revert the text value to the value stored in |
|---|
| 1041 | #the model. |
|---|
| 1042 | if status is False: |
|---|
| 1043 | msg = "Could not configure " + pName |
|---|
| 1044 | utils.showMessage(msg, utils.NON_FATAL) |
|---|
| 1045 | self.formatModelToWidget(propertyCtrl, preVal) |
|---|
| 1046 | |
|---|
| 1047 | return |
|---|
| 1048 | # if propertyCtrl.__class__ is wx.SpinCtrl: |
|---|
| 1049 | # propertyCtrl.SetRange(newMin, newMax) |
|---|
| 1050 | # if propertyCtrl.__class__ is wx.Slider: |
|---|
| 1051 | # propertyCtrl.SetMin(newMin) |
|---|
| 1052 | # propertyCtrl.SetMax(newMax) |
|---|
| 1053 | |
|---|
| 1054 | def FindMenuInMenuBar(self, title): |
|---|
| 1055 | pos = self.GetMenuBar().FindMenu(title) |
|---|
| 1056 | return self.GetMenuBar().GetMenu(pos) |
|---|
| 1057 | |
|---|
| 1058 | def getCurrentPanel(self): |
|---|
| 1059 | return self.notebook.GetCurrentPage() |
|---|
| 1060 | |
|---|
| 1061 | def replaceComponentPanel(self, wPanel, component): |
|---|
| 1062 | |
|---|
| 1063 | # Find the component to be replaced from the children list of current |
|---|
| 1064 | # active waveform panel. Replace the Old component panel in the waveform |
|---|
| 1065 | # panel's sizer with the compnent panel created new and then destroy the |
|---|
| 1066 | # old component panel |
|---|
| 1067 | # |
|---|
| 1068 | for button in self.configureButtons: |
|---|
| 1069 | if button.isComponentButton and button.getParentName() == component.getName(): |
|---|
| 1070 | self.configureButtons.remove(button) |
|---|
| 1071 | |
|---|
| 1072 | oldCPanel = wPanel.FindWindowByName(component.getName()) |
|---|
| 1073 | newCPanel = self.createComponentPanel(wPanel, component) |
|---|
| 1074 | wSizer = wPanel.GetSizer() |
|---|
| 1075 | wSizer.Replace(oldCPanel, newCPanel) |
|---|
| 1076 | |
|---|
| 1077 | wSizer.Fit(wPanel) |
|---|
| 1078 | wPanel.SetSizer(wSizer) |
|---|
| 1079 | wSizer.Layout() |
|---|
| 1080 | oldCPanel.Destroy() |
|---|
| 1081 | |
|---|
| 1082 | def OnRefresh(self, event): |
|---|
| 1083 | self.controller.refresh() |
|---|
| 1084 | |
|---|
| 1085 | def waveformRefresh(self, event): |
|---|
| 1086 | wformsTobeRemoved = event.getSource() |
|---|
| 1087 | wformMenu = self.FindMenuInMenuBar('Waveforms') |
|---|
| 1088 | |
|---|
| 1089 | for wformName in wformsTobeRemoved: |
|---|
| 1090 | wPanel = self.getWaveformPanel(wformName) |
|---|
| 1091 | self.wpanels.remove(wPanel) |
|---|
| 1092 | self.compPopupMenus.pop(wPanel) |
|---|
| 1093 | self.prpPopupMenus.pop(wPanel) |
|---|
| 1094 | wPanel.Destroy() |
|---|
| 1095 | |
|---|
| 1096 | #update the menu display |
|---|
| 1097 | menuItems = wformMenu.GetMenuItems() |
|---|
| 1098 | |
|---|
| 1099 | #remove the selected waveform from the menu list |
|---|
| 1100 | for mItem in menuItems: |
|---|
| 1101 | if mItem.GetItemLabel() == wformName : |
|---|
| 1102 | wformMenu.RemoveItem(mItem) |
|---|
| 1103 | mItem.Destroy() |
|---|
| 1104 | break |
|---|
| 1105 | |
|---|
| 1106 | for wPanel in self.wpanels: |
|---|
| 1107 | cPanelList = wPanel.GetChildren() |
|---|
| 1108 | wformRef = self.model.getWaveform(wPanel.GetName(), WaveformModel.INSTANCE_WAVEFORM) |
|---|
| 1109 | for cPanel in cPanelList: |
|---|
| 1110 | compRef = wformRef.getComponent(cPanel.GetName()) |
|---|
| 1111 | prpList = compRef.getAllProperties() |
|---|
| 1112 | prpWidgetList = cPanel.GetChildren() |
|---|
| 1113 | |
|---|
| 1114 | for prpW in prpWidgetList: |
|---|
| 1115 | if type(prpW) is wx.TextCtrl: |
|---|
| 1116 | prpW.SetValue(str(compRef.findPropertyByName(prpW.GetName()).getValue())) |
|---|
| 1117 | elif type(prpW) is wx.SpinCtrl: |
|---|
| 1118 | prpW.SetValue(int(compRef.findPropertyByName(prpW.GetName()).getValue())) |
|---|
| 1119 | elif type(prpW) is wx.Slider: |
|---|
| 1120 | prpW.SetValue(int(compRef.findPropertyByName(prpW.GetName()).getValue())) |
|---|
| 1121 | |
|---|
| 1122 | if (self.model.getActiveWaveform() is None): |
|---|
| 1123 | nextActiveWform = None |
|---|
| 1124 | #make the first available waveform active |
|---|
| 1125 | menuItems = wformMenu.GetMenuItems() |
|---|
| 1126 | for mItem in menuItems: |
|---|
| 1127 | if mItem.IsCheckable(): |
|---|
| 1128 | mItem.Check() |
|---|
| 1129 | nextActiveWform = mItem.GetItemLabel() |
|---|
| 1130 | break |
|---|
| 1131 | |
|---|
| 1132 | #no running waveforms on the system |
|---|
| 1133 | if nextActiveWform is None: |
|---|
| 1134 | self.SetSize(OSSIE_WAVEAPP_DIMENSION) |
|---|
| 1135 | return |
|---|
| 1136 | self.model.setActiveWaveform(nextActiveWform) |
|---|
| 1137 | |
|---|
| 1138 | def getWaveformPanel(self, wformName): |
|---|
| 1139 | for wPanel in self.wpanels: |
|---|
| 1140 | if (wformName == wPanel.GetName()): |
|---|
| 1141 | return wPanel |
|---|
| 1142 | |
|---|
| 1143 | |
|---|
| 1144 | def OnOpenLayout(self, event): |
|---|
| 1145 | pass |
|---|
| 1146 | def OnSaveLayout(self, event): |
|---|
| 1147 | self.model.waveformToXML() |
|---|
| 1148 | pass |
|---|
| 1149 | def OnSaveLayoutAs(self, event): |
|---|
| 1150 | pass |
|---|
| 1151 | def OnClose(self, event): |
|---|
| 1152 | if self.controller.nodeBooterProcess != None: |
|---|
| 1153 | dlg = wx.MessageDialog(self, |
|---|
| 1154 | "NodeBooter was started by WaveDash.\n" + |
|---|
| 1155 | "Would you like to terminate it?", |
|---|
| 1156 | "Confirm NodeBooter Termination", wx.YES | wx.NO | wx.ICON_QUESTION) |
|---|
| 1157 | result = dlg.ShowModal() |
|---|
| 1158 | if result == wx.ID_YES: |
|---|
| 1159 | print "Terminating nodeBooter" |
|---|
| 1160 | self.controller.nodeBooterProcess.terminate() |
|---|
| 1161 | self.Destroy() |
|---|
| 1162 | |
|---|
| 1163 | def OnWidgetSettings(self, event): |
|---|
| 1164 | pass |
|---|
| 1165 | def OnAbout(self, event): |
|---|
| 1166 | dlg = wx.MessageDialog(self, "WaveDash\nPart of the OSSIE Toolset", |
|---|
| 1167 | "About WaveDash") |
|---|
| 1168 | dlg.ShowModal() |
|---|
| 1169 | |
|---|
| 1170 | def OnUpdateOnRefreshCheck(self, event): |
|---|
| 1171 | for button in self.configureButtons: |
|---|
| 1172 | button.Enable(self.updateOnRefresh.IsChecked()) |
|---|
| 1173 | |
|---|
| 1174 | def OpenPreferences(self, event): |
|---|
| 1175 | PreferencePage = WavedashPreferencePage(self, self.controller) |
|---|
| 1176 | PreferencePage.Show() |
|---|
| 1177 | |
|---|
| 1178 | def OnUpdateComponentClicked(self, event): |
|---|
| 1179 | src = event.GetEventObject() |
|---|
| 1180 | compName = src.GetParent().GetName() |
|---|
| 1181 | wName = src.GetParent().GetParent().GetName() |
|---|
| 1182 | self.updateComponent(compName, wName) |
|---|
| 1183 | |
|---|
| 1184 | def OnUpdateWaveformClicked(self, event): |
|---|
| 1185 | src = event.GetEventObject() |
|---|
| 1186 | wName = src.GetParent().GetName() |
|---|
| 1187 | self.updateWaveform(wName) |
|---|
| 1188 | |
|---|
| 1189 | def updateWaveform(self, waveformName): |
|---|
| 1190 | wform = self.model.getWaveform(waveformName, WaveformModel.INSTANCE_WAVEFORM) |
|---|
| 1191 | for component in wform.getAllComponents(): |
|---|
| 1192 | self.updateComponent(component.getName(), wform.getName()) |
|---|
| 1193 | |
|---|
| 1194 | def updateComponent(self, componentName, waveformName): |
|---|
| 1195 | wform = self.model.getWaveform(waveformName, WaveformModel.INSTANCE_WAVEFORM) |
|---|
| 1196 | compRef = wform.getComponent(componentName) |
|---|
| 1197 | for property in compRef.getAllProperties(): |
|---|
| 1198 | curVal = self.formatWidgetToModel(property.getWindow().GetValue(), property.getType()) |
|---|
| 1199 | preVal = property.getValue() |
|---|
| 1200 | |
|---|
| 1201 | |
|---|
| 1202 | if curVal is not None: |
|---|
| 1203 | |
|---|
| 1204 | #if both the values are equal then no need to call configure() |
|---|
| 1205 | if preVal == curVal: |
|---|
| 1206 | pass |
|---|
| 1207 | else: |
|---|
| 1208 | status = self.model.configure(waveformName, componentName, property.getName(), curVal) |
|---|
| 1209 | #leave the text box as it is if status is True |
|---|
| 1210 | #if the configure operation failed, revert the text value to the value stored in |
|---|
| 1211 | #the model. |
|---|
| 1212 | if status is False: |
|---|
| 1213 | msg = "Could not configure " + property.getName() |
|---|
| 1214 | utils.showMessage(msg, utils.NON_FATAL) |
|---|
| 1215 | self.formatModelToWidget(property.getWindow(), preVal) |
|---|
| 1216 | #src.SetValue(str(preVal)) |
|---|
| 1217 | elif property.type[1] == "boolean": |
|---|
| 1218 | self.formatModelToWidget(property.getWindow(), curVal) |
|---|
| 1219 | |
|---|
| 1220 | else: |
|---|
| 1221 | msg = "Invalid value for %s/%s" % (componentName, property.getName()) + "\nEnter only '" + property.getType()[1] + "' values" |
|---|
| 1222 | msg = msg + "\nFor sequence types, enter values separated by comma" |
|---|
| 1223 | msg = msg + " and enclosed within [] e.g. [10,20,30]" |
|---|
| 1224 | |
|---|
| 1225 | utils.showMessage(msg, utils.NON_FATAL) |
|---|
| 1226 | self.formatModelToWidget(property.getWindow(), preVal) |
|---|
| 1227 | self.Layout() |
|---|
| 1228 | |
|---|
| 1229 | def getRoot(self): |
|---|
| 1230 | root = __file__ |
|---|
| 1231 | if os.path.islink (root): |
|---|
| 1232 | root = os.path.realpath (root) |
|---|
| 1233 | root = os.path.dirname (os.path.abspath (root)) |
|---|
| 1234 | return root |
|---|
| 1235 | |
|---|
| 1236 | def main(): |
|---|
| 1237 | app = wx.App() |
|---|
| 1238 | ctrlr = Controller() |
|---|
| 1239 | ctrlr.createWidgetContainer() |
|---|
| 1240 | |
|---|
| 1241 | frame = WavedashView(ctrlr, ctrlr.model) |
|---|
| 1242 | |
|---|
| 1243 | ctrlr.CORBAutils.init_CORBA() |
|---|
| 1244 | ctrlr.buildModel() |
|---|
| 1245 | |
|---|
| 1246 | app.MainLoop() |
|---|
| 1247 | |
|---|
| 1248 | if __name__ == '__main__': |
|---|
| 1249 | main() |
|---|
| 1250 | |
|---|
| 1251 | |
|---|