Code archives/User Input/Auto Form
This code has been declared by its author to be Public Domain code.
Download source code
| |||||
Input data from user to an object based on field names. A form is automatically generated using reflection and MaxGUI. Supports text fields, requesters, check boxes and combo boxes. Edit: Refactored the magic numbers and strings out. Edit2: Added file&dir requesters Example: SuperStrict Framework MaxGUI.Drivers Import "autoform.bmx" Type TCustomer Field Name:String Field Age:Int ' Creates a combo box Field _Type:String = "Unknown" { choose = "Regular,First_Timer,Unknown" } ' Creates a checkbox Field Send_spam:Int = True { bool } ' Creates a file requester Field Data_file:String { loadfile="Data_files_(*.dat):dat;All_files_(*.*):*" } End Type Local c:TCustomer = New TCustomer AutoForm "Please enter details", c, FORM_TRIM_|FORM_RESIZABLE Print c._type+": " + c.Name +" ("+c.age+") ["+c.Send_spam+"]" Print c.Data_file AutoForm "Modify details", c, FORM_RESET|FORM_TRIM_ Print c._type+": " + c.Name +" ("+c.age+") ["+c.Send_spam+"]" Print c.Data_file The code: | |||||
SuperStrict Import BRL.EventQueue Import BRL.Reflection Import MaxGUI.MaxGUI Private ' Sizes and spacing for general gadgets Const GADGET_X:Int = 170 Const GADGET_Y:Int = 25 Const SPACE_X:Int = 15 Const SPACE_Y:Int = 10 ' Button (max) width Const BUTTON_X:Int = 80 ' Label height Const LABEL_Y:Int = 20 ' Strings ' Meta strings to match Const META_DIRECTORY:String = "directory" Const META_LOAD:String = "loadfile" Const META_SAVE:String = "savefile" Const META_CHECKBOX:String = "bool" Const META_COMBOBOX:String = "choose" Const META_SEPARATOR:String = "," ' Labels Const LABEL_AFTER:String = ":" Const LABEL_BROWSE:String = "Browse..." Const LABEL_OK:String = "OK" Const LABEL_RESET:String = "Reset" ' Special characters Const UNDERSCORE:String = "_" Const SPACE:String = " " Public Const FORM_TRIM_:Int = 1 'Replace underscores with spaces and trim (Default) Const FORM_RESET:Int = 2 'Show a Reset button Const FORM_SKIP_:Int = 4 'Skip fields beginning with underscores Const FORM_RESIZABLE:Int = 8 'Window allows resizing ' Automatically generate a MaxGUI form based on an object ' Returns: True on success (OK), False on quit (WINDOW_CLOSE) Function AutoForm:Int(title:String, o:Object, opts:Int = FORM_TRIM_ ) Local i% = 0 ' Object is required If Not o Return False ' Find Type ID Local tid:TTypeId = TTypeId.ForObject(o) ' Find Fields and calculate window size Local flist:TList = tid.EnumFields() Local fields:TField[flist.Count()] Local sizex:Int = GADGET_X + 2*SPACE_X Local sizey:Int = GADGET_Y + 2*SPACE_Y For Local f:TField = EachIn flist ' Skip? If opts&FORM_SKIP_ And f.Name().StartsWith(UNDERSCORE) Then Continue fields[i] = f ' Calculate size If fields[i].MetaData(META_CHECKBOX) sizey :+ GADGET_Y + SPACE_Y Else If fields[i].MetaData(META_DIRECTORY) .. Or fields[i].MetaData(META_SAVE).. Or fields[i].MetaData(META_LOAD) sizex = GADGET_X + 3*SPACE_X + BUTTON_X sizey :+ LABEL_Y + GADGET_Y + SPACE_Y Else sizey :+ LABEL_Y + GADGET_Y + SPACE_Y End If i :+ 1 Next If FORM_SKIP_ fields = fields[..i] 'Removes empty elements ' Create window Local flags:Int = WINDOW_CLIENTCOORDS | WINDOW_TITLEBAR | WINDOW_CENTER If opts & FORM_RESIZABLE flags = flags | WINDOW_RESIZABLE Local win:TGadget = CreateWindow( title, 0,0, sizex,sizey, Null, flags ) ' Create gadgets for fields Local flabels:TGadget[fields.length] 'Labels Local ftexts:TGadget[fields.length] 'Text fields Local fcombos:TGadget[fields.length] 'Combo boxes Local fchecks:TGadget[fields.length] 'Check boxes Local fbuttons:TGadget[fields.length] 'Buttons (browse) Local y:Int = 10 For i = 0 Until fields.length ' Get Field name and trim Local n:String = fields[i].Name() If opts & FORM_TRIM_ Then n = n.Replace(UNDERSCORE, SPACE).Trim() If fields[i].MetaData(META_CHECKBOX) ' Checkbox fchecks[i] = CreateButton(n, SPACE_X,y, GADGET_X,GADGET_Y, win, BUTTON_CHECKBOX) y :+ GADGET_Y + SPACE_Y SetButtonState fchecks[i], fields[i].GetInt(o) Continue End If ' Create label flabels[i] = CreateLabel(n+LABEL_AFTER, SPACE_X,y, GADGET_X,LABEL_Y, win) y :+ LABEL_Y Local c:String = fields[i].MetaData(META_COMBOBOX) If c 'Combo box If opts & FORM_TRIM_ Then c = c.Replace(UNDERSCORE, SPACE).Trim() fcombos[i] = CreateComboBox(SPACE_X,y, GADGET_X,GADGET_Y, win) Local value:String = fields[i].GetString(o) Local items:String[] = c.Split(META_SEPARATOR) For Local j:Int = 0 Until items.length AddGadgetItem fcombos[i], items[j] If items[j]=value Then SelectGadgetItem fcombos[i], j Next Else 'Text field ftexts[i] = CreateTextField(SPACE_X,y, GADGET_X,GADGET_Y, win) SetGadgetText ftexts[i], fields[i].GetString(o) If fields[i].MetaData(META_DIRECTORY).. Or fields[i].MetaData(META_SAVE).. Or fields[i].MetaData(META_LOAD) fbuttons[i] = CreateButton( LABEL_BROWSE, 2*SPACE_X+GADGET_X,y, .. BUTTON_X,GADGET_Y, win ) End If End If y :+ GADGET_Y + SPACE_Y Next ' Create buttons Local ok:TGadget, reset:TGadget If opts & FORM_RESET Local bx:Int = Min((sizex-3*SPACE_X)/2, BUTTON_X) Local sx:Int = (sizex-2*bx)/3 ok = CreateButton(LABEL_OK, sx,y, bx,GADGET_Y, win, BUTTON_OK) reset = CreateButton(LABEL_RESET, 2*sx+bx,y, bx,GADGET_Y, win) Else ok = CreateButton(LABEL_OK, (sizex-BUTTON_X)/2,y, BUTTON_X,GADGET_Y, win, BUTTON_OK) End If ' Main loop Repeat Select WaitEvent() Case EVENT_GADGETACTION Local source:Object = EventSource() ' OK If source=ok Exit ' Reset Else If source=reset For i = 0 Until fields.length If ftexts[i] 'Text field SetGadgetText ftexts[i], fields[i].GetString(o) Else If fcombos[i] 'Combo box Local value:String = fields[i].GetString(o) For Local j% = 0 Until CountGadgetItems(fcombos[i]) If GadgetItemText(fcombos[i],j)=value SelectGadgetItem fcombos[i], j Exit End If Next Else If fchecks[i] 'Check box SetButtonState fchecks[i], fields[i].GetInt(o) End If Next ' Browse Else For i = 0 Until fields.length If Not fbuttons[i] Or source<>fbuttons[i] Then Continue Local t:String = GadgetText(ftexts[i]) If fields[i].MetaData(META_DIRECTORY) t = RequestDir( GadgetText(flabels[i]), t ) Else Local s:Int = True Local exts:String = fields[i].MetaData(META_SAVE) If Not exts s = False exts = fields[i].MetaData(META_LOAD) End If If opts & FORM_TRIM_ exts = exts.Replace(UNDERSCORE, SPACE).Trim() End If t = RequestFile( GadgetText(flabels[i]), exts, s, t ) End If SetGadgetText ftexts[i], t Next End If Case EVENT_WINDOWCLOSE, EVENT_APPTERMINATE ' Free all gadgets For Local g:TGadget = EachIn flabels+ftexts+fcombos+fchecks + [ok,reset,win] FreeGadget g Next Return False End Select Forever ' Write data to object For i = 0 Until fields.length If ftexts[i] fields[i].SetString o, GadgetText(ftexts[i]) Else If fcombos[i] fields[i].SetString o, GadgetItemText( fcombos[i], SelectedGadgetItem(fcombos[i]) ) Else If fchecks[i] fields[i].SetInt o, ButtonState(fchecks[i]) End If Next ' Free all gadgets For Local g:TGadget = EachIn flabels+ftexts+fcombos+fchecks + [ok,reset,win] FreeGadget g Next Return True End Function |
Comments
None.
Code Archives Forum