Package diffpy :: Package pdfgui :: Package gui :: Module phaseconstraintspanel
[hide private]
[frames] | no frames]

Source Code for Module diffpy.pdfgui.gui.phaseconstraintspanel

  1  #!/usr/bin/env python 
  2  # -*- coding: UTF-8 -*- 
  3  ############################################################################## 
  4  # 
  5  # PDFgui            by DANSE Diffraction group 
  6  #                   Simon J. L. Billinge 
  7  #                   (c) 2006 trustees of the Michigan State University. 
  8  #                   All rights reserved. 
  9  # 
 10  # File coded by:    Chris Farrow, Dmitriy Bryndin 
 11  # 
 12  # See AUTHORS.txt for a list of people who contributed. 
 13  # See LICENSE.txt for license information. 
 14  # 
 15  ############################################################################## 
 16   
 17  # generated by wxGlade 0.4.1 on Thu Nov  2 11:29:31 2006 
 18   
 19  __id__ = "$Id: phaseconstraintspanel.py 2981 2009-04-02 02:13:58Z farrowch $" 
 20   
 21  import re 
 22  import wx 
 23  import wx.grid 
 24  from diffpy.pdfgui.control.constraint import Constraint 
 25  from diffpy.pdfgui.control.controlerrors import * 
 26  from diffpy.pdfgui.gui.pdfpanel import PDFPanel 
 27  from diffpy.pdfgui.gui.tooltips import phasepanel as toolTips 
 28  from diffpy.pdfgui.gui.wxExtensions.autowidthlabelsgrid import \ 
 29          AutoWidthLabelsGrid 
 30  from diffpy.pdfgui.gui.wxExtensions.textctrlutils import textCtrlAsGridCell 
 31  from diffpy.pdfgui.gui.sgconstraindialog import SGConstrainDialog 
 32  from diffpy.pdfgui.gui import phasepanelutils 
 33   
34 -class PhaseConstraintsPanel(wx.Panel, PDFPanel):
35 - def __init__(self, *args, **kwds):
36 PDFPanel.__init__(self) 37 # begin wxGlade: PhaseConstraintsPanel.__init__ 38 kwds["style"] = wx.TAB_TRAVERSAL 39 wx.Panel.__init__(self, *args, **kwds) 40 self.sizerLatticeParameters_staticbox = wx.StaticBox(self, -1, "") 41 self.sizerAdditionalParameters_staticbox = wx.StaticBox(self, -1, "") 42 self.sizerAtoms_staticbox = wx.StaticBox(self, -1, "") 43 self.sizerPanelName_staticbox = wx.StaticBox(self, -1, "") 44 self.labelPanelName = wx.StaticText(self, -1, "Phase Constraints") 45 self.labelA = wx.StaticText(self, -1, "a") 46 self.textCtrlA = wx.TextCtrl(self, -1, "", style=wx.TE_PROCESS_ENTER) 47 self.labelB = wx.StaticText(self, -1, "b") 48 self.textCtrlB = wx.TextCtrl(self, -1, "", style=wx.TE_PROCESS_ENTER) 49 self.labelC = wx.StaticText(self, -1, "c") 50 self.textCtrlC = wx.TextCtrl(self, -1, "", style=wx.TE_PROCESS_ENTER) 51 self.labelAlpha = wx.StaticText(self, -1, "alpha") 52 self.textCtrlAlpha = wx.TextCtrl(self, -1, "", style=wx.TE_PROCESS_ENTER) 53 self.labelBeta = wx.StaticText(self, -1, "beta") 54 self.textCtrlBeta = wx.TextCtrl(self, -1, "", style=wx.TE_PROCESS_ENTER) 55 self.labelGamma = wx.StaticText(self, -1, "gamma") 56 self.textCtrlGamma = wx.TextCtrl(self, -1, "", style=wx.TE_PROCESS_ENTER) 57 self.labelScaleFactor = wx.StaticText(self, -1, "Scale Factor") 58 self.textCtrlScaleFactor = wx.TextCtrl(self, -1, "", style=wx.TE_PROCESS_ENTER) 59 self.labelDelta1 = wx.StaticText(self, -1, "delta1") 60 self.textCtrlDelta1 = wx.TextCtrl(self, -1, "", style=wx.TE_PROCESS_ENTER) 61 self.labelDelta2 = wx.StaticText(self, -1, "delta2") 62 self.textCtrlDelta2 = wx.TextCtrl(self, -1, "", style=wx.TE_PROCESS_ENTER) 63 self.labelSpdiameter = wx.StaticText(self, -1, "spdiameter") 64 self.textCtrlSpdiameter = wx.TextCtrl(self, -1, "", style=wx.TE_PROCESS_ENTER) 65 self.labelSratio = wx.StaticText(self, -1, "sratio") 66 self.textCtrlSratio = wx.TextCtrl(self, -1, "", style=wx.TE_PROCESS_ENTER) 67 self.labelRcut = wx.StaticText(self, -1, "rcut") 68 self.textCtrlRcut = wx.TextCtrl(self, -1, "", style=wx.TE_PROCESS_ENTER|wx.TE_READONLY) 69 self.labelStepcut = wx.StaticText(self, -1, "stepcut") 70 self.textCtrlStepcut = wx.TextCtrl(self, -1, "", style=wx.TE_PROCESS_ENTER|wx.TE_READONLY) 71 self.labelIncludedPairs = wx.StaticText(self, -1, "Included Pairs") 72 self.textCtrlIncludedPairs = wx.TextCtrl(self, -1, "all-all", style=wx.TE_READONLY) 73 self.gridAtoms = AutoWidthLabelsGrid(self, -1, size=(1, 1)) 74 75 self.__set_properties() 76 self.__do_layout() 77 78 self.Bind(wx.grid.EVT_GRID_CMD_CELL_RIGHT_CLICK, self.onCellRightClick, self.gridAtoms) 79 self.Bind(wx.grid.EVT_GRID_CMD_EDITOR_SHOWN, self.onEditorShown, self.gridAtoms) 80 self.Bind(wx.grid.EVT_GRID_CMD_LABEL_RIGHT_CLICK, self.onLabelRightClick, self.gridAtoms) 81 self.Bind(wx.grid.EVT_GRID_CMD_CELL_CHANGE, self.onCellChange, self.gridAtoms) 82 # end wxGlade 83 self.__customProperties()
84
85 - def __set_properties(self):
86 # begin wxGlade: PhaseConstraintsPanel.__set_properties 87 self.labelPanelName.SetFont(wx.Font(18, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, "")) 88 self.labelA.SetToolTipString("lat(1)") 89 self.textCtrlA.SetToolTipString("lat(1)") 90 self.labelB.SetToolTipString("lat(2)") 91 self.textCtrlB.SetToolTipString("lat(2)") 92 self.labelC.SetToolTipString("lat(3)") 93 self.textCtrlC.SetToolTipString("lat(3)") 94 self.labelAlpha.SetToolTipString("lat(4)") 95 self.textCtrlAlpha.SetToolTipString("lat(4)") 96 self.labelBeta.SetToolTipString("lat(5)") 97 self.textCtrlBeta.SetToolTipString("lat(5)") 98 self.labelGamma.SetToolTipString("lat(6)") 99 self.textCtrlGamma.SetToolTipString("lat(6)") 100 self.labelScaleFactor.SetToolTipString("phase scale factor") 101 self.textCtrlScaleFactor.SetToolTipString("phase scale") 102 self.labelDelta1.SetToolTipString("linear atomic correlation factor") 103 self.textCtrlDelta1.SetToolTipString("linear atomic correlation factor") 104 self.labelDelta2.SetToolTipString("quadratic atomic correlation factor") 105 self.textCtrlDelta2.SetToolTipString("quadratic atomic correlation factor") 106 self.labelSpdiameter.SetToolTipString("spherical nanoparticle amplitude correction") 107 self.textCtrlSpdiameter.SetToolTipString("spherical nanoparticle amplitude correction") 108 self.labelSratio.SetToolTipString("low r peak sharpening") 109 self.textCtrlSratio.SetToolTipString("low r peak sharpening") 110 self.labelRcut.SetToolTipString("peak sharpening cutoff") 111 self.textCtrlRcut.SetToolTipString("peak sharpening cutoff") 112 self.labelStepcut.SetToolTipString("cutoff for profile step-function") 113 self.textCtrlStepcut.SetToolTipString("cutoff for profile step-function") 114 self.textCtrlIncludedPairs.SetMinSize((240, 25)) 115 self.gridAtoms.CreateGrid(0, 11) 116 self.gridAtoms.EnableDragRowSize(0) 117 self.gridAtoms.SetColLabelValue(0, "elem") 118 self.gridAtoms.SetColLabelValue(1, "x") 119 self.gridAtoms.SetColLabelValue(2, "y") 120 self.gridAtoms.SetColLabelValue(3, "z") 121 self.gridAtoms.SetColLabelValue(4, "u11") 122 self.gridAtoms.SetColLabelValue(5, "u22") 123 self.gridAtoms.SetColLabelValue(6, "u33") 124 self.gridAtoms.SetColLabelValue(7, "u12") 125 self.gridAtoms.SetColLabelValue(8, "u13") 126 self.gridAtoms.SetColLabelValue(9, "u23") 127 self.gridAtoms.SetColLabelValue(10, "occ") 128 # end wxGlade 129 self.setToolTips(toolTips)
130 131
132 - def __do_layout(self):
133 # begin wxGlade: PhaseConstraintsPanel.__do_layout 134 sizerMain = wx.BoxSizer(wx.VERTICAL) 135 sizerAtoms = wx.StaticBoxSizer(self.sizerAtoms_staticbox, wx.VERTICAL) 136 sizer_1 = wx.BoxSizer(wx.HORIZONTAL) 137 sizerAdditionalParameters = wx.StaticBoxSizer(self.sizerAdditionalParameters_staticbox, wx.HORIZONTAL) 138 grid_sizer_4 = wx.FlexGridSizer(3, 6, 0, 0) 139 sizerLatticeParameters = wx.StaticBoxSizer(self.sizerLatticeParameters_staticbox, wx.HORIZONTAL) 140 grid_sizer_3 = wx.FlexGridSizer(2, 6, 0, 0) 141 sizerPanelName = wx.StaticBoxSizer(self.sizerPanelName_staticbox, wx.HORIZONTAL) 142 sizerPanelName.Add(self.labelPanelName, 0, wx.LEFT|wx.RIGHT|wx.ALIGN_CENTER_VERTICAL, 5) 143 sizerMain.Add(sizerPanelName, 0, wx.LEFT|wx.RIGHT|wx.EXPAND, 5) 144 grid_sizer_3.Add(self.labelA, 0, wx.ALL|wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, 5) 145 grid_sizer_3.Add(self.textCtrlA, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 0) 146 grid_sizer_3.Add(self.labelB, 0, wx.ALL|wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, 5) 147 grid_sizer_3.Add(self.textCtrlB, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 0) 148 grid_sizer_3.Add(self.labelC, 0, wx.ALL|wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, 5) 149 grid_sizer_3.Add(self.textCtrlC, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 0) 150 grid_sizer_3.Add(self.labelAlpha, 0, wx.ALL|wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, 5) 151 grid_sizer_3.Add(self.textCtrlAlpha, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 0) 152 grid_sizer_3.Add(self.labelBeta, 0, wx.ALL|wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, 5) 153 grid_sizer_3.Add(self.textCtrlBeta, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 0) 154 grid_sizer_3.Add(self.labelGamma, 0, wx.ALL|wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, 5) 155 grid_sizer_3.Add(self.textCtrlGamma, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 0) 156 sizerLatticeParameters.Add(grid_sizer_3, 1, wx.EXPAND, 0) 157 sizerMain.Add(sizerLatticeParameters, 0, wx.LEFT|wx.RIGHT|wx.EXPAND, 5) 158 grid_sizer_4.Add(self.labelScaleFactor, 0, wx.ALL|wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, 5) 159 grid_sizer_4.Add(self.textCtrlScaleFactor, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 0) 160 grid_sizer_4.Add((20, 10), 0, 0, 0) 161 grid_sizer_4.Add((20, 10), 0, 0, 0) 162 grid_sizer_4.Add((20, 10), 0, 0, 0) 163 grid_sizer_4.Add((20, 10), 0, 0, 0) 164 grid_sizer_4.Add(self.labelDelta1, 0, wx.ALL|wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, 5) 165 grid_sizer_4.Add(self.textCtrlDelta1, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 0) 166 grid_sizer_4.Add(self.labelDelta2, 0, wx.ALL|wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, 5) 167 grid_sizer_4.Add(self.textCtrlDelta2, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 0) 168 grid_sizer_4.Add(self.labelSpdiameter, 0, wx.ALL|wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, 5) 169 grid_sizer_4.Add(self.textCtrlSpdiameter, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 0) 170 grid_sizer_4.Add(self.labelSratio, 0, wx.ALL|wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, 5) 171 grid_sizer_4.Add(self.textCtrlSratio, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 0) 172 grid_sizer_4.Add(self.labelRcut, 0, wx.ALL|wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, 5) 173 grid_sizer_4.Add(self.textCtrlRcut, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 0) 174 grid_sizer_4.Add(self.labelStepcut, 0, wx.ALL|wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, 5) 175 grid_sizer_4.Add(self.textCtrlStepcut, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 0) 176 sizerAdditionalParameters.Add(grid_sizer_4, 1, wx.EXPAND, 0) 177 sizerMain.Add(sizerAdditionalParameters, 0, wx.LEFT|wx.RIGHT|wx.EXPAND, 5) 178 sizer_1.Add(self.labelIncludedPairs, 0, wx.ALL|wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL, 5) 179 sizer_1.Add(self.textCtrlIncludedPairs, 0, wx.ALL, 5) 180 sizerAtoms.Add(sizer_1, 0, wx.EXPAND, 0) 181 sizerAtoms.Add(self.gridAtoms, 1, wx.EXPAND, 0) 182 sizerMain.Add(sizerAtoms, 1, wx.LEFT|wx.RIGHT|wx.EXPAND, 5) 183 self.SetSizer(sizerMain) 184 sizerMain.Fit(self)
185 # end wxGlade 186 187 ########################################################################## 188 # Misc Methods 189
190 - def __customProperties(self):
191 """Custom properties for the panel.""" 192 self.structure = None 193 self.constraints = {} 194 self.results = None 195 self._textctrls = ['textCtrlA', 'textCtrlB', 'textCtrlC', 196 'textCtrlAlpha', 'textCtrlBeta', 'textCtrlGamma', 197 'textCtrlScaleFactor', 'textCtrlDelta1', 'textCtrlDelta2', 198 'textCtrlSratio', 'textCtrlSpdiameter'] 199 self._row = 0 200 self._col = 0 201 self._focusedText = None 202 self._selectedCells = [] 203 # bind onSetFocus onKillFocus events to text controls 204 for widget in self._textctrls: 205 self.__dict__[widget].Bind(wx.EVT_SET_FOCUS, self.onSetFocus) 206 self.__dict__[widget].Bind(wx.EVT_KILL_FOCUS, self.onKillFocus) 207 self.__dict__[widget].Bind(wx.EVT_KEY_DOWN, self.onTextCtrlKey) 208 209 # set up grid 210 self.lAtomConstraints = ['x','y','z', 211 'u11','u22','u33','u12','u13','u23','occ'] 212 # pdffit internal naming 213 self.lConstraints = [ 214 'lat(1)', 'lat(2)', 'lat(3)', 'lat(4)', 'lat(5)', 'lat(6)', 215 'pscale', 'delta1', 'delta2', 'sratio', 'spdiameter'] 216 textCtrlIds = [getattr(self, n).GetId() for n in self._textctrls] 217 self._id2varname = dict(zip(textCtrlIds, self.lConstraints)) 218 219 # set 'elem' abd 'name' columns to read-only 220 attr = wx.grid.GridCellAttr() 221 attr.SetReadOnly(True) 222 self.gridAtoms.SetColAttr(0, attr) 223 self.gridAtoms.SetColAttr(11, attr) 224 225 # catch key events and apply them to the grid 226 self.Bind(wx.EVT_KEY_DOWN, self.onKey) 227 228 # Hide some stuff 229 self.labelRcut.Hide() 230 self.textCtrlRcut.Hide() 231 self.labelStepcut.Hide() 232 self.textCtrlStepcut.Hide() 233 return
234 235 # Create the onTextCtrlKey event handler from textCtrlAsGridCell from 236 # wxExtensions.textctrlutils 237 onTextCtrlKey = textCtrlAsGridCell 238
239 - def _cache(self):
240 """Cache the current structure and constraints for future comparison.""" 241 pass
242
243 - def refresh(self):
244 """Refresh wigets on the panel.""" 245 if self.structure is None: 246 raise ValueError("structure is not defined.") 247 248 self.refreshTextCtrls() 249 250 ### update the grid ### 251 natoms = len(self.structure) 252 nrows = self.gridAtoms.GetNumberRows() 253 self.gridAtoms.BeginBatch() 254 # make sure grid has correct number of rows 255 if natoms > nrows: 256 self.gridAtoms.InsertRows(numRows = natoms - nrows) 257 elif natoms < nrows: 258 self.gridAtoms.DeleteRows(numRows = nrows - natoms) 259 260 # start with clean grid 261 self.gridAtoms.ClearGrid() 262 263 # fill the first 'elem' column with element symbols 264 for row, atom in zip(range(natoms), self.structure): 265 self.gridAtoms.SetCellValue(row, 0, atom.element) 266 267 # update constraints 268 bareAtomVarColumn = dict( zip(self.lAtomConstraints, 269 range(1, 1 + len(self.lAtomConstraints))) ) 270 avpat = re.compile(r'(\w+)\((\d+)\)$') 271 for var, con in self.constraints.iteritems(): 272 m = avpat.match(var) 273 if not m: continue 274 barevar = m.group(1) 275 if not barevar in bareAtomVarColumn: continue 276 column = bareAtomVarColumn[barevar] 277 row = int(m.group(2)) - 1 278 if not 0 <= row < natoms: 279 emsg = "Invalid variable index for %r" % var 280 raise ControlValueError(emsg) 281 self.gridAtoms.SetCellValue(row, column, con.formula) 282 barevar = re.sub(r'\(\d+\)$', '', var) 283 if not barevar in bareAtomVarColumn: continue 284 285 self.gridAtoms.AutosizeLabels() 286 self.gridAtoms.AutoSizeColumns() 287 self.gridAtoms.EndBatch() 288 289 self.gridAtoms.AdjustScrollbars() 290 self.gridAtoms.ForceRefresh() 291 return
292
293 - def refreshTextCtrls(self):
294 """Refreshes the TextCtrls. """ 295 296 for widget, var in zip(self._textctrls, self.lConstraints): 297 wobj = getattr(self, widget) 298 if var in self.constraints: 299 s = self.constraints[var].formula 300 else: 301 s = "" 302 wobj.SetValue(s) 303 304 pairs = self.structure.getSelectedPairs() 305 self.textCtrlIncludedPairs.SetValue(pairs) 306 return
307 308
309 - def applyTextCtrlChange(self, id, value):
310 """Update a structure according to a change in a TextCtrl. 311 312 id -- textctrl id 313 value -- new value 314 """ 315 self.mainFrame.needsSave() 316 var = self._id2varname[id] 317 formula = value.strip() 318 if formula != "": 319 self.constraints[var] = Constraint(formula) 320 return self.constraints[var].formula 321 else: 322 self.constraints.pop(var, None) 323 return ""
324
325 - def applyCellChange(self, i, j, value):
326 """Update an atom according to a change in a cell. 327 328 i -- cell position 329 j -- cell position 330 value -- new value 331 332 returns the new value stored in the data object, or None if value is 333 somehow invalid. 334 """ 335 self.mainFrame.needsSave() 336 key = self.lAtomConstraints[j-1] + '('+`i+1`+')' 337 formula = value.strip() 338 if formula != "": 339 self.constraints[key] = Constraint(formula) 340 return self.constraints[key].formula 341 else: 342 self.constraints.pop(key, None) 343 return "" 344 return
345 346 347 ########################################################################## 348 # Event Handlers 349 350 # TextCtrl Events
351 - def onSetFocus(self, event):
352 """Saves a TextCtrl value, to be compared in onKillFocuse later.""" 353 self._focusedText = event.GetEventObject().GetValue() 354 return
355
356 - def onKillFocus(self, event):
357 """Check value of TextCtrl and update structure if necessary.""" 358 if not self.mainFrame: return 359 textctrl = event.GetEventObject() 360 value = textctrl.GetValue() 361 if value != self._focusedText: 362 self.applyTextCtrlChange(textctrl.GetId(), value) 363 self.refreshTextCtrls() 364 self.mainFrame.needsSave() 365 self._focusedText = None 366 return
367 368 # Grid Events
369 - def onLabelRightClick(self, event): # wxGlade: PhaseConstraintsPanel.<event_handler>
370 """Bring up right-click menu.""" 371 if self.structure is not None: 372 dx = dy = 0 373 if event.GetRow() == -1: 374 dy = self.gridAtoms.GetGridCornerLabelWindow().GetSize().y 375 if event.GetCol() == -1: 376 dx = self.gridAtoms.GetGridCornerLabelWindow().GetSize().x 377 378 # do not popup menu if the whole grid is set to read only 379 if len(self.structure) == 0: 380 self.popupMenu(self.gridAtoms, event.GetPosition().x-dx, 381 event.GetPosition().y-dy) 382 event.Skip() 383 return
384
385 - def onCellRightClick(self, event): # wxGlade: PhaseConstraintsPanel.<event_handler>
386 """Bring up right-click menu.""" 387 self._row = event.GetRow() 388 self._col = event.GetCol() 389 390 # If the right-clicked node is not part of a group, then make sure that 391 # it is the only selected cell. 392 append = False 393 r = self._row 394 c = self._col 395 if self.gridAtoms.IsInSelection(r,c): 396 append = True 397 self.gridAtoms.SelectBlock(r,c,r,c,append) 398 399 self.popupMenu(self.gridAtoms, event.GetPosition().x, event.GetPosition().y) 400 event.Skip() 401 return 402
403 - def onEditorShown(self, event): # wxGlade: PhaseConstraintsPanel.<event_handler>
404 """Capture the focused text when the grid editor is shown.""" 405 i = event.GetRow() 406 j = event.GetCol() 407 self._focusedText = self.gridAtoms.GetCellValue(i,j) 408 self._selectedCells = phasepanelutils.getSelectedCells(self) 409 return 410
411 - def onCellChange(self, event): # wxGlade: PhaseConstraintsPanel.<event_handler>
412 """Update focused and selected text when a cell changes.""" 413 # NOTE: be careful with refresh(). It calls Grid.AutoSizeColumns, which 414 # creates a EVT_GRID_CMD_CELL_CHANGE event, which causes a recursion 415 # loop. 416 i = event.GetRow() 417 j = event.GetCol() 418 419 value = self.gridAtoms.GetCellValue(i,j) 420 while (i,j) in self._selectedCells: 421 self._selectedCells.remove((i,j)) 422 # We need the edited cell to be at the front of the list 423 self._selectedCells.insert(0,(i,j)) 424 self.fillCells(value) 425 self._focusedText = None 426 return 427
428 - def fillCells(self, value):
429 """Fill cells with a given value. 430 431 value -- string value to place into cells 432 433 This uses the member variable _selectedCells, a list of (i,j) tuples for 434 the selected cells. 435 """ 436 for (i,j) in self._selectedCells: 437 if not self.gridAtoms.IsReadOnly(i,j): 438 # Get the last valid text from the cell. For the cell that triggered 439 # this method, that is the _focusedText, for other cells it is the 440 # value returned by GetCellValue 441 oldvalue = self._focusedText 442 if oldvalue is None: 443 oldvalue = self.gridAtoms.GetCellValue(i,j) 444 self._focusedText = None 445 newvalue = self.applyCellChange(i,j, value) 446 #print i, j, value, oldvalue, newvalue 447 if newvalue is None: 448 # Get out of here. If the value is invalid, it won't be valid 449 # for any cells. 450 newvalue = oldvalue 451 self.gridAtoms.SetCellValue(i,j,str(newvalue)) 452 break 453 else: 454 self.gridAtoms.SetCellValue(i,j,str(newvalue)) 455 456 phasepanelutils.quickResizeColumns(self, self._selectedCells) 457 return
458 459
460 - def onKey(self, event):
461 """Catch key events in the panel.""" 462 key = event.GetKeyCode() 463 464 # Select All - Ctrl+A 465 if event.ControlDown() and key == 65: 466 rows = self.gridAtoms.GetNumberRows() 467 cols = self.gridAtoms.GetNumberCols() 468 self.gridAtoms.SelectBlock(0,0,rows,cols) 469 470 # Delete 471 elif key == 127: 472 self._selectedCells = phasepanelutils.getSelectedCells(self) 473 self.fillCells("") 474 self.mainFrame.needsSave() 475 476 # Can't get these to work. Maybe later. 477 ## Copy - Ctrl+C / Ctrl+Insert 478 #if event.ControlDown() and (key == 67 or key == wx.WXK_INSERT): 479 # if phasepanelutils.canCopySelectedCells(self): 480 # phasepanelutils.copySelectedCells(self) 481 482 ## Paste - Ctrl+V / Shift+Insert 483 #if (event.ControlDown() and key == 86) or\ 484 # (event.ShiftDown() and key == wx.WXK_INSERT): 485 # if phasepanelutils.canPasteIntoCells(self): 486 # phasepanelutils.pasteIntoCells(self) 487 488 else: 489 event.Skip() 490 return
491 492 ########################################################################## 493 # Grid popup menu and handlers 494
495 - def popupMenu(self, window, x, y):
496 """Creates the popup menu 497 498 window -- window, where to popup a menu 499 x -- x coordinate 500 y -- y coordinate 501 """ 502 # only do this part the first time so the events are only bound once 503 if not hasattr(self, "spaceGroupID"): 504 self.spaceGroupID = wx.NewId() 505 self.copyID = wx.NewId() 506 self.pasteID = wx.NewId() 507 508 self.Bind(wx.EVT_MENU, self.onPopupSpaceGroup, id=self.spaceGroupID) 509 self.Bind(wx.EVT_MENU, self.onPopupCopy, id=self.copyID) 510 self.Bind(wx.EVT_MENU, self.onPopupPaste, id=self.pasteID) 511 512 # make a menu 513 menu = wx.Menu() 514 515 # add some other items 516 menu.Append(self.spaceGroupID, "Symmetry constraints...") 517 menu.AppendSeparator() 518 menu.Append(self.copyID, "Copy") 519 menu.Append(self.pasteID, "Paste") 520 521 # Disable some items if there are no atoms selected 522 indices = phasepanelutils.getSelectedAtoms(self) 523 if not indices: 524 menu.Enable(self.spaceGroupID, False); 525 526 # Check for copy/paste 527 if not phasepanelutils.canCopySelectedCells(self): 528 menu.Enable(self.copyID, False) 529 if not phasepanelutils.canPasteIntoCells(self): 530 menu.Enable(self.pasteID, False) 531 532 # Popup the menu. If an item is selected then its handler 533 # will be called before PopupMenu returns. 534 window.PopupMenu(menu, wx.Point(x,y)) 535 menu.Destroy() 536 return
537
538 - def onPopupSpaceGroup(self, event):
539 """Create a supercell with the supercell dialog.""" 540 if self.structure is not None: 541 542 indices = phasepanelutils.getSelectedAtoms(self) 543 dlg = SGConstrainDialog(self) 544 dlg.mainFrame = self.mainFrame 545 dlg.indices = indices 546 dlg.setStructure(self.structure) 547 dlg.updateWidgets() 548 if dlg.ShowModal() == wx.ID_OK: 549 spcgrp = dlg.getSpaceGroup() 550 offset = dlg.getOffset() 551 posflag = dlg.getPosFlag() 552 tempflag = dlg.getTempFlag() 553 self.structure.applySymmetryConstraints(spcgrp, 554 indices, posflag, tempflag, offset) 555 self.refresh() 556 dlg.Destroy() 557 self.mainFrame.needsSave() 558 return
559
560 - def onPopupCopy(self, event):
561 """Copy selected cells.""" 562 phasepanelutils.copySelectedCells(self) 563 return
564
565 - def onPopupPaste(self, event):
566 """Paste previously copied cells.""" 567 phasepanelutils.pasteIntoCells(self) 568 return
569 570 # end of class PhaseConstraintsPanel 571