Source code for diffpy.pdfgui.gui.phaseconfigurepanel

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
##############################################################################
#
# PDFgui            by DANSE Diffraction group
#                   Simon J. L. Billinge
#                   (c) 2006 trustees of the Michigan State University.
#                   All rights reserved.
#
# File coded by:    Chris Farrow, Dmitriy Bryndin
#
# See AUTHORS.txt for a list of people who contributed.
# See LICENSE.txt for license information.
#
##############################################################################

# generated by wxGlade 0.9.3 on Fri Jul 19 16:04:47 2019

import wx
import wx.grid

from diffpy.pdffit2 import is_element
from diffpy.pdfgui.control.controlerrors import TempControlSelectError
from diffpy.pdfgui.gui import phasepanelutils, tooltips
from diffpy.pdfgui.gui.insertrowsdialog import InsertRowsDialog
from diffpy.pdfgui.gui.pdfpanel import PDFPanel
from diffpy.pdfgui.gui.wxextensions.autowidthlabelsgrid import AutoWidthLabelsGrid
from diffpy.pdfgui.gui.wxextensions.textctrlutils import textCtrlAsGridCell
from diffpy.pdfgui.gui.wxextensions.validators import FLOAT_ONLY, TextValidator
from diffpy.structure import Atom
from diffpy.utils.wx import gridutils


[docs] class PhaseConfigurePanel(wx.Panel, PDFPanel): """Panel for configuring a phase. Data members: structure -- reference to PDFStructure _focusedText -- value of a cell or textctrl before it changes lConstraintsMap -- map of TextCtrl name to parameter name _row -- row, where rightclick occurred _col -- column, where rightclick occurred """ def __init__(self, *args, **kwds): PDFPanel.__init__(self) # begin wxGlade: PhaseConfigurePanel.__init__ kwds["style"] = kwds.get("style", 0) | wx.TAB_TRAVERSAL wx.Panel.__init__(self, *args, **kwds) self.SetFocus() sizerMain = wx.BoxSizer(wx.VERTICAL) sizerPanelName = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, ""), wx.HORIZONTAL) sizerMain.Add(sizerPanelName, 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 5) self.labelPanelName = wx.StaticText(self, wx.ID_ANY, "Phase Configuration") self.labelPanelName.SetFont( wx.Font( 18, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD, 0, "", ) ) sizerPanelName.Add(self.labelPanelName, 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT, 5) sizerLatticeParameters = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, ""), wx.HORIZONTAL) sizerMain.Add(sizerLatticeParameters, 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 5) grid_sizer_3 = wx.FlexGridSizer(2, 6, 0, 0) sizerLatticeParameters.Add(grid_sizer_3, 1, wx.EXPAND, 0) self.labelA = wx.StaticText(self, wx.ID_ANY, "a") grid_sizer_3.Add(self.labelA, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) self.textCtrlA = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) grid_sizer_3.Add(self.textCtrlA, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) self.labelB = wx.StaticText(self, wx.ID_ANY, "b") grid_sizer_3.Add(self.labelB, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) self.textCtrlB = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) grid_sizer_3.Add(self.textCtrlB, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) self.labelC = wx.StaticText(self, wx.ID_ANY, "c") grid_sizer_3.Add(self.labelC, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) self.textCtrlC = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) grid_sizer_3.Add(self.textCtrlC, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) self.labelAlpha = wx.StaticText(self, wx.ID_ANY, "alpha") grid_sizer_3.Add(self.labelAlpha, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) self.textCtrlAlpha = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) grid_sizer_3.Add(self.textCtrlAlpha, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) self.labelBeta = wx.StaticText(self, wx.ID_ANY, "beta") grid_sizer_3.Add(self.labelBeta, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) self.textCtrlBeta = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) grid_sizer_3.Add(self.textCtrlBeta, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) self.labelGamma = wx.StaticText(self, wx.ID_ANY, "gamma") grid_sizer_3.Add(self.labelGamma, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) self.textCtrlGamma = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) grid_sizer_3.Add(self.textCtrlGamma, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) sizerAdditionalParameters = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, ""), wx.HORIZONTAL) sizerMain.Add(sizerAdditionalParameters, 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 5) grid_sizer_4 = wx.FlexGridSizer(3, 6, 0, 0) sizerAdditionalParameters.Add(grid_sizer_4, 1, wx.EXPAND, 0) self.labelScaleFactor = wx.StaticText(self, wx.ID_ANY, "Scale Factor") grid_sizer_4.Add( self.labelScaleFactor, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5, ) self.textCtrlScaleFactor = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) grid_sizer_4.Add(self.textCtrlScaleFactor, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) grid_sizer_4.Add((20, 10), 0, 0, 0) grid_sizer_4.Add((20, 10), 0, 0, 0) grid_sizer_4.Add((20, 10), 0, 0, 0) grid_sizer_4.Add((20, 10), 0, 0, 0) self.labelDelta1 = wx.StaticText(self, wx.ID_ANY, "delta1") grid_sizer_4.Add(self.labelDelta1, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) self.textCtrlDelta1 = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) grid_sizer_4.Add(self.textCtrlDelta1, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) self.labelDelta2 = wx.StaticText(self, wx.ID_ANY, "delta2") grid_sizer_4.Add(self.labelDelta2, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) self.textCtrlDelta2 = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) grid_sizer_4.Add(self.textCtrlDelta2, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) self.labelSpdiameter = wx.StaticText(self, wx.ID_ANY, "spdiameter") grid_sizer_4.Add( self.labelSpdiameter, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5, ) self.textCtrlSpdiameter = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) grid_sizer_4.Add(self.textCtrlSpdiameter, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) self.labelSratio = wx.StaticText(self, wx.ID_ANY, "sratio") grid_sizer_4.Add(self.labelSratio, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) self.textCtrlSratio = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) grid_sizer_4.Add(self.textCtrlSratio, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) self.labelRcut = wx.StaticText(self, wx.ID_ANY, "rcut") grid_sizer_4.Add(self.labelRcut, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) self.textCtrlRcut = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) grid_sizer_4.Add(self.textCtrlRcut, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) self.labelStepcut = wx.StaticText(self, wx.ID_ANY, "stepcut") grid_sizer_4.Add(self.labelStepcut, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) self.textCtrlStepcut = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_PROCESS_ENTER) grid_sizer_4.Add(self.textCtrlStepcut, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 0) sizerAtoms = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, ""), wx.VERTICAL) sizerMain.Add(sizerAtoms, 1, wx.EXPAND | wx.LEFT | wx.RIGHT, 5) sizer_1 = wx.BoxSizer(wx.HORIZONTAL) sizerAtoms.Add(sizer_1, 0, wx.EXPAND, 0) self.labelIncludedPairs = wx.StaticText(self, wx.ID_ANY, "Included Pairs") sizer_1.Add(self.labelIncludedPairs, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) self.textCtrlIncludedPairs = wx.TextCtrl(self, wx.ID_ANY, "all-all") self.textCtrlIncludedPairs.SetMinSize((240, 25)) sizer_1.Add(self.textCtrlIncludedPairs, 0, wx.ALL, 5) self.gridAtoms = AutoWidthLabelsGrid(self, wx.ID_ANY, size=(1, 1)) self.gridAtoms.CreateGrid(0, 11) self.gridAtoms.EnableDragRowSize(0) self.gridAtoms.SetColLabelValue(0, "elem") self.gridAtoms.SetColLabelValue(1, "x") self.gridAtoms.SetColLabelValue(2, "y") self.gridAtoms.SetColLabelValue(3, "z") self.gridAtoms.SetColLabelValue(4, "u11") self.gridAtoms.SetColLabelValue(5, "u22") self.gridAtoms.SetColLabelValue(6, "u33") self.gridAtoms.SetColLabelValue(7, "u12") self.gridAtoms.SetColLabelValue(8, "u13") self.gridAtoms.SetColLabelValue(9, "u23") self.gridAtoms.SetColLabelValue(10, "occ") sizerAtoms.Add(self.gridAtoms, 1, wx.EXPAND, 0) self.SetSizer(sizerMain) sizerMain.Fit(self) self.Layout() self.Bind(wx.grid.EVT_GRID_CMD_CELL_CHANGED, self.onCellChange, self.gridAtoms) self.Bind(wx.grid.EVT_GRID_CMD_CELL_RIGHT_CLICK, self.onCellRightClick, self.gridAtoms) self.Bind(wx.grid.EVT_GRID_CMD_EDITOR_SHOWN, self.onEditorShown, self.gridAtoms) self.Bind( wx.grid.EVT_GRID_CMD_LABEL_RIGHT_CLICK, self.onLabelRightClick, self.gridAtoms, ) # end wxGlade self.__customProperties() # ######################################################################## # Misc Methods def __customProperties(self): """Custom properties for the panel.""" self.structure = None self.constraints = {} self.results = None self._row = 0 self._col = 0 self._focusedText = None self._selectedCells = [] self.lAtomConstraints = [ "x", "y", "z", "u11", "u22", "u33", "u12", "u13", "u23", "occ", ] # pdffit internal naming self.lConstraintsMap = { "textCtrlA": "lat(1)", "textCtrlB": "lat(2)", "textCtrlC": "lat(3)", "textCtrlAlpha": "lat(4)", "textCtrlBeta": "lat(5)", "textCtrlGamma": "lat(6)", "textCtrlScaleFactor": "pscale", "textCtrlDelta1": "delta1", "textCtrlDelta2": "delta2", "textCtrlSratio": "sratio", "textCtrlRcut": "rcut", "textCtrlStepcut": "stepcut", "textCtrlSpdiameter": "spdiameter", } # bind onSetFocus onKillFocus events to text controls for tname in self.lConstraintsMap: self.__dict__[tname].Bind(wx.EVT_SET_FOCUS, self.onSetFocus) self.__dict__[tname].Bind(wx.EVT_KILL_FOCUS, self.onKillFocus) self.__dict__[tname].SetValidator(TextValidator(FLOAT_ONLY)) self.__dict__[tname].Bind(wx.EVT_KEY_DOWN, self.onTextCtrlKey) self.textCtrlIncludedPairs.Bind(wx.EVT_SET_FOCUS, self.onSetFocus) self.textCtrlIncludedPairs.Bind(wx.EVT_KILL_FOCUS, self.onSelectedPairs) self.textCtrlIncludedPairs.Bind(wx.EVT_KEY_DOWN, self.onTextCtrlKey) # define tooltips self.setToolTips(tooltips.phasepanel) # make sure tooltips exist for all lConstraintsMap controls as # this is later assumed in restrictConstrainedParameters code for tname in self.lConstraintsMap: assert getattr(self, tname).GetToolTip() is not None # catch key events and apply them to the grid self.Bind(wx.EVT_KEY_DOWN, self.onKey) return # Create the onTextCtrlKey event handler from textCtrlAsGridCell from # wxextensions.textctrlutils onTextCtrlKey = textCtrlAsGridCell def _cache(self): """Cache the current structure and constraints for future comparison.""" pass __this_is_first_refresh = True
[docs] def refresh(self): """Refreshes widgets on the panel.""" phasepanelutils.refreshTextCtrls(self) pairs = self.structure.getSelectedPairs() self.textCtrlIncludedPairs.SetValue(pairs) phasepanelutils.refreshGrid(self) self.restrictConstrainedParameters() # wxpython 3.0 on Windows 7 prevents textCtrlA from receiving # left-click input focus and can be only focused with a Tab key. # This only happens for the first input, the text control behaves # normally after receiving focus once. # Workaround: do explicit focus here for the first rendering. if self.__this_is_first_refresh: self.__this_is_first_refresh = False focusowner = self.textCtrlA.FindFocus() wx.CallAfter(self.textCtrlA.SetFocus) if focusowner is not None: wx.CallAfter(focusowner.SetFocus) return
[docs] def restrictConstrainedParameters(self): """Set 'read-only' boxes that correspond to constrained parameters.""" self.setToolTips(tooltips.phasepanel) self.textCtrlA.DefaultStyle.BackgroundColour txtbg = self.textCtrlScaleFactor.DefaultStyle.BackgroundColour # First the TextCtrls for key, var in self.lConstraintsMap.items(): textCtrl = getattr(self, key) if var in self.constraints: textCtrl.SetEditable(False) textCtrl.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT)) tt = textCtrl.GetToolTip() tt.SetTip(self.constraints[var].formula) else: textCtrl.SetEditable(True) textCtrl.SetBackgroundColour(txtbg) # Now the grid rows = self.gridAtoms.GetNumberRows() cols = self.gridAtoms.GetNumberCols() for i in range(rows): for j in range(1, cols): var = self.lAtomConstraints[j - 1] var += "(%i)" % (i + 1) if var in self.constraints: self.gridAtoms.SetReadOnly(i, j, True) self.gridAtoms.SetCellBackgroundColour( i, j, wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT) ) else: self.gridAtoms.SetReadOnly(i, j, False) self.gridAtoms.SetCellBackgroundColour(i, j, wx.NullColour) return
[docs] def applyTextCtrlChange(self, id, value): """Update a structure according to a change in a TextCtrl. id -- textctrl id value -- new value """ if self.structure is None: return try: value = float(value) if id == self.textCtrlA.GetId(): self.structure.lattice.setLatPar(a=value) elif id == self.textCtrlB.GetId(): self.structure.lattice.setLatPar(b=value) elif id == self.textCtrlC.GetId(): self.structure.lattice.setLatPar(c=value) elif id == self.textCtrlAlpha.GetId(): self.structure.lattice.setLatPar(alpha=value) elif id == self.textCtrlBeta.GetId(): self.structure.lattice.setLatPar(beta=value) elif id == self.textCtrlGamma.GetId(): self.structure.lattice.setLatPar(gamma=value) elif id == self.textCtrlScaleFactor.GetId(): self.structure.pdffit["scale"] = value elif id == self.textCtrlDelta1.GetId(): self.structure.pdffit["delta1"] = value elif id == self.textCtrlDelta2.GetId(): self.structure.pdffit["delta2"] = value elif id == self.textCtrlSratio.GetId(): self.structure.pdffit["sratio"] = value elif id == self.textCtrlRcut.GetId(): self.structure.pdffit["rcut"] = value elif id == self.textCtrlStepcut.GetId(): self.structure.pdffit["stepcut"] = value elif id == self.textCtrlSpdiameter.GetId(): self.structure.pdffit["spdiameter"] = value return value except Exception: return None
[docs] def applyCellChange(self, i, j, value): """Update an atom according to a change in a cell. i -- cell position j -- cell position value -- new value """ if not self.mainFrame or self.structure is None: return # The element name if j == 0: value = value.title() if not is_element(value): return self.structure[i].element = value # element return value # Other entries # ignore the change if the value is not valid try: value = float(value) if value == "": value = 0.0 if j == 1: self.structure[i].xyz[0] = value # x elif j == 2: self.structure[i].xyz[1] = value # y elif j == 3: self.structure[i].xyz[2] = value # z elif j == 4: self.structure[i].U[0, 0] = value # U(1,1) elif j == 5: self.structure[i].U[1, 1] = value # U(2,2) elif j == 6: self.structure[i].U[2, 2] = value # U(3,3) elif j == 7: self.structure[i].U[0, 1] = self.structure[i].U[1, 0] = value # U(1,2) elif j == 8: self.structure[i].U[0, 2] = self.structure[i].U[2, 0] = value # U(1,3) elif j == 9: self.structure[i].U[1, 2] = self.structure[i].U[2, 1] = value # U(2,3) elif j == 10: self.structure[i].occupancy = value # occupancy self.mainFrame.needsSave() return value except ValueError: return
# ######################################################################## # Event Handlers # TextCtrl Events
[docs] def onSetFocus(self, event): """Saves a TextCtrl value, to be compared in onKillFocus later.""" self._focusedText = event.GetEventObject().GetValue() event.Skip() return
[docs] def onKillFocus(self, event): """Check value of TextCtrl and update structure if necessary.""" if not self.mainFrame: return textctrl = event.GetEventObject() value = textctrl.GetValue() if value != self._focusedText: self.applyTextCtrlChange(textctrl.GetId(), value) phasepanelutils.refreshTextCtrls(self) self.mainFrame.needsSave() self._focusedText = None event.Skip() return
[docs] def onSelectedPairs(self, event): """Check to see if the value of the selected pairs is valid.""" if not self.mainFrame: return value = self.textCtrlIncludedPairs.GetValue() self.structure.setSelectedPairs(value) value = self.structure.getSelectedPairs() self.textCtrlIncludedPairs.SetValue(value) event.Skip() return
# Grid Events
[docs] def onLabelRightClick(self, event): # wxGlade: PhaseConfigurePanel.<event_handler> """Bring up right-click menu.""" if self.structure is not None: dx = dy = 0 if event.GetRow() == -1: dy = self.gridAtoms.GetGridCornerLabelWindow().GetSize().y if event.GetCol() == -1: dx = self.gridAtoms.GetGridCornerLabelWindow().GetSize().x # do not popup menu if the whole grid is set to read only if len(self.structure) == 0: self.popupMenu( self.gridAtoms, event.GetPosition().x - dx, event.GetPosition().y - dy, ) event.Skip() return
[docs] def onCellRightClick(self, event): # wxGlade: PhaseConfigurePanel.<event_handler> """Bring up right-click menu.""" self._row = event.GetRow() self._col = event.GetCol() # If the right-clicked node is not part of a group, then make sure that # it is the only selected cell. append = False r = self._row c = self._col if self.gridAtoms.IsInSelection(r, c): append = True self.gridAtoms.SelectBlock(r, c, r, c, append) self.popupMenu(self.gridAtoms, event.GetPosition().x, event.GetPosition().y) event.Skip() return
[docs] def onEditorShown(self, event): # wxGlade: PhaseConfigurePanel.<event_handler> """Capture the focused text when the grid editor is shown.""" i = event.GetRow() j = event.GetCol() self._focusedText = self.gridAtoms.GetCellValue(i, j) # self._selectedCells = gridutils.getSelectedCells(self.gridAtoms) # TODO: temporary show the error message for control-select. try: self._selectedCells = gridutils.getSelectedCells(self.gridAtoms) except TypeError: raise TempControlSelectError("controlselecterror") return
[docs] def onCellChange(self, event): # wxGlade: PhaseConfigurePanel.<event_handler> """Update focused and selected text when a cell changes.""" # NOTE: be careful with refresh(). It calls Grid.AutoSizeColumns, which # creates a EVT_GRID_CMD_CELL_CHANGED event, which causes a recursion # loop. i = event.GetRow() j = event.GetCol() value = self.gridAtoms.GetCellValue(i, j) while (i, j) in self._selectedCells: self._selectedCells.remove((i, j)) # We need the edited cell to be at the front of the list self._selectedCells.insert(0, (i, j)) self.fillCells(value) self._focusedText = None return
[docs] def fillCells(self, value): """Fill cells with a given value. value -- string value to place into cells This uses the member variable _selectedCells, a list of (i,j) tuples for the selected cells. """ for i, j in self._selectedCells: if not self.gridAtoms.IsReadOnly(i, j): # Get the last valid text from the cell. For the cell that triggered # this method, that is the _focusedText, for other cells it is the # value returned by GetCellValue oldvalue = self._focusedText or self.gridAtoms.GetCellValue(i, j) self._focusedText = None newvalue = self.applyCellChange(i, j, value) # print i, j, value, oldvalue, newvalue if newvalue is None: newvalue = oldvalue self.gridAtoms.SetCellValue(i, j, str(newvalue)) gridutils.quickResizeColumns(self.gridAtoms, self._selectedCells) return
[docs] def onKey(self, event): """Catch key events in the panel.""" key = event.GetKeyCode() # Select All # Ctrl A if event.ControlDown() and key == 65: rows = self.gridAtoms.GetNumberRows() cols = self.gridAtoms.GetNumberCols() self.gridAtoms.SelectBlock(0, 0, rows, cols) # context menu key elif key == wx.WXK_MENU: self.popupMenu(self.gridAtoms, event.GetPosition().x, event.GetPosition().y) # Vim-like search for atom selection elif key == 47: self.onPopupSelect(event) # Delete an atom # Delete elif key == 127: selected = self.gridAtoms.GetSelectedRows() if selected: self.structure.deleteAtoms(selected) self.refresh() self.mainFrame.needsSave() # Ctrl - elif event.ControlDown() and key == 45: indices = gridutils.getSelectionRows(self.gridAtoms) self.structure.deleteAtoms(indices) self.refresh() self.mainFrame.needsSave() # Append an atom # Ctrl + or Ctrl = elif event.ControlDown() and (key == 61 or key == 43): indices = gridutils.getSelectionRows(self.gridAtoms) pos = 0 if indices: pos = 1 + indices[-1] elif self.structure: pos = len(self.structure) # insert "rows" atoms into the structure atoms = [_defaultNewAtom()] self.structure.insertAtoms(pos, atoms) self.refresh() self.mainFrame.needsSave() else: event.Skip() return
# ######################################################################## # Grid popup menu and handlers
[docs] def popupMenu(self, window, x, y): """Creates the popup menu. window -- window, where to popup a menu x -- x coordinate y -- y coordinate """ # only do this part the first time so the events are only bound once if not hasattr(self, "insertID"): self.insertID = wx.NewIdRef() self.deleteID = wx.NewIdRef() self.selectID = wx.NewIdRef() self.copyID = wx.NewIdRef() self.pasteID = wx.NewIdRef() self.supercellID = wx.NewIdRef() self.spaceGroupID = wx.NewIdRef() self.Bind(wx.EVT_MENU, self.onPopupInsert, id=self.insertID) self.Bind(wx.EVT_MENU, self.onPopupDelete, id=self.deleteID) self.Bind(wx.EVT_MENU, self.onPopupSelect, id=self.selectID) self.Bind(wx.EVT_MENU, self.onPopupCopy, id=self.copyID) self.Bind(wx.EVT_MENU, self.onPopupPaste, id=self.pasteID) self.Bind(wx.EVT_MENU, self.onPopupSupercell, id=self.supercellID) self.Bind(wx.EVT_MENU, self.onPopupSpaceGroup, id=self.spaceGroupID) # make a menu menu = wx.Menu() # add some other items menu.Append(self.insertID, "&Insert atoms...") menu.Append(self.deleteID, "&Delete atoms") menu.AppendSeparator() menu.Append(self.selectID, "Select &atoms...") menu.Append(self.copyID, "&Copy") menu.Append(self.pasteID, "&Paste") menu.AppendSeparator() menu.Append(self.supercellID, "Create supercell...") menu.Append(self.spaceGroupID, "Expand space group...") # Disable some items if there are no atoms selected indices = gridutils.getSelectionRows(self.gridAtoms) if not indices: menu.Enable(self.deleteID, False) menu.Enable(self.spaceGroupID, False) # Disable some items if there is no structure if self.structure is None or len(self.structure) == 0: menu.Enable(self.deleteID, False) menu.Enable(self.supercellID, False) menu.Enable(self.spaceGroupID, False) # Check for copy/paste if not phasepanelutils.canCopySelectedCells(self): menu.Enable(self.copyID, False) if not phasepanelutils.canPasteIntoCells(self): menu.Enable(self.pasteID, False) # Popup the menu. If an item is selected then its handler # will be called before PopupMenu returns. window.PopupMenu(menu, wx.Point(x, y)) menu.Destroy() return
[docs] def onPopupInsert(self, event): """Adds rows to the grid.""" if self.structure is not None: dlg = InsertRowsDialog(self) if dlg.ShowModal() == wx.ID_OK: rows = dlg.spin_ctrl_Rows.GetValue() if len(self.structure) == 0: self._row = 0 elif dlg.radio_box_where.GetSelection() == 1: # if selected "below" self._row += 1 # insert "rows" atoms into the structure atoms = [_defaultNewAtom() for i in range(rows)] self.structure.insertAtoms(self._row, atoms) self.refresh() self.mainFrame.needsSave() # Highlight the elements of the new rows so that they can be # changed by the user. self.gridAtoms.SetFocus() self.gridAtoms.SelectBlock(self._row, 0, self._row + len(atoms) - 1, 0) self.gridAtoms.SetGridCursor(self._row, 0) dlg.Destroy() return
[docs] def onPopupDelete(self, event): """Deletes the row under mouse pointer from the grid.""" if self.structure is not None: indices = gridutils.getSelectionRows(self.gridAtoms) self.structure.deleteAtoms(indices) self.refresh() self.mainFrame.needsSave() return
[docs] def onPopupSelect(self, event): """Limit cell selection to specified atom selection string.""" phasepanelutils.showSelectAtomsDialog(self) return
[docs] def onPopupCopy(self, event): """Copy selected cells.""" phasepanelutils.copySelectedCells(self) return
[docs] def onPopupPaste(self, event): """Paste previously copied cells.""" phasepanelutils.pasteIntoCells(self) return
[docs] def onPopupSupercell(self, event): """Create a supercell with the supercell dialog.""" from diffpy.pdfgui.gui.supercelldialog import SupercellDialog if self.structure is not None: dlg = SupercellDialog(self) if dlg.ShowModal() == wx.ID_OK: mno = dlg.getMNO() self.structure.expandSuperCell(mno) self.refresh() self.mainFrame.needsSave() dlg.Destroy() return
[docs] def onPopupSpaceGroup(self, event): """Create a supercell with the supercell dialog.""" from diffpy.pdfgui.gui.sgstructuredialog import SGStructureDialog if self.structure is not None: indices = gridutils.getSelectionRows(self.gridAtoms) dlg = SGStructureDialog(self) dlg.mainFrame = self.mainFrame dlg.indices = indices dlg.setStructure(self.structure) if dlg.ShowModal() == wx.ID_OK: spcgrp = dlg.getSpaceGroup() offset = dlg.getOffset() self.structure.expandAsymmetricUnit(spcgrp, indices, offset) self.refresh() self.mainFrame.needsSave() dlg.Destroy() return
# end of class PhaseConfigurePanel # Local helpers -------------------------------------------------------------- def _defaultNewAtom(): """Create new atom instance with non-zero initial U.""" uii = 0.003 rv = Atom("C", [0.0, 0.0, 0.0], U=[[uii, 0, 0], [0, uii, 0], [0, 0, uii]]) return rv