@@ -271,9 +271,12 @@ class ValidatedTxtCtrl(wx.TextCtrl):
271
271
came from. The type of the initial value must be int,
272
272
float or str or None (see :obj:`key` and :obj:`typeHint`);
273
273
this type (or the one in :obj:`typeHint`) is preserved.
274
+ Values are processed and saved when Enter is pressed, when the
275
+ mouse is moved to another control (leave window or focus is lost)
276
+ or after a change and a delay of two seconds.
274
277
275
278
Float values can be entered in the TextCtrl as numbers or also
276
- as algebraic expressions using operators + - / \\ * () and \\ *\\ *,
279
+ as algebraic expressions using operators ( + - / \\ * () and \\ *\\ *) ,
277
280
in addition pi, sind(), cosd(), tand(), and sqrt() can be used,
278
281
as well as appreviations s, sin, c, cos, t, tan and sq.
279
282
@@ -364,7 +367,6 @@ class ValidatedTxtCtrl(wx.TextCtrl):
364
367
def __init__ (self ,parent ,loc ,key ,nDig = None ,notBlank = True ,xmin = None ,xmax = None ,
365
368
OKcontrol = None ,OnLeave = None ,typeHint = None ,CIFinput = False ,exclLim = [False ,False ],
366
369
OnLeaveArgs = {}, ASCIIonly = False ,
367
- min = None , max = None , # patch: remove this eventually
368
370
** kw ):
369
371
# save passed values needed outside __init__
370
372
self .result = loc
@@ -376,25 +378,12 @@ def __init__(self,parent,loc,key,nDig=None,notBlank=True,xmin=None,xmax=None,
376
378
self .CIFinput = CIFinput
377
379
self .notBlank = notBlank
378
380
self .ASCIIonly = ASCIIonly
379
-
380
- # patch: remove this when min & max are no longer used to call this
381
- if min is not None :
382
- xmin = min
383
- if GSASIIpath .GetConfigValue ('debug' ):
384
- print ('Call to ValidatedTxtCtrl using min (change to xmin) here:' )
385
- G2obj .HowDidIgetHere (True )
386
- if max is not None :
387
- xmax = max
388
- if GSASIIpath .GetConfigValue ('debug' ):
389
- print ('Call to ValidatedTxtCtrl using max (change to xmax) here:' )
390
- G2obj .HowDidIgetHere (True )
391
- # end patch
392
-
381
+
393
382
# initialization
394
383
self .invalid = False # indicates if the control has invalid contents
395
384
self .evaluated = False # set to True when the validator recognizes an expression
396
385
self .timer = None # tracks pending updates for expressions in float textctrls
397
- self .delay = 5000 # delay for timer update (5 sec)
386
+ self .delay = 2000 # delay for timer update (2 sec)
398
387
self .type = str
399
388
400
389
val = loc [key ]
@@ -447,7 +436,7 @@ def __init__(self,parent,loc,key,nDig=None,notBlank=True,xmin=None,xmax=None,
447
436
else :
448
437
wx .TextCtrl .__init__ (self ,parent ,wx .ID_ANY ,** kw )
449
438
if val is not None :
450
- self .SetValue (val )
439
+ self .ChangeValue (val )
451
440
if notBlank :
452
441
self .Bind (wx .EVT_CHAR ,self ._onStringKey )
453
442
self .ShowStringValidity () # test if valid input
@@ -460,15 +449,42 @@ def __init__(self,parent,loc,key,nDig=None,notBlank=True,xmin=None,xmax=None,
460
449
self .Bind (wx .EVT_LEAVE_WINDOW , self ._onLeaveWindow )
461
450
self .Bind (wx .EVT_KILL_FOCUS , self ._onLoseFocus )
462
451
self .Bind (wx .EVT_TEXT_ENTER , self ._onLoseFocus )
463
- # patch for wx 2.9 on Mac
464
- i ,j = wx .__version__ .split ('.' )[0 :2 ]
465
- if int (i )+ int (j )/ 10. > 2.8 and 'wxOSX' in wx .PlatformInfo :
466
- self .Bind (wx .EVT_KEY_DOWN , self .OnKeyDown )
467
452
468
- def SetValue (self ,val ):
469
- if self .result is not None : # note that this bypasses formatting
453
+ def SetValue (self ,val ,warn = True ):
454
+ '''Place a value into the text widget and save it into the
455
+ associated array element. Note that, unlike the stock wx.TextCtrl,
456
+ val is expected to be in the form expected by the widget
457
+ (float/int/str) rather than only str's.
458
+ For float val values, the value is formatted when placed in the
459
+ TextCtrl, but the supplied value is what is actually saved.
460
+
461
+ This routine triggers a wx.EVT_TEXT event
462
+ '''
463
+ # GSAS-II callback routines should call ChangeValue not SetValue
464
+ # for debugging flag calls. Set warn to False for calls that are not in callbacks
465
+ # and thus are OK
466
+ #if GSASIIpath.GetConfigValue('debug') and warn:
467
+ # G2obj.HowDidIgetHere(True)
468
+ if self .result is not None :
470
469
self .result [self .key ] = val
471
470
self ._setValue (val )
471
+ # Direct calls to SetValue should trigger an event
472
+ wx .TextCtrl .SetValue (self ,wx .TextCtrl .GetValue (self ))
473
+
474
+ def ChangeValue (self ,val ):
475
+ '''Place a value into the text widget and save it into the
476
+ associated array element. Note that, unlike the stock wx.TextCtrl,
477
+ val is expected to be in the form expected by the widget
478
+ (float/int/str) rather than only str's.
479
+ For float val values, the value is formatted when placed in the
480
+ TextCtrl, but the supplied value is what is actually saved.
481
+
482
+ This routine does not trigger a wx.EVT_TEXT event. This is what
483
+ should be used inside event callbacks, not :meth:`SetValue`.
484
+ '''
485
+ if self .result is not None :
486
+ self .result [self .key ] = val
487
+ self ._setValue (val )
472
488
473
489
def _setValue (self ,val ,show = True ):
474
490
'''Check the validity of an int or float value and convert to a str.
@@ -487,7 +503,7 @@ def _setValue(self,val,show=True):
487
503
pass
488
504
else :
489
505
self .invalid = True
490
- if show and not self .invalid : wx .TextCtrl .SetValue (self ,str (val ))
506
+ if show and not self .invalid : wx .TextCtrl .ChangeValue (self ,str (val ))
491
507
elif self .type is float :
492
508
try :
493
509
if type (val ) is str : val = val .replace (',' ,'.' )
@@ -498,10 +514,10 @@ def _setValue(self,val,show=True):
498
514
else :
499
515
self .invalid = True
500
516
if self .nDig and show and not self .invalid :
501
- wx .TextCtrl .SetValue (self ,str (G2fil .FormatValue (val ,self .nDig )))
517
+ wx .TextCtrl .ChangeValue (self ,str (G2fil .FormatValue (val ,self .nDig )))
502
518
self .evaluated = False # expression has been recast as value, reset flag
503
519
elif show and not self .invalid :
504
- wx .TextCtrl .SetValue (self ,str (G2fil .FormatSigFigs (val )).rstrip ('0' ))
520
+ wx .TextCtrl .ChangeValue (self ,str (G2fil .FormatSigFigs (val )).rstrip ('0' ))
505
521
self .evaluated = False # expression has been recast as value, reset flag
506
522
else :
507
523
if self .ASCIIonly :
@@ -516,9 +532,9 @@ def _setValue(self,val,show=True):
516
532
show = True
517
533
if show :
518
534
try :
519
- wx .TextCtrl .SetValue (self ,str (val ))
535
+ wx .TextCtrl .ChangeValue (self ,str (val ))
520
536
except :
521
- wx .TextCtrl .SetValue (self ,val )
537
+ wx .TextCtrl .ChangeValue (self ,val )
522
538
self .ShowStringValidity () # test if valid input
523
539
return
524
540
@@ -550,15 +566,17 @@ def _IndicateValidity(self):
550
566
ins = self .GetInsertionPoint ()
551
567
self .SetForegroundColour ("red" )
552
568
self .SetBackgroundColour ("yellow" )
553
- self .SetFocus ()
569
+ if not sys .platform .startswith ("linux" ):
570
+ self .SetFocus ()
554
571
self .Refresh () # this selects text on some Linuxes
555
572
self .SetSelection (0 ,0 ) # unselect
556
573
self .SetInsertionPoint (ins ) # put insertion point back
557
574
else : # valid input
558
575
self .SetBackgroundColour (wx .SystemSettings .GetColour (wx .SYS_COLOUR_WINDOW ))
559
576
self .SetForegroundColour (wx .SystemSettings .GetColour (wx .SYS_COLOUR_BTNTEXT ))
560
577
self .Refresh ()
561
- self .SetFocus () # seems needed, at least on MacOS to get color change
578
+ if not sys .platform .startswith ("linux" ):
579
+ self .SetFocus () # seems needed, at least on MacOS to get color change
562
580
563
581
def _GetNumValue (self ):
564
582
'Get and where needed convert string from GetValue into int or float'
@@ -605,7 +623,10 @@ def _GetStringValue(self,event):
605
623
wx .CallAfter (self ._SaveStringValue )
606
624
607
625
def _SaveStringValue (self ):
608
- val = self .GetValue ().strip ()
626
+ try :
627
+ val = self .GetValue ().strip ()
628
+ except RuntimeError : # ignore if control has been deleted
629
+ return
609
630
# always store the result
610
631
if self .CIFinput and '2' in platform .python_version_tuple ()[0 ]: # Py2/CIF make results ASCII
611
632
self .result [self .key ] = val .encode ('ascii' ,'replace' )
@@ -5787,8 +5808,20 @@ class HelpButton(wx.Button):
5787
5808
def __init__ (self ,parent ,msg = '' ,helpIndex = '' ,wrap = None ):
5788
5809
if sys .platform == "darwin" :
5789
5810
wx .Button .__init__ (self ,parent ,wx .ID_HELP )
5790
- else :
5811
+ elif sys . platform . startswith ( "linux" ) :
5791
5812
wx .Button .__init__ (self ,parent ,wx .ID_ANY ,'?' ,style = wx .BU_EXACTFIT )
5813
+ self .SetBackgroundColour ('yellow' )
5814
+ self .SetForegroundColour ('black' )
5815
+ f = wx .Font (self .GetFont ()).Bold ()
5816
+ f .SetPointSize (f .PointSize + 1 )
5817
+ self .SetFont (f )
5818
+ else : # button needs to be exaggerated in Windows
5819
+ wx .Button .__init__ (self ,parent ,wx .ID_ANY ,' ? ' ,style = wx .BU_EXACTFIT )
5820
+ self .SetBackgroundColour ('yellow' )
5821
+ self .SetForegroundColour ('black' )
5822
+ f = wx .Font (self .GetFont ()).Bold ()
5823
+ f .SetPointSize (f .PointSize + 4 )
5824
+ self .SetFont (f )
5792
5825
self .Bind (wx .EVT_BUTTON ,self ._onPress )
5793
5826
if wrap :
5794
5827
self .msg = StripIndents (msg ,True )
0 commit comments