;+ ; NAME: ; FSC_INPUTFIELD ; ; PURPOSE: ; ; The purpose of this compound widget is to provide an alternative ; to the CW_FIELD widget offered in the IDL distribution. What has ; always bothered me about CW_FIELD is that the text widgets do not ; look editable to the users on Windows platforms. This program ; corrects that deficiency and adds some features that I think ; would be helpful. For example, you can now assign an event handler ; to the compound widget. The program is written entirely as an object. ; A companion program, COYOTE_FIELD, has much the same functionality, ; but is written as a traditional compound widget. The point of writing ; the same program in two different ways is to give you the opportunity ; to compare and contrast the two methods. I personally think there ; is no substitute for the power of object programs. :-) ; ; AUTHOR: ; FANNING SOFTWARE CONSULTING ; David Fanning, Ph.D. ; 1645 Sheely Drive ; Fort Collins, CO 80526 USA ; Phone: 970-221-0438 ; E-mail: david@idlcoyote.com ; Coyote's Guide to IDL Programming: http://www.idlcoyote.com/ ; ; CATEGORY: ; ; General programming. ; ; CALLING SEQUENCE: ; ; objectRef = FSC_INPUTFIELD(parent, Title='X Size: ", Value=256, /IntegerValue) ; ; INPUT PARAMETERS: ; ; parent -- The parent widget ID of the compound widget. Required. ; ; INPUT KEYWORDS: ; ; Column -- Set this keyword to have the Label Widget above the Text Widget. ; CR_Only -- Set this keyword if you only want Carriage Return events. Note that no ; events are returned unless the EVENT_PRO or EVENT_FUNC keywords are also used. ; Decimal -- Set this keyword to the number of digits to the right of the decimal ; point in FLOATVALUE and DOUBLEVALUE numbers. ; Digits -- Set this keyword to the number of digits permitted in INTERGERVALUE and LONGVALUE numbers. ; DoubleValue -- Set this keyword if you want DOUBLE values returned. ; Event_Func -- Set this keyword to the name of an Event Function. If this ; keyword is undefined and the Event_Pro keyword is undefined, ; all compound widget events are handled internally and not ; passed on to the parent widget. ; Event_Pro -- Set this keyword to the name of an Event Procedure. If this ; keyword is undefined and the Event_Func keyword is undefined, ; all compound widget events are handled internally and not ; passed on to the parent widget. ; FieldFont -- The font name for the text in the Text Widget. ; FloatValue -- Set this keyword for FLOAT values. ; Focus_Events -- Set this keyword if you only want text events when the keyboard focus is ; moved out of the text widget. Note that no events are returned unless the ; EVENT_PRO or EVENT_FUNC keywords are also used. ; Frame -- Set this keyword to put a frame around the compound widget. ; IntegerValue -- Set this keyword for INTEGER values. ; LabelAlign -- Set this keyword to align label text. [0-center (default), 1-left, 2-right]. ; LabelFont -- The font name for the text in the Label Widget. ; LabelSize -- The X screen size of the Label Widget. ; LongValue -- Set this keyword for LONG values. ; Name -- A scalar string name of the object. (default = '') ; Positive -- Set this keyword if you want only positive numbers allowed. ; Row=row -- Set this keyword to have the Label beside the Text Widget. (The default.) ; Scr_XSize -- The X screen size of the compound widget. ; Scr_YSize -- The Y screen size of the compound widget. ; StringValue -- Set this keyword for STRING values. (The default.) ; Title -- The text to go on the Label Widget. ; UValue -- A user value for any purpose. ; Value -- The "value" of the compound widget. ; XSize -- The X size of the Text Widget. ; ; In addition, any keyword defined for WIDGET_TEXT, but not defined here (e.g., SENSITIVE), is ; passed along without inspection to the text widget. Use of "extra" keywords is discouraged. ; ; COMMON BLOCKS: ; ; None. ; ; RESTRICTIONS: ; ; None. ; ; EVENT STRUCTURE: ; ; All events are handled internally unless either the Event_Pro or Event_Func ; keywords are used to assign an event handler to the compound widget. By ; default all events generated by the text widget are passed to the assigned ; event handler. If you wish to receive only Carriage Return events, set the ; CR_Only keyword. ; ; event = { FSC_INPUTFIELD_EVENTS, $ ; The name of the event structure. ; ID: 0L, $ ; The ID of the compound widget's top-level base. ; TOP: 0L, $ ; The widget ID of the top-level base of the hierarchy. ; HANDLER: 0L, $ ; The event handler ID. Filled out by IDL. ; ObjRef: Obj_New(), $ ; The "self" object reference. Provided so you can call methods. ; Value: Ptr_New(), $ ; A pointer to the widget value. ; Type:"" ; A string indicating the type of data in the VALUE field. ; } ; Values are "INT", "LONG", "FLOAT", "DOUBLE", or "STRING". ; ; GETTING and SETTING VALUES: ; ; Almost all the properties of the widget can be obtained or set via ; the object's GetProperty and SetProperty methods (described below). ; But since traditional compound widgets have the ability to get and ; set the value of the compound widget, this capability is implemented ; as special methods. ; ; To get the value of the field, do this: value = objectRef->Get_Value() ; To set the value of the field, so this: objectRef->Set_Value, value, /IntegerValue ; ; The proper keyword should be used to set the data type of the value. If a keyword ; is not used, the data type is determined from the value itself. ; ; OBJECT PROCEDURE METHODS: ; ; GetProperty -- This method allows various properties of the widget to be ; returned via output keywords. The keywords that are available are: ; ; CR_Only -- A flag, if set, means only report carriage return events. ; DataType -- The data type of the field variable. ; Decimal -- Set this keyword to the number of digits to the right of the decimal ; point in FLOATVALUE and DOUBLEVALUE numbers. ; Digits -- Set this keyword to the number of digits permitted in INTERGERVALUE and LONGVALUE numbers. ; Event_Func -- The name of the event handler function. ; Event_Pro -- The name of the event handler function. ; Positive -- Indicates if the Positive number flag is set (1) or not (0). ; UValue -- The user value assigned to the compound widget. ; Value -- The "value" of the compound widget. ; Name -- A scalar string name of the object. ; ; Resize -- This method allows you to resize the compound widget's text field. ; The value parameter is an X screen size for the entire widget. The text ; widget is sized by using the value obtained from this value minus the ; X screen size of the label widget. ; ; objectRef->Resize, screen_xsize_value ; ; Set_Value -- This method allows you to set the "value" of the field. It takes ; one positional parameter, which is the value. ; ; objectRef->Set_Value, 5 ; ; Keywords available are these to set the type of the data. If keywords ; are not used, the data type is determined from the value. ; ; DoubleValue -- Set this keyword if you want DOUBLE values returned. ; FloatValue -- Set this keyword for FLOAT values. ; IntegerValue -- Set this keyword for INTEGER values. ; LongValue -- Set this keyword for LONG values. ; StringValue -- Set this keyword for STRING values. (The default.) ; ; SetProperty -- This method allows various properties of the widget to be ; set via input keywords. The keywords that are available are: ; ; CR_Only -- Set this keyword if you only want Carriage Return events. ; Decimal -- Set this keyword to the number of digits to the right of the decimal ; point in FLOATVALUE and DOUBLEVALUE numbers. ; Digits -- Set this keyword to the number of digits permitted in INTERGERVALUE and LONGVALUE numbers. ; DoubleValue -- Set this keyword if you want DOUBLE values returned. ; Event_Func -- Set this keyword to the name of an Event Function. ; Event_Pro -- Set this keyword to the name of an Event Procedure. ; FloatValue -- Set this keyword for FLOAT values. ; IntegerValue -- Set this keyword for INTEGER values. ; LabelSize -- The X screen size of the Label Widget. ; LongValue -- Set this keyword for LONG values. ; Name -- A scalar string name of the object. (default = '') ; Positive -- Set this keyword to indicate only positive numbers are allowed. ; Scr_XSize -- The X screen size of the text widget. ; Scr_YSize -- The Y screen size of the text widget. ; Sensitive -- Set to 1 to make the widget sensitive, and to 0 to make it insensitive. ; StringValue -- Set this keyword for STRING values. (The default.) ; Title -- The text to go on the Label Widget. ; UValue -- A user value for any purpose. ; Value -- The "value" of the compound widget. ; XSize -- The X size of the Text Widget. ; ; SetTabNext -- This method allows you to specify which field to go to when a TAB character ; is typed in the text widget. See the Example program below for an example of how to ; use this method. ; ; OBJECT FUNCTIONS METHODS: ; ; Get_Value -- Returns the "value" of the field. No parameters. Will be undefined ; if a "number" field is blank. Should be checked before using: ; ; IF N_Elements(objectRef->Get_Value()) NE 0 THEN Print, Value is: ', objectRef->Get_Value() ; ; GetID -- Returns the widget identifier of the compound widget's top-level base. ; (The first child of the parent widget.) No parameters. ; ; GetLabelSize -- Returns the X screen size of the label widget. No parameters. ; ; GetTextID -- Returns the widget identifier of the compound widget's text widget. ; No parameters. ; ; GetTextSize -- Returns the X screen size of the text widget. No parameters. ; ; PRIVATE OBJECT METHODS: ; ; Although there is really no such thing as a "private" method in IDL's ; object implementation, some methods are used internally and not meant to ; be acessed publicly. Here are a few of those methods. I list them because ; it may be these private methods are ones you wish to override in subclassed ; objects. ; ; MoveTab -- This method moves the focus to the widget identified in the "next" field, ; which must be set with the SetTabNext method. No parameters. Called automatically ; when a TAB character is typed in the text widget. ; ; Text_Events -- The main event handler method for the compound widget. All ; text widget events are processed here. ; ; ReturnValue -- This function method accepts a string input value and converts ; it to the type of data requested by the user. ; ; Validate -- This function method examines all text input and removes unwanted ; characters, depending upon the requested data type for the field. It makes it ; impossible, for example, to type alphanumeric characters in an INTEGER field. ; ; EXAMPLE: ; ; An example program is provided at the end of the FSC_INPUTFIELD code. To run it, ; type these commands: ; ; IDL> .Compile FSC_InputField ; IDL> Example ; ; NOTES: ; ; IDL 6.2 introduced new TAB behavior, which broke the previous TAB behavior. New TAB behavior ; is now supported, but FOCUS_EVENTS *must* be set on the widget for the new TAB events to ; behave properly. See the EXAMPLE program for examples. ; ; DEPENDENCIES: ; ; Requires cgDblToStr from the Coyote Library: ; http://www.idlcoyote.com/programs/cgdbltostr.pro ; ; MODIFICATION HISTORY: ; ; Written by: David W. Fanning, 23 NOV 1999. ; Added DECIMAL and DIGITS keywords, 2 Jan 2000, DWF. ; Changed the calling sequence to that of a function rather than an object ; creation call. This is more familiar to users of compound widgets. 4 Jan 00. DWF. ; Added GetID and Resize methods. 7 Jan 00. DWF. ; Added the Positive keyword and functionality. 12 Jan 00. DWF ; Modified (slightly) the behavior on deleting characters. 12 Jan 00. DWF. ; If a number field is blank, the Get_Value method will now return an undefined variable. ; Be sure you check this value before you use it for something! 17 Jan 00. DWF. ; Fixed a small typo: "aveDecimal" to "haveDecimal". 10 March 2000. DWF. ; Added the ability to tab between FSC_INPUTFIELD widgets with the SetTabNext, ; MoveTab, and GetTextID methods. 31 July 2000. DWF. ; Added NAME field property, a scalar string name for the object 2 AUG 2000 BT ; Added ObjRef field to the FSC_FIELD event structure and added field selection ; for the TAB events added 31 July. 7 AUG 2000. DWF ; Added GetTextSize and GetLabelSize methods for obtaining the X screen ; size of the text and label widgets, respectively. 30 Jan 2001. DWF. ; Added FOCUS_EVENTS keyword and fixed a problem with the event structure. ; Also added better error handling. 5 January 2003. DWF. ; Fixed a small problem in which input values were cast to strings inadvertently. 9 January 2004. DWF. ; Fixed a small problem with error messages and using EVENT_FUNC. 14 January 2004. DWF. ; Fixed a problem when setting ROW keyword. 23 February 2004. DWF. ; IDL 6.2 introduced new TAB behavior, which broke the previous TAB behavior. New TAB behavior ; is now supported, but FOCUS_EVENTS *must* be set for the new TAB events to behave properly. ; 10 August 2005. DWF. ; Modified to covert double precision values to strings properly. 30 November 2005. DWF. ; Added POSITIVE keyword to SETPROPERTY and GETPROPERTY methods. 25 February 2006. DWF. ; Set the DYNAMIC_RESIZE keyword on the label widget. 25 February 2006. DWF. ; Added SENSITIVE keyword to SetProperty documentation. 10 November 2006. DWF. ; Fixed a small problem in which doubles were not being initialized correctly due ; to an inadvertant extra line of code. 3 July 2007. DWF. ; Fixed a small problem with input validation when the input is of BYTE type. 1 Oct 2008. DWF. ; Set the default fonts to be the current widget font, rather than the default widget font. 4 Oct 2008. DWF. ; Fixed a problem with validating a float or double value when it was written with ; exponential notation. 2 April 2010. DWF. ;- ;******************************************************************************************; ; Copyright (c) 2008, by Fanning Software Consulting, Inc. ; ; All rights reserved. ; ; ; ; Redistribution and use in source and binary forms, with or without ; ; modification, are permitted provided that the following conditions are met: ; ; ; ; * Redistributions of source code must retain the above copyright ; ; notice, this list of conditions and the following disclaimer. ; ; * Redistributions in binary form must reproduce the above copyright ; ; notice, this list of conditions and the following disclaimer in the ; ; documentation and/or other materials provided with the distribution. ; ; * Neither the name of Fanning Software Consulting, Inc. nor the names of its ; ; contributors may be used to endorse or promote products derived from this ; ; software without specific prior written permission. ; ; ; ; THIS SOFTWARE IS PROVIDED BY FANNING SOFTWARE CONSULTING, INC. ''AS IS'' AND ANY ; ; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ; ; OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT ; ; SHALL FANNING SOFTWARE CONSULTING, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, ; ; INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED ; ; TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; ; ; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ; ; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ; ; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ; ; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ; ;******************************************************************************************; FUNCTION FSC_InputField_WidgetFont, DEFAULT=default ; Build a small widget to determine the current ; and default widget fonts. base = Widget_Base(MAP=0) button = Widget_Button(base, Value='TEST') ; Checking before realization gives default font. defaultFont = Widget_Info(button, /FONTNAME) ; Checking after realization gives current font. Widget_Control, base, /REALIZE currentFont = Widget_Info(button, /FONTNAME) ; Clean up. Widget_Control, base, /DESTROY IF Keyword_Set(default) THEN $ RETURN, defaultFont ELSE $ RETURN, currentFont END ;----------------------------------------------------------------------------------------------------------------------------- PRO FSC_InputField::MoveTab IF NOT Widget_Info(self.tabnext, /Valid_ID) THEN RETURN Widget_Control, self.tabnext, /Input_Focus Widget_Control, self.tabnext, Get_Value=theText theText = theText[0] Widget_Control, self.tabnext, Set_Text_Select=[0,StrLen(theText)] END ;----------------------------------------------------------------------------------------------------------------------------- PRO FSC_InputField::SetTabNext, nextID self.tabnext = nextID END ;----------------------------------------------------------------------------------------------------------------------------- FUNCTION FSC_InputField::GetTextID ; This method returns the ID of the text widget of the compound widget. RETURN, self.textID END ;----------------------------------------------------------------------------------------------------------------------------- PRO FSC_InputField::Resize, newsize ; This method resizes the widget by making the text widget fit the new size. l = Widget_Info(self.labelID, /Geometry) Widget_Control, self.textID, Scr_XSize = (newsize - l.scr_xsize) END ;----------------------------------------------------------------------------------------------------------------------------- FUNCTION FSC_InputField::GetID ; This method returns the ID of the top-level base of the compound widget. RETURN, self.tlb END ;----------------------------------------------------------------------------------------------------------------------------- FUNCTION FSC_InputField::GetLabelSize ; This method returns the X screen size of the label widget. geom = Widget_Info(self.labelID, /Geometry) RETURN, geom.scr_xsize END ;----------------------------------------------------------------------------------------------------------------------------- FUNCTION FSC_InputField::GetTextSize ; This method returns the X screen size of the text widget. geom = Widget_Info(self.textID, /Geometry) RETURN, geom.scr_xsize END ;----------------------------------------------------------------------------------------------------------------------------- FUNCTION FSC_InputField::Geometry ; This method returns the geometry of the compound widget. RETURN, Widget_Info(self.tlb,/Geometry) END ;----------------------------------------------------------------------------------------------------------------------------- FUNCTION FSC_InputField::Get_Value ; This method returns the actual value of the compound widget. RETURN, *self.theValue END ;----------------------------------------------------------------------------------------------------------------------------- PRO FSC_InputField::Set_Value, value, IntegerValue=integervalue, $ FloatValue=floatvalue, LongValue=longvalue, DoubleValue=doublevalue, $ StringValue=stringvalue ; This method sets the value of the compound widget. ; Error Handling. Catch, theError IF theError NE 0 THEN BEGIN ok = cgErrorMsg(/Traceback) RETURN ENDIF IF Keyword_Set(stringvalue) THEN dataType = 'STRING' IF Keyword_Set(integervalue) THEN dataType = 'INT' IF Keyword_Set(longvalue) THEN dataType = 'LONG' IF Keyword_Set(floatvalue) THEN dataType = 'FLOAT' IF Keyword_Set(doublevalue) THEN dataType = 'DOUBLE' IF N_Elements(dataType) EQ 0 THEN dataType = Size(value, /TName) IF dataType EQ 'BYTE' THEN BEGIN value = 0 > FIX(value) < 255 dataType = 'INT' ENDIF self.dataType = datatype IF self.dataType EQ 'DOUBLE' THEN theText = cgDblToStr(value) ELSE theText = StrTrim(value, 2) theText = self->Validate(theText) ; Load the value in the widget. Widget_Control, self.textID, Set_Value=theText, Set_Text_Select=[StrLen(theText),0] self.theText = theText ; Set the actual value of the compound widget. *self.theValue = self->ReturnValue(theText) END ;----------------------------------------------------------------------------------------------------------------------------- FUNCTION FSC_InputField::Validate, value ; This function eliminates illegal characters from a string that represents ; a number. The return value is a properly formatted string that can be turned into ; an INT, LONG, FLOAT, or DOUBLE value. This is a "private" method. ; ; + 43B ; - 45B ; . 46B ; 0 - 9 48B -57B ; 'eEdD' [101B, 69B, 100B, 68B] ; Error Handling. Catch, theError IF theError NE 0 THEN BEGIN ok = cgErrorMsg(/Traceback) RETURN, "" ENDIF ; A null string should be returned at once. IF N_Elements(value) EQ 0 THEN value = "" value = value[0] IF value EQ "" THEN RETURN, String(value) ; No leading or trailing blank characters to evaluate. value = StrTrim(value, 2) ; A string value should be returned at once. Nothing to check. IF StrUpCase(self.datatype) EQ 'STRING' THEN RETURN, String(value) ; Check integers and longs. A "-" or "+" in the first character is allowed. Otherwise, ; only number between 0 and 9, or 43B to 57B. IF StrUpCase(self.datatype) EQ 'INT' OR StrUpCase(self.datatype) EQ 'LONG' THEN BEGIN returnValue = Ptr_New(/Allocate_Heap) asBytes = Byte(value) IF self.positive THEN BEGIN IF (asBytes[0] EQ 43B) OR $ (asBytes[0] GE 48B AND asBytes[0] LE 57B) THEN *returnValue = [asBytes[0]] ENDIF ELSE BEGIN IF (asBytes[0] EQ 45B) OR (asBytes[0] EQ 43B) OR $ (asBytes[0] GE 48B AND asBytes[0] LE 57B) THEN *returnValue = [asBytes[0]] ENDELSE length = StrLen(asBytes) IF length EQ 1 THEN BEGIN IF N_Elements(*returnValue) EQ 0 THEN *returnValue = [32B] ELSE $ *returnValue = [asBytes[0]] ENDIF ELSE BEGIN FOR j=1,length-1 DO BEGIN IF (asBytes[j] GE 48B AND asBytes[j] LE 57B) THEN BEGIN IF N_Elements(*returnValue) EQ 0 THEN *returnValue = [asBytes[j]] ELSE $ *returnValue = [*returnValue, asBytes[j]] ENDIF ENDFOR ENDELSE IF N_Elements(*returnValue) NE 0 THEN retValue = String(*returnValue) ELSE retValue = "" Ptr_Free, returnValue ; Check for digit restrictions. IF self.digits GT 0 THEN BEGIN retValue = StrTrim(retValue, 2) IF StrMid(retValue, 0, 1) EQ "-" THEN digits = self.digits + 1 ELSE digits = self.digits retValue = StrMid(retValue, 0, digits) ENDIF RETURN, retValue ENDIF ; Check floating and double values. (+,-) in first character or after 'eEdD'. ; Only numbers, signs, decimal points, and 'eEdD' allowed. IF StrUpCase(self.datatype) EQ 'FLOAT' OR StrUpCase(self.datatype) EQ 'DOUBLE' THEN BEGIN returnValue = Ptr_New(/Allocate_Heap) asBytes = Byte(value) IF self.positive THEN BEGIN IF (asBytes[0] EQ 43B) OR $ (asBytes[0] GE 48B AND asBytes[0] LE 57B) OR $ (asBytes[0] EQ 46B) THEN *returnValue = [asBytes[0]] IF (asBytes[0] EQ 46B) THEN haveDecimal = 1 ELSE haveDecimal = 0 ENDIF ELSE BEGIN IF (asBytes[0] EQ 45B) OR (asBytes[0] EQ 43B) OR $ (asBytes[0] GE 48B AND asBytes[0] LE 57B) OR $ (asBytes[0] EQ 46B) THEN *returnValue = [asBytes[0]] IF (asBytes[0] EQ 46B) THEN haveDecimal = 1 ELSE haveDecimal = 0 ENDELSE haveExponent = 0 length = StrLen(asBytes) prevByte = asBytes[0] exponents = Byte('eEdD') IF length EQ 1 THEN BEGIN IF N_Elements(*returnValue) EQ 0 THEN *returnValue = [32B] ELSE $ *returnValue = [asBytes[0]] ENDIF ELSE BEGIN FOR j=1,length-1 DO BEGIN IF (asBytes[j] GE 48B AND asBytes[j] LE 57B) THEN BEGIN IF N_Elements(*returnValue) EQ 0 THEN *returnValue = [asBytes[j]] ELSE $ *returnValue = [*returnValue, asBytes[j]] prevByte = asBytes[j] ENDIF ELSE BEGIN ; What kind of thing is it? IF (asBytes[j] EQ 46B) THEN BEGIN ; A decimal point. IF haveDecimal EQ 0 THEN BEGIN *returnValue = [*returnValue, asBytes[j]] haveDecimal = 1 prevByte = asBytes[j] ENDIF ENDIF IF (asBytes[j] EQ 45B) OR (asBytes[j] EQ 43B) THEN BEGIN ; A + or - sign. index = Where(exponents EQ prevByte, count) IF count EQ 1 AND haveExponent THEN BEGIN *returnValue = [*returnValue, asBytes[j]] haveDecimal = 1 prevByte = asBytes[j] ENDIF ENDIF index = Where(exponents EQ asBytes[j], count) IF count EQ 1 AND haveExponent EQ 0 THEN BEGIN ; An exponent *returnValue = [*returnValue, asBytes[j]] haveExponent = 1 prevByte = asBytes[j] ENDIF ENDELSE ENDFOR ENDELSE IF N_Elements(*returnValue) NE 0 THEN BEGIN retValue = String(*returnValue) retValue = StrTrim(retValue, 2) ; Check for decimal restrictions IF self.decimal GE 0 THEN BEGIN theDecimalPt = StrPos(retValue, '.') IF theDecimalPt NE -1 THEN retValue = StrMid(retValue, 0, theDecimalPt + self.decimal + 1) ENDIF ENDIF ELSE retValue = "" Ptr_Free, returnValue ; Is this a representable number? testValue = self->ReturnValue(retValue) IF String(testValue) NE 'NULLVALUE' THEN numCheck = Finite(testValue) ELSE numCheck = 1 IF numCheck THEN BEGIN RETURN, retValue ENDIF ELSE BEGIN Message, 'The requested number is not representable.' ENDELSE ENDIF END ;----------------------------------------------------------------------------------------------------------------------------- PRO FSC_InputField_Event__Define ; The FSC_InputField_Event Structure. Sent only if EVENT_PRO or EVENT_FUNC keywords ; have defined an event handler for the top-level base of the compound widget. event = { FSC_InputField_Event, $; The name of the event structure. ID: 0L, $ ; The ID of the compound widget's top-level base. TOP: 0L, $ ; The widget ID of the top-level base of the hierarchy. HANDLER: 0L, $ ; The event handler ID. Filled out by IDL. Value: Ptr_New(), $ ; A pointer to the widget value. Type:"", $ ; A string indicating the type of data in the VALUE field. ; Values are "INT", "LONG", "FLOAT", "DOUBLE", or "STRING". ObjRef:Obj_New()} ; The "self" object. END ;----------------------------------------------------------------------------------------------------------------------------- FUNCTION FSC_InputField::ReturnValue, inputValue ; This method takes a string and turns it into a number, ; depending upon the current data type of the compound widget. ; This is a "private" method. For numbers, if the input value ; is a null string, then an undefined variable is returned. ; Error Handling. ON_IOERROR, CatchIt CASE self.datatype OF 'INT': IF inputValue EQ "" OR inputValue EQ "-" OR inputValue EQ "+" THEN $ retValue = 'NULLVALUE' ELSE retValue = Fix(inputValue) 'LONG': IF inputValue EQ "" OR inputValue EQ "-" OR inputValue EQ "+" THEN $ retValue = 'NULLVALUE' ELSE retValue = Long(inputValue) 'FLOAT' : IF inputValue EQ "" OR inputValue EQ "-" OR inputValue EQ "+" THEN $ retValue = 'NULLVALUE' ELSE retValue = Float(inputValue) 'DOUBLE': IF inputValue EQ "" OR inputValue EQ "-" OR inputValue EQ "+" THEN $ retValue = 'NULLVALUE' ELSE retValue = Double(inputValue) 'STRING' : retValue = inputValue ENDCASE RETURN, retValue CatchIt: retValue = 'NULLVALUE' RETURN, retValue END ;----------------------------------------------------------------------------------------------------------------------------- FUNCTION FSC_InputField::TextEvents, event ; The event handler method for the text widget of the compound widget. ; Error Handling. Catch, theError IF theError NE 0 THEN BEGIN Catch, /Cancel ok = cgErrorMsg(/Traceback) RETURN, 0 ENDIF ; Get the previous text, the current cursor location in the text widget, ; and indicate this is not a Carriage Return event. previousText = self.theText textLocation = Widget_Info(event.id, /Text_Select) cr_event = 0 ; Is this a keyboard focus event? Then process it differently. IF Tag_Names(event, /Structure_Name) EQ 'WIDGET_KBRD_FOCUS' THEN BEGIN ; New behavior for TAB MODE functionality in IDL 6.2. IF Float(!Version.Release) GT 6.1 THEN BEGIN IF event.enter EQ 1 THEN BEGIN Widget_Control, self.textID, Get_Value=theText theText = theText[0] Widget_Control, self.textID, Set_Text_Select=[0,StrLen(theText)] ; Send the keyboard focus events if there is an event handler to accept them. IF self.event_func NE "" THEN BEGIN thisEvent = {FSC_InputField_Event, self.tlb, event.top, 0L, self.theValue, self.dataType, self} RETURN, thisEvent ENDIF IF self.event_pro NE "" THEN BEGIN thisEvent = {FSC_InputField_Event, self.tlb, event.top, 0L, self.theValue, self.dataType, self} RETURN, thisEvent ENDIF ; Out of here. RETURN, 0 ENDIF ELSE BEGIN Widget_Control, self.textID, Set_Text_Select=[0,0] ; Send the keyboard focus events if there is an event handler to accept them. IF self.event_func NE "" THEN BEGIN thisEvent = {FSC_InputField_Event, self.tlb, event.top, 0L, self.theValue, self.dataType, self} RETURN, thisEvent ENDIF IF self.event_pro NE "" THEN BEGIN thisEvent = {FSC_InputField_Event, self.tlb, event.top, 0L, self.theValue, self.dataType, self} RETURN, thisEvent ENDIF ; Out of here. RETURN, 0 ENDELSE ENDIF ELSE BEGIN IF event.enter EQ 1 THEN RETURN,0 ; Don't bother. Only interested in losing keyboard focus. ; Get the current contents of text widget. Validate it. Widget_Control, self.textID, Get_Value=newText newText = newText[0] validText = self->Validate(newText) ; Load the valid text. self.theText = validText testValue = self->ReturnValue(validText) IF String(testValue) EQ "NULLVALUE" THEN BEGIN Ptr_Free, self.theValue self.theValue = Ptr_New(/Allocate_Heap) ENDIF ELSE *self.theValue = testValue ; Send the keyboard focus events if there is an event handler to accept them. IF self.event_func NE "" THEN BEGIN thisEvent = {FSC_InputField_Event, self.tlb, event.top, 0L, self.theValue, self.dataType, self} RETURN, thisEvent ENDIF IF self.event_pro NE "" THEN BEGIN thisEvent = {FSC_InputField_Event, self.tlb, event.top, 0L, self.theValue, self.dataType, self} RETURN, thisEvent ENDIF RETURN, 0 ENDELSE ENDIF ; What kind of event is this? possibleTypes = ['INSERT SINGLE CHARACTER', 'INSERT MULTIPLE CHARACTERS', 'DELETE TEXT', 'SELECT TEXT'] thisType = possibleTypes[event.type] ; Branch on event type. CASE thisType OF 'INSERT SINGLE CHARACTER': BEGIN ; If the character is a TAB see if there is something to do. IF event.ch EQ 9B THEN BEGIN self->MoveTab RETURN, 0 ENDIF ; Get the current contents of text widget. Validate it. Widget_Control, self.textID, Get_Value=newText newText = newText[0] validText = self->Validate(newText) ; If it is valid, leave it alone. If not, go back to previous text. IF validText NE newText THEN BEGIN Widget_Control, self.textID, Set_Value=previousText, Set_Text_Select=[textLocation[0]-1,0] ENDIF ELSE BEGIN self.theText = validText testValue = self->ReturnValue(validText) IF String(testValue) EQ "NULLVALUE" THEN BEGIN Ptr_Free, self.theValue self.theValue = Ptr_New(/Allocate_Heap) ENDIF ELSE *self.theValue = testValue ENDELSE ; Is this a Carriage Return event? IF event.ch EQ 10B then cr_event = 1 ENDCASE 'INSERT MULTIPLE CHARACTERS': BEGIN ; Same as above, but for all the characters you are inserting. Widget_Control, self.textID, Get_Value=newText newText = newText[0] validText = self->Validate(newText) IF validText NE newText THEN BEGIN Widget_Control, self.textID, Set_Value=previousText, Set_Text_Select=[textLocation[0]-1,0] ENDIF ELSE BEGIN self.theText = validText testValue = self->ReturnValue(validText) IF String(testValue) EQ "NULLVALUE" THEN BEGIN Ptr_Free, self.theValue self.theValue = Ptr_New(/Allocate_Heap) ENDIF ELSE *self.theValue = testValue ENDELSE ENDCASE 'DELETE TEXT': BEGIN ; Get the current contents of text widget. Validate it. Widget_Control, self.textID, Get_Value=newText newText = newText[0] validText = self->Validate(newText) ; Load the valid text. Widget_Control, self.textID, Set_Value=validText, Set_Text_Select=[textLocation[0],0] self.theText = validText testValue = self->ReturnValue(validText) IF String(testValue) EQ "NULLVALUE" THEN BEGIN Ptr_Free, self.theValue self.theValue = Ptr_New(/Allocate_Heap) ENDIF ELSE *self.theValue = testValue ENDCASE 'SELECT TEXT': ; Nothing to do. ENDCASE ; Do you report all events, or only Carriage Return events? CASE 1 OF self.cr_only: BEGIN IF self.event_func NE "" THEN BEGIN thisEvent = {FSC_InputField_Event, self.tlb, event.top, 0L, self.theValue, self.dataType, self} IF cr_event THEN RETURN, thisEvent ENDIF IF self.event_pro NE "" THEN BEGIN thisEvent = {FSC_InputField_Event, self.tlb, event.top, 0L, self.theValue, self.dataType, self} IF cr_event THEN RETURN, thisEvent ENDIF END self.focus: ELSE: BEGIN IF self.event_func NE "" THEN BEGIN thisEvent = {FSC_InputField_Event, self.tlb, event.top, 0L, self.theValue, self.dataType, self} RETURN, thisEvent ENDIF IF self.event_pro NE "" THEN BEGIN thisEvent = {FSC_InputField_Event, self.tlb, event.top, 0L, self.theValue, self.dataType, self} RETURN, thisEvent ENDIF END ENDCASE RETURN, 0 END ;----------------------------------------------------------------------------------------------------------------------------- FUNCTION FSC_InputField_Event_Handler, event ; The main event handler for the compound widget. It reacts ; to "messages" in the UValue of the text widget. ; The message indicates which object method to call. A message ; consists of an object method and the self object reference. Widget_Control, event.ID, Get_UValue=theMessage event = Call_Method(theMessage.method, theMessage.object, event) RETURN, event END ;----------------------------------------------------------------------------------------------------------------------------- PRO FSC_InputField::GetProperty, $ ; ; This method allows you to obtain various properties of the compound widget via output keywords. ; CR_Only=cr_only, $ ; Get the value of the self.cr_only flag.. DataType=datatype, $ ; The datatype of the compound widget. Decimal=decimal, $ ; Get the number of digits to the right of the decimal ; point in FLOATVALUE and DOUBLEVALUE numbers. Digits=digits, $ ; The number of digits permitted in INTERGERVALUE and LONGVALUE numbers. Event_Func=event_func, $ ; Get the name of an Event Function. Event_Pro=event_pro, $ ; Get the name of an Event Procedure. Focus_Events=focus_event, $ ; Get the current state of the self.focus flag. Name=Name, $ ; Get the name of the object. Positive=positive, $ ; Get the positive state of the object. UValue=uvalue, $ ; Get the user value of this object. Value=value ; Get the "value" of the compound widget. ; Error Handling. Catch, theError IF theError NE 0 THEN BEGIN ok = cgErrorMsg(/Traceback) RETURN ENDIF ; Get the properties. cr_only = self.cr_only datatype = self.datatype decimal = self.decimal digits = self.digits event_func = self.event_func event_pro = self.event_pro positive = self.positive uvalue = *self.uvalue value = *self.thevalue name = self.name focus_event = self.focus END ;-------------------------------------------------------------------------------------------------------------- PRO FSC_InputField::SetProperty, $ ; ; This method allows you to set various properties of the compound widget. ; CR_Only=cr_only, $ ; Set this keyword if you only want Carriage Return events. Decimal=decimal, $ ; Set this keyword to the number of digits to the right of the decimal ; point in FLOATVALUE and DOUBLEVALUE numbers. Digits=digits, $ ; Set this keyword to the number of digits permitted in INTERGERVALUE and LONGVALUE numbers. DoubleValue=doublevalue, $ ; Set this keyword if you want DOUBLE values returned. Event_Func=event_func, $ ; Set this keyword to the name of an Event Function. Event_Pro=event_pro, $ ; Set this keyword to the name of an Event Procedure. FloatValue=floatvalue, $ ; Set this keyword for FLOAT values. Focus_Events=focus_events, $ ; Set this keyword to the current state of the self.focus flag. IntegerValue=integervalue, $ ; Set this keyword for INTEGER values. LabelSize=labelsize, $ ; The X screen size of the Label Widget. LongValue=longvalue, $ ; Set this keyword for LONG values. Name=name, $ ; A scalar string name for the object. Positive=positive, $ ; The positive property. Scr_XSize=scr_xsize, $ ; The X screen size of the text widget. Scr_YSize=scr_ysize, $ ; The Y screen size of the text widget. Sensitive=sensitive, $ ; Set to 1 to make the widget sensitive, and to 0 to make it insensitive. StringValue=stringvalue, $ ; Set this keyword for STRING values. (The default.) Title=title, $ ; The text to go on the Label Widget. UValue=uvalue, $ ; A user value for any purpose. Value=value, $ ; The "value" of the compound widget. XSize=xsize ; The X size of the Text Widget. ; Error Handling. Catch, theError IF theError NE 0 THEN BEGIN ok = cgErrorMsg(/Traceback) RETURN ENDIF ; Set the properties, if needed. IF N_Elements(cr_only) NE 0 THEN self.cr_only = Keyword_Set(cr_only) IF Keyword_Set(decimal)THEN self.decimal = decimal IF Keyword_Set(digits)THEN self.digits = digits IF Keyword_Set(doublevalue)THEN self.datatype = 'DOUBLE' IF N_Elements(event_func) NE 0 THEN self.event_func = event_func IF N_Elements(event_pro) NE 0 THEN self.event_pro = event_pro IF Keyword_Set(floatvalue)THEN self.datatype = 'FLOAT' IF N_Elements(focus_events) NE 0 THEN self.focus = Keyword_Set(focus_events) IF Keyword_Set(integervalue)THEN self.datatype = 'INT' IF N_Elements(labelsize) NE 0 THEN BEGIN Widget_Control, self.labelID, XSize=labelsize ENDIF IF Keyword_Set(longvalue)THEN self.datatype = 'LONG' IF N_Elements(scr_xsize) NE 0 THEN BEGIN self.scr_xsize = scr_xsize Widget_Control, self.textID, Scr_XSize=scr_xsize ENDIF IF N_Elements(positive) NE 0 THEN self.positive = positive IF N_Elements(scr_ysize) NE 0 THEN BEGIN self.scr_ysize = scr_ysize Widget_Control, self.textID, Scr_YSize=scr_ysize ENDIF IF N_Elements(sensitive) NE 0 THEN Widget_Control, self.textID, Sensitive=sensitive IF Keyword_Set(stringvalue)THEN self.datatype = 'STRING' IF N_Elements(title) NE 0 THEN Widget_Control, self.labelID, Set_Value=title IF N_Elements(uvalue) NE 0 THEN *self.uvalue = uvalue If N_elements(Name) NE 0 Then Self.Name = String(Name[0]) IF N_Elements(xsize) NE 0 THEN BEGIN self.xsize = xsize Widget_Control, self.textID, XSize=xsize ENDIF IF N_Elements(value) NE 0 THEN BEGIN CASE Size(value, /TNAME) OF 'FLOAT': self.theText = StrTrim(String(value, FORMAT='(F0)'),2) 'DOUBLE': self.theText = StrTrim(String(value, FORMAT='(D0)'),2) ELSE: self.theText = StrTrim(value, 2) ENDCASE *self.theValue = self->ReturnValue(self.theText) Widget_Control, self.textID, Set_Value=self.theText ENDIF ELSE BEGIN Widget_Control, self.textID, Get_Value=theText theText = theText[0] *self.theValue = self->ReturnValue(theText) ENDELSE END ;-------------------------------------------------------------------------------------------------------------- FUNCTION FSC_InputField::INIT, $ ; The compound widget FSC_InputField INIT method.. parent, $ ; The parent widget. Required for all compound widgets. Column=column, $ ; Set this keyword to have Label above Text Widget. CR_Only=cr_only, $ ; Set this keyword if you only want Carriage Return events. Decimal=decimal, $ ; Set this keyword to the number of digits to the right of the decimal ; point in FLOATVALUE and DOUBLEVALUE numbers. Digits=digits, $ ; Set this keyword to the number of digits permitted in INTERGERVALUE and LONGVALUE numbers. DoubleValue=doublevalue, $ ; Set this keyword if you want DOUBLE values returned. Event_Func=event_func, $ ; Set this keyword to the name of an Event Function. Event_Pro=event_pro, $ ; Set this keyword to the name of an Event Procedure. _Extra=extra, $ ; Passes along extra keywords to the text widget. FieldFont=fieldfont, $ ; The font name for the text in the Text Widget. FloatValue=floatvalue, $ ; Set this keyword for FLOAT values. Focus_Events=focus_events, $ ; Set this keyword to enable event reporting when the widget loses keyboard focus. Frame=frame, $ ; Set this keyword to put a frame around the compound widget. IntegerValue=integervalue, $ ; Set this keyword for INTEGER values. LabelAlign=labelalign, $ ; Set this keyword to align label text. LabelFont=labelfont, $ ; The font name for the text in the Label Widget. LabelSize=labelsize, $ ; The X screen size of the Label Widget. LongValue=longvalue, $ ; Set this keyword for LONG values. Name=name, $ ; A scalar string name for the object. Positive=positive, $ ; Set this keyword to indicate only positive numbers allowed in the field. Row=row, $ ; Set this keyword to have the Label beside the Text Widget. (The default.) Scr_XSize=scr_xsize, $ ; The X screen size of the text widget. Scr_YSize=scr_ysize, $ ; The Y screen size of the text widget. StringValue=stringvalue, $ ; Set this keyword for STRING values. (The default.) Title=title, $ ; The text to go on the Label Widget. UValue=uvalue, $ ; A user value for any purpose. Value=value, $ ; The "value" of the compound widget. XSize=xsize ; The X size of the Text Widget. ; Error Handling. Catch, theError IF theError NE 0 THEN BEGIN ok = cgErrorMsg(/Traceback) RETURN, 0 ENDIF ; A parent is required. IF N_Elements(parent) EQ 0 THEN BEGIN Message, 'A PARENT argument is required. Returning...', /Informational RETURN, -1L ENDIF ; Check keyword values. IF N_Elements(column) EQ 0 THEN column = 0 IF N_Elements(digits) EQ 0 THEN digits = 0 ELSE digits = Fix(digits) IF N_Elements(decimal) EQ 0 THEN decimal = -1 ELSE decimal = Fix(decimal) IF N_Elements(event_func) EQ 0 THEN event_func = "" IF N_Elements(event_pro) EQ 0 THEN event_pro = "" IF N_Elements(fieldfont) EQ 0 THEN fieldfont = FSC_InputField_WidgetFont() IF N_Elements(frame) EQ 0 THEN frame = 0 IF N_Elements(labelalign) EQ 0 THEN labelalign = 0 IF N_Elements(labelfont) EQ 0 THEN labelfont = FSC_InputField_WidgetFont() IF N_Elements(labelsize) EQ 0 THEN labelsize = 0 ;IF N_Elements(scr_xsize) EQ 0 THEN scr_xsize = 0 ;IF N_Elements(scr_ysize) EQ 0 THEN scr_ysize = 0 IF N_Elements(title) EQ 0 THEN title = "Input Value: " IF N_Elements(uvalue) EQ 0 THEN uvalue = "" IF N_Elements(value) EQ 0 THEN value = "" IF N_Elements(xsize) EQ 0 THEN xsize = 0 IF N_Elements(row) EQ 0 AND column EQ 0 THEN row = 1 ; What data type are we looking for? dataType = 'STRING' IF Keyword_Set(stringvalue) THEN dataType = 'STRING' IF Keyword_Set(integervalue) THEN dataType = 'INT' IF Keyword_Set(longvalue) THEN dataType = 'LONG' IF Keyword_Set(floatvalue) THEN dataType = 'FLOAT' IF Keyword_Set(doublevalue) THEN dataType = 'DOUBLE' ; Populate the object. self.cr_only = Keyword_Set(cr_only) self.datatype = datatype self.decimal = decimal self.digits = digits self.focus = Keyword_Set(focus_events) self.parent = parent self.event_pro = event_pro self.event_func = event_func self.positive = Keyword_Set(positive) self.uvalue = Ptr_New(uvalue) If N_Elements(name) NE 0 Then self.name = String(name[0]) ; Validate the input value. IF dataType EQ 'DOUBLE' THEN theText = cgDblToStr(value) ELSE theText = StrTrim(value, 2) theText = self->Validate(theText) self.theText = theText ; Create the widgets. self.tlb = Widget_Base( parent, $ ; The top-level base of the compound widget. Frame=frame, $ Row=row, $ Column=Keyword_Set(column), $ Base_Align_Center=1, $ UValue=uvalue, $ Event_Pro=event_pro, $ Event_Func=event_func ) ; New TAB MODE functionality in IDL 6.2. IF Float(!Version.Release) GT 6.1 THEN Widget_Control, self.tlb, TAB_MODE=1 self.labelID = Widget_Label( self.tlb, Value=title, Font=labelfont, $ ; The Label Widget. Scr_XSize=labelsize, Scr_YSize=scr_ysize, /Dynamic_Resize, $ Align_Center=(labelalign eq 0)?1:0, $ Align_Left=(labelalign EQ 1)?1:0, $ Align_Right=(labelalign EQ 2)?1:0) self.textID = Widget_Text( self.tlb, $ ; The Text Widget. Value=theText, $ XSize=xsize, $ YSize=1, $ Font=fieldfont, $ All_Events=1, $ _Extra=extra, $ Scr_YSize=scr_ysize, $ Kbrd_Focus_Events=self.focus, $ Event_Func='FSC_InputField_Event_Handler', $ UValue={Method:"TextEvents", Object:self}, $ Kill_Notify='FSC_InputField_Kill_Notify', $ Editable=1 ) ; If screen sizes are set, adjust the text widget size. IF N_Elements(scr_xsize) NE 0 THEN BEGIN tlbg = Widget_Info(self.tlb, /Geometry) textg = Widget_Info(self.textID, /Geometry) labelg = Widget_info(self.labelID, /Geometry) plussize = textg.scr_xsize + labelg.scr_xsize stuff = (tlbg.xpad*2) + tlbg.space IF plussize GT scr_xsize THEN $ Widget_Control, self.textID, Scr_XSize=textg.scr_xsize-(plussize-scr_xsize)-stuff ELSE $ Widget_Control, self.textID, Scr_XSize=textg.scr_xsize+(scr_xsize - plussize)-stuff ENDIF ; Set the actual return value of the compound widget. self.theValue = Ptr_New(self->ReturnValue(theText)) ; If CR_ONLY or FOCUS_EVENTS are turned on and EVENT_PRO and EVENT_FUNC keywords are ; unspecified, issue a warning message to the command log. IF self.cr_only AND (self.event_pro EQ "" AND self.event_func EQ "") THEN $ Message, /Information, 'WARNING: There is no specified event handler for carriage return events for this widget. Events will be swallowed.' IF self.focus AND (self.event_pro EQ "" AND self.event_func EQ "") THEN $ Message, /Information, 'WARNING: There is no specified event handler for keyboard focus events for this widget. Events will be swallowed.' RETURN, 1 END ;-------------------------------------------------------------------------------------------------------------- PRO FSC_InputField_Kill_Notify, textID ; This widget call-back procedure makes sure the self object is ; destroyed when the widget is destroyed. Widget_Control, textID, Get_UValue=message Obj_Destroy, message.object END ;-------------------------------------------------------------------------------------------------------------- PRO FSC_InputField::CLEANUP ; This method makes sure there are not pointers left on the heap. Ptr_Free, self.theValue Ptr_Free, self.uvalue END ;-------------------------------------------------------------------------------------------------------------- PRO FSC_InputField__Define objectClass = { FSC_INPUTFIELD, $ ; The object class name. parent: 0L, $ ; The parent widget ID. tlb: 0L, $ ; The top-level base of the compound widget. labelID: 0L, $ ; The label widget ID. textID: 0L, $ ; The text widget ID. theText: "", $ ; The actual text in the text widget. theValue: Ptr_New(), $ ; The actual "value" of the text in the text widget. :-) event_func: "", $ ; The name of the specified event handler function. event_pro: "", $ ; The name of the specified event handler procedrue cr_only: 0L, $ ; A flag meaning send only carriage return events. focus: 0L, $ ; A flag to indicate focus events should be returned. tabnext: 0L, $ ; The identifier of a widget to receive the cursor focus if a TAB character is detected. uvalue: Ptr_New(), $ ; The user value of the compound widget. decimal: 0, $ ; The number of decimals points in FLOAT and DOUBLE numbers. digits: 0, $ ; The number of digits in INT and LONG numbers. positive: 0, $ ; A flag meaning only positive numbers allowed. datatype: "" , $ ; The type of data to be returned from the text widget. Name: "" $ ; A scalar string name for the object } END ;-------------------------------------------------------------------------------------------------------------- FUNCTION FSC_INPUTFIELD, $ ; The compound widget FSC_InputField. parent, $ ; The parent widget. Required for all compound widgets. Column=column, $ ; Set this keyword to have Label above Text Widget. CR_Only=cr_only, $ ; Set this keyword if you only want Carriage Return events. Decimal=decimal, $ ; Set this keyword to the number of digits to the right of the decimal ; point in FLOATVALUE and DOUBLEVALUE numbers. Digits=digits, $ ; Set this keyword to the number of digits permitted in INTERGERVALUE and LONGVALUE numbers. DoubleValue=doublevalue, $ ; Set this keyword if you want DOUBLE values returned. Event_Func=event_func, $ ; Set this keyword to the name of an Event Function. Event_Pro=event_pro, $ ; Set this keyword to the name of an Event Procedure. _Extra=extra, $ ; Passes along extra keywords to the text widget. FieldFont=fieldfont, $ ; The font name for the text in the Text Widget. FloatValue=floatvalue, $ ; Set this keyword for FLOAT values. Focus_Events=focus_events, $ ; Set this keyword to enable event reporting when the widget loses keyboard focus. Frame=frame, $ ; Set this keyword to put a frame around the compound widget. IntegerValue=integervalue, $ ; Set this keyword for INTEGER values. LabelAlign=labelalign, $ ; Set this keyword to align label text. LabelFont=labelfont, $ ; The font name for the text in the Label Widget. LabelSize=labelsize, $ ; The X screen size of the Label Widget. LongValue=longvalue, $ ; Set this keyword for LONG values. Positive=positive, $ ; Set this keyword to indicate only positive numbers allowed in the field. Name=name, $ ; The name of the object. Row=row, $ ; Set this keyword to have the Label beside the Text Widget. (The default.) Scr_XSize=scr_xsize, $ ; The X screen size of the text widget. Scr_YSize=scr_ysize, $ ; The Y screen size of the text widget. StringValue=stringvalue, $ ; Set this keyword for STRING values. (The default.) Title=title, $ ; The text to go on the Label Widget. UValue=uvalue, $ ; A user value for any purpose. Value=value, $ ; The "value" of the compound widget. XSize=xsize ; The X size of the Text Widget. RETURN, Obj_New("FSC_INPUTFIELD", $ parent, $ ; The parent widget. Required for all compound widgets. Column=column, $ ; Set this keyword to have Label above Text Widget. CR_Only=cr_only, $ ; Set this keyword if you only want Carriage Return events. Decimal=decimal, $ ; Set this keyword to the number of digits to the right of the decimal ; point in FLOATVALUE and DOUBLEVALUE numbers. Digits=digits, $ ; Set this keyword to the number of digits permitted in INTERGERVALUE and LONGVALUE numbers. DoubleValue=doublevalue, $ ; Set this keyword if you want DOUBLE values returned. Event_Func=event_func, $ ; Set this keyword to the name of an Event Function. Event_Pro=event_pro, $ ; Set this keyword to the name of an Event Procedure. _Extra=extra, $ ; Passes along extra keywords to the text widget. FieldFont=fieldfont, $ ; The font name for the text in the Text Widget. FloatValue=floatvalue, $ ; Set this keyword for FLOAT values. Focus_Events=focus_events, $ ; Set this keyword to enable event reporting when the widget loses keyboard focus. Frame=frame, $ ; Set this keyword to put a frame around the compound widget. IntegerValue=integervalue, $ ; Set this keyword for INTEGER values. LabelAlign=labelalign, $ ; Set this keyword to align label text. LabelFont=labelfont, $ ; The font name for the text in the Label Widget. LabelSize=labelsize, $ ; The X screen size of the Label Widget. LongValue=longvalue, $ ; Set this keyword for LONG values. Name=name, $ ; The name of the object. Positive=positive, $ ; Set this keyword to indicate only positive numbers allowed in the field. Row=row, $ ; Set this keyword to have the Label beside the Text Widget. (The default.) Scr_XSize=scr_xsize, $ ; The X screen size of the text widget. Scr_YSize=scr_ysize, $ ; The Y screen size of the text widget. StringValue=stringvalue, $ ; Set this keyword for STRING values. (The default.) Title=title, $ ; The text to go on the Label Widget. UValue=uvalue, $ ; A user value for any purpose. Value=value, $ ; The "value" of the compound widget. XSize=xsize) ; The X size of the Text Widget. END PRO Example_Event, event ; An example event handler for FSC_Input_Field. Widget_Control, event.top, Get_UValue=info Widget_Control, event.id, Get_UValue=thisEvent ; Not interested in losing keyboard focus events. theName = Tag_Names(event, /Structure_Name) IF theName EQ 'WIDGET_KBRD_EVENT' THEN BEGIN IF event.type EQ 0 THEN RETURN ENDIF ; What kind of event is this? CASE thisEvent OF 'Field 1 Event': BEGIN Print, '' IF N_Elements(*event.value) EQ 0 THEN Print, 'Field 1 Value is Undefined' ELSE $ Print, 'Field 1 Value: ', *event.value END 'Field 2 Event': BEGIN Print, '' IF N_Elements(*event.value) EQ 0 THEN Print, 'Field 2 Value is Undefined' ELSE $ Print, 'Field 2 Value: ', *event.value END 'Field 3 Event': BEGIN Print, '' IF N_Elements(*event.value) EQ 0 THEN Print, 'Field 3 Value is Undefined' ELSE $ Print, 'Field 3 Value: ', *event.value END 'Print It': BEGIN theValue =info.field3->Get_Value() Print, '' Print, 'Field 3 Value: ', theValue END 'Set It': BEGIN info.field3->Set_Value, 'Coyote Rules!' END 'Quit': Widget_Control, event.top, /Destroy 'ChangeToFloat': BEGIN info.field1->SetProperty, Title='Float:', Value=RandomU(seed, 1)*100, /FloatValue END 'ChangeToString': BEGIN info.field1->SetProperty, Title='String:', Value='Coyote Jules', /StringValue END 'PrintFloat': BEGIN IF N_Elements(info.field2->Get_Value()) EQ 0 THEN Print, 'Field 2 Value is Undefined' ELSE $ Print, 'Field 2 Value: ', info.field2->Get_Value() END 'LabelSize': BEGIN Widget_Control, event.top, Update=0 info.field1->SetProperty, LabelSize=75 info.field2->SetProperty, LabelSize=75 info.field3->SetProperty, LabelSize=75 Widget_Control, event.top, Update=1 END ENDCASE END ;---------------------------------------------------------------------------- PRO Example ; An example program to exercise some of the features of FSC_Input_FIELD. tlb = Widget_Base(Column=1) button = Widget_Button(tlb, Value='Change First Field to Float', $ UValue='ChangeToFloat') button = Widget_Button(tlb, Value='Change First Field to String', $ UValue='ChangeToString') field1 = FSC_INPUTFIELD(tlb, Title='Integer:', LabelSize=50, Digits=2, $ Value=5, /IntegerValue, UValue='Field 1 Event', Event_Pro='Example_Event', /Focus_Events) field2 = FSC_INPUTFIELD(tlb, Title='Float:', LabelSize=50, Value=45.6, /CR_Only, $ /FloatValue, UValue='Field 2 Event', Event_Pro='Example_Event', Decimal=2, /Positive, /Focus_Events) field3 = FSC_INPUTFIELD(tlb, Title='String:', LabelSize=50, Value='Coyote Rules!', $ UValue='Field 3 Event', /Focus_Events, Event_Pro='Example_Event') ; Set up TABing between fields. field1->SetTabNext, field2->GetTextID() field2->SetTabNext, field3->GetTextID() field3->SetTabNext, field1->GetTextID() button = Widget_Button(tlb, Value='Print Value of String', UValue="Print It") button = Widget_Button(tlb, Value='Set Value of String', UValue='Set It') button = Widget_Button(tlb, Value='Change Size of Labels', UValue='LabelSize') button = Widget_Button(tlb, Value='Print Floating Value', UValue='PrintFloat') button = Widget_Button(tlb, Value='Quit', UValue='Quit') Widget_Control, tlb, /Realize, Set_UValue={field1:field1, field2:field2, field3:field3} XManager, 'example', tlb, /No_Block END