Author: bugman Date: Tue Oct 29 10:22:00 2013 New Revision: 21292 URL: http://svn.gna.org/viewcvs/relax?rev=21292&view=rev Log: Created a special GUI analysis element for floating point numbers. This allows for user input of floating point numbers into one of the GUI analysis tabs. If the input is not a number, the original value will be restored. Added: trunk/gui/analyses/elements/float_element.py - copied, changed from r21260, trunk/gui/analyses/elements/text_element.py Modified: trunk/gui/analyses/elements/__init__.py Modified: trunk/gui/analyses/elements/__init__.py URL: http://svn.gna.org/viewcvs/relax/trunk/gui/analyses/elements/__init__.py?rev=21292&r1=21291&r2=21292&view=diff ============================================================================== --- trunk/gui/analyses/elements/__init__.py (original) +++ trunk/gui/analyses/elements/__init__.py Tue Oct 29 10:22:00 2013 @@ -25,6 +25,7 @@ # The package contents. __all__ = [ 'bool_element', + 'float_element', 'model_list', 'spin_element', 'text_element' Copied: trunk/gui/analyses/elements/float_element.py (from r21260, trunk/gui/analyses/elements/text_element.py) URL: http://svn.gna.org/viewcvs/relax/trunk/gui/analyses/elements/float_element.py?p2=trunk/gui/analyses/elements/float_element.py&p1=trunk/gui/analyses/elements/text_element.py&r1=21260&r2=21292&rev=21292&view=diff ============================================================================== --- trunk/gui/analyses/elements/text_element.py (original) +++ trunk/gui/analyses/elements/float_element.py Tue Oct 29 10:22:00 2013 @@ -33,13 +33,13 @@ from gui.string_conv import str_to_gui -class Text_ctrl: - """The analysis specific text control. - - This consists of three elements: wx.StaticText, wx.TextCtrl, and wx.Button. +class Float_ctrl: + """The analysis specific floating point number control. + + This consists of two elements: wx.StaticText and wx.TextCtrl. """ - def __init__(self, box, parent, text="", default="", tooltip=None, tooltip_button=None, button_text=" Change", control=wx.TextCtrl, icon=icon_16x16.open, fn=None, editable=True, button=False, width_text=200, width_button=80, spacer=0): + def __init__(self, box, parent, text="", default="", tooltip=None, editable=True, width_text=200, width_button=80, spacer=0): """Create a text selection element for the frame. This consists of a horizontal layout with a static text element, a text control, and an optional button. @@ -54,23 +54,11 @@ @type default: str @keyword tooltip: The tooltip which appears on hovering over the text or input field. @type tooltip: str - @keyword tooltip_button: The separate tooltip for the button. - @type tooltip_button: str - @keyword button_text: The text to display on the button. - @type button_text: str - @keyword control: The control class to use. - @type control: wx.TextCtrl derived class - @keyword icon: The path of the icon to use for the button. - @type icon: str - @keyword fn: The function or method to execute when clicking on the button. If this is a string, then an equivalent function will be searched for in the control object. - @type fn: func or str @keyword editable: A flag specifying if the control is editable or not. @type editable: bool - @keyword button: A flag which if True will cause a button to appear. - @type button: bool @keyword width_text: The width of the text element. @type width_text: int - @keyword width_button: The width of the button. + @keyword width_button: The width of the standard button used in the other elements. @type width_button: int @keyword spacer: The horizontal spacing between the elements. @type spacer: int @@ -92,8 +80,8 @@ # Spacer. sizer.AddSpacer((spacer, -1)) - # The text input field. - self.field = control(parent, -1, str_to_gui(default)) + # The floating point number input field. + self.field = wx.TextCtrl(parent, -1, str_to_gui(default)) self.field.SetMinSize((-1, size_horizontal)) self.field.SetFont(font.normal) self.field.SetEditable(editable) @@ -102,27 +90,16 @@ self.field.SetOwnBackgroundColour(colour) sizer.Add(self.field, 1, wx.ALIGN_CENTER_VERTICAL|wx.ADJUST_MINSIZE, 0) + # Catch all input to ensure that it is a float. + self.field.Bind(wx.EVT_KEY_DOWN, self.pre_input) + self.field.Bind(wx.EVT_TEXT, self.post_input) + self.field.Bind(wx.EVT_KEY_UP, self.end_input) + # Spacer. sizer.AddSpacer((spacer, -1)) - # The button. - if button: - # Function is in the control class. - if isinstance(fn, str): - # The function. - fn = getattr(field, fn) - - # Add the button. - self.button = wx.lib.buttons.ThemedGenBitmapTextButton(parent, -1, None, str_to_gui(button_text)) - self.button.SetBitmapLabel(wx.Bitmap(icon, wx.BITMAP_TYPE_ANY)) - self.button.SetMinSize((width_button, size_horizontal)) - self.button.SetFont(font.normal) - parent.Bind(wx.EVT_BUTTON, fn, self.button) - sizer.Add(self.button, 0, wx.ALIGN_CENTER_VERTICAL|wx.ADJUST_MINSIZE, 0) - - # No button, so add a spacer. - else: - sizer.AddSpacer((width_button, -1)) + # Empty space where buttons normally are. + sizer.AddSpacer((width_button, -1)) # Add the element to the box. box.Add(sizer, 0, wx.ALL|wx.EXPAND, 0) @@ -131,8 +108,6 @@ if tooltip: self.label.SetToolTipString(tooltip) self.field.SetToolTipString(tooltip) - if button and tooltip_button: - self.button.SetToolTipString(tooltip_button) def Enable(self, enable=True): @@ -142,10 +117,8 @@ @type enable: bool """ - # Call the control and button methods. + # Call the text control method. self.field.Enable(enable) - if hasattr(self, 'button'): - self.button.Enable(enable) def GetValue(self): @@ -168,3 +141,77 @@ # Set the value of the text control. return self.field.SetValue(value) + + + def end_input(self, event): + """Restore the cursor position at the end if needed. + + This does not work so well as multiple wx.EVT_KEY_DOWN events can occur for a single wx.EVT_TEXT. + + @param event: The wx event. + @type event: wx event + """ + + # Restore the input position. + if self._restore_pos_flag: + self.field.SetInsertionPoint(self._pos) + + # Thaw the field to allow the text to be displayed. + self.field.Thaw() + + + def pre_input(self, event): + """Catch all key presses to store the original value and position and freeze the element. + + @param event: The wx event. + @type event: wx event + """ + + # Initialise the restore position flag. + self._restore_pos_flag = False + + # Store the value and position to restore if the input is bad. + self._value = self.field.GetValue() + self._pos = self.field.GetInsertionPoint() + + # Freeze the field so that the changed text is only shown at the end. + self.field.Freeze() + + # Continue the event to allow text to be entered. + event.Skip() + + + def post_input(self, event): + """Check that the user input is a float when the text changes, restoring the value if not. + + @param event: The wx event. + @type event: wx event + """ + + # Get the value. + value = self.field.GetValue() + + # Initialise the restore flag. + flag = False + + # Check if it is a number and, if not, restore the original text. + try: + float(value) + except ValueError: + flag = True + + # Do not allow spaces. + if ' ' in value: + flag = True + + # Do not allow 'e' for the exponent. + if 'e' in value or 'E' in value: + flag = True + + # Restore the original text and set the flag to restore the cursor position. + if flag: + self.field.SetValue(self._value) + self._restore_pos_flag = True + + # Continue the event. + event.Skip()