Function O4WI_FORMDESIGNER_TEMPLATE_XXX(ACTION, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, status)
*#!Precompile


/*
*  This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without
*  written permission from Revelation Technologies, Inc.
!
*
*  VERSION    : 1.0
*
*
*  AUTHOR     : Revelation Software, Inc.  All Rights Reserved.
*
*  CREATED    : July 18, 2019
*
*
!
*
*  REVISION HISTORY           (Most CURRENT first) :
*
*    DATE       IMPLEMENTOR     FUNCTION
*  --------     -----------     --------
*
*/
*
$Insert o4wcommon
$Insert o4wequates
$Insert O4W_COMMUTER_COMMON
$Insert O4W_DESIGN_FORM_EQUATES

Declare Function Repository, Function, RTI_VERIFY_PROC

If Assigned(ACTION) Else ACTION = ""
If Assigned(param1) Else param1 = ""
If Assigned(param2) Else param2 = ""
If Assigned(param3) Else param3 = ""
If Assigned(param4) Else param4 = ""
If Assigned(param5) Else param5 = ""
If Assigned(param6) Else param6 = ""
If Assigned(param7) Else param7 = ""
If Assigned(param8) Else param8 = ""
If Assigned(param9) Else param9 = ""
If Assigned(param10) Else param10 = ""
If Assigned(param11) Else param11 = ""
If Assigned(status) Else status = ""

RSLT = ""
If Not(Num(ACTION)) Or ACTION < TEMPLATEWIDGET_ACTION_MIN_VALUE$ Or ACTION > TEMPLATEWIDGET_ACTION_MAX_VALUE$ Then
     rslt = WIDGET_ACTION_INVALID$
End Else
     On action Gosub doTemplateInfo,doQuickDraw,doCreate,doFormProperties
End

Return RSLT

doTemplateInfo:
* no parameters passed in
param1 = "Example Code"
rslt = "O4WI_FORMDESIGNER_TEMPLATE_XXX" ;* our ID
Return

doFormProperties:
* passed headerInfo (if asked to draw the form for real) or nothing (if just getting the tab IDs and Name(s))
headerInfo = param1
* if we have any overall "form" properties we need for this type of form, we could add them here...
If headerInfo = "" Then
     * looking for the name(s) and tab id(s) of the tab(s) we wish to add
     rslt<1> = ""; * tab id(s) (@VM delimited)
     rslt<2> = "" ;* tab name(s) (@VM delimited)
End Else
     * actually draw the tab(s)
End
Return

doQuickDraw:
* passed table, fields, tableStyle, textfields, textSearch, textResults, formfields, tabInfo, searchFields, resultFields, metafields)
table = param1
fields = param2
tableStyle = param3
textfields = param4
textSearch = param5
textResults = param6
formfields = param7
tabInfo = param8
searchFields = param9
resultFields = param10
metafields = param11
unselectedFields =  Xlate("DICT.":table, "%FIELDS%", 3, "X")
unselectedFields = Insert(unselectedFields, 1, 1, 0, "@ID")
num.fields = dcount(fields, @VM)
For each.Field = 1 To num.fields
this.Field = fields<1, each.Field>
Locate this.Field In unselectedFields<1> using @VM setting dummy Then
     unselectedFields = Delete(unselectedFields, 1, dummy, 0)
End
Next each.Field
num.unselected = dcount(unselectedFields, @VM)
tabOpts = " "
tabOpts<2> = "0"
tabOpts<1,-1> = "General":@VM:"Next Tab"
tabOpts<2,-1> = "-1":@VM:"1"
fieldTypes = "Textbox":@VM:"Listbox":@VM:"Checkbox":@VM:"Radio Buttons":@VM:"Text":@VM:"Date Picker":@VM:"Time Picker":@VM:"Toggle":@VM:"None/Not Used"
fieldCodes = "1":@VM:"2":@VM:"3":@VM:"4":@VM:"5":@VM:"6":@VM:"7":@VM:"9":@VM:"0"
helpID = 1
* draw our quickdraw tables in the qfMain section (if we have more than one page, use o4wtabs with qfMain being the "host" for the tabs)
o4wsectionstart("qfMain")
O4WHeader("Please select and re-order the form field(s)...", 5)
helpText = "Please select the field(s) that you wish to display and/or allow the user to update. Also choose the type of element you wish to use for this field. "
helpText := " For fields that offer multiple choices (like list boxes), you can choose the options once the form has been displayed."
helpText:= " Arrange the fields in the order you wish them to be displayed; pay particular attention to keep associated multivalue fields together if you wish them to be placed into the same table."
helpText:= "You can specify which tab the element should be placed on - the general tab is located above the individual tabs, or you can choose next tab to create a new tab.  "
helpText := " You can optionally suppress the use of tabs entirely if you wish."
helpID += 1; Gosub addQFHelp               
O4WBreak()
o4wtablestart("qfMainTable", tableStyle)
o4wtableheader("Field")
o4wtableheader("Field Type")
o4wtableheader("Put in tab...")
passedInfo = textFields; Gosub reArrangeFieldsForWizard
For each.Field = 1 To num.sfields
   this.field = sortedfields<1, each.field>
   fieldType = formFields<1, each.Field>
   o4wsetcell(each.Field, 1)                                    
   o4wtext(this.field)
   o4wstore(this.Field, "tForm")                  
   o4wsetcell()
   If fieldType = "" then
        fieldType = "1"
        dInfo = Xlate("DICT.":table, this.Field, "", "X")
        If dInfo = "" Then
          dInfo = Xlate("SYSDICT", this.Field, "", "X")
        end
        convCd = dInfo<7>
        Begin Case
          Case convCd[1,1] = "D"
               fieldType = "6"
          Case convCd[1,2] = "MT"
               fieldType = "7"
          Case convCd[1,1] = "B"
               fieldType = "9"
          *Case convCd[1,2] = "MR"
          *     fieldType = "8"
          Case dInfo<1> <> "F"
               fieldType = "5"
         End Case
   end
   O4WLISTBOXSTART("ftype", "qfMainTable_":each.Field, o4wmarkedoptions("", fieldType))
   o4wlistbox(fieldTypes, fieldCodes, "ftype")
   o4wlistboxend()
   o4wsetcell()
   this.tab = tabInfo<1, each.field>
   o4wlistbox(tabOpts<1>, tabOpts<2>, "ttype", "", "", o4wmarkedoptions("", this.tab))
   O4WSetCell("+1")
Next each.Field
CNTR = num.sfields
For each.Field = 1 To num.sunselected
   cntr+=1
   o4wsetcell(cntr)
   o4wtablemodify(cntr, "", "unselected")
   this.field = sortedUnusedFields<1, each.field>
   o4wtext(this.field)
   o4wstore(this.Field, "tForm")                  
   o4wsetcell()
   O4WLISTBOXSTART("ftype", "qfMainTable_us":each.Field, o4wmarkedoptions("", "0"))
   o4wlistbox(fieldTypes, fieldCodes, "ftype")
   o4wlistboxend()
   o4wsetcell()
   o4wlistbox(tabOpts<1>, tabOpts<2>, "ttype")
Next each.Field
o4wsetcell("+1")
o4wtableend("qfMainTable")
o4wqualifyevent("$", "hide", ".unselected")
o4wlink("Show/Hide additional fields", O4W_LINKTYPE_LOCAL$, "#", "", "BTN_TOGGLE")
o4wqualifyevent("BTN_TOGGLE", "toggle", ".unselected")
o4wbreak()
o4wbreak()
o4wbreak()
o4wbreak()
bNoTab = ""
If tabInfo = "" And textFields <> "" Then
     bNoTab = "1"
end
o4wcheckbox("Don't use tabs", "1", "notabs", "notabs", o4wmarkedoptions(bNoTab))
o4wbreak()
promptValue = metaFields<1,1>
o4wlistboxstart("metaFields_prompt", "metaFields_prompt_main", o4wmarkedoptions("", promptValue))
o4wlistbox("Put labels next to fields", "prompt_sidexside", "metaFields_prompt")
o4wlistbox("Put labels above fields", "prompt_overunder", "metaFields_prompt")
o4wlistbox("Use inline prompts (suppress labels)", "prompt_inline", "metaFields_prompt")
o4wlistboxend()
o4wbreak()
bClassic = metaFields<1,2> + 0
o4wcheckbox("Use 'classic' user interface on desktop", "use_classic", "metaFields_ui", "", o4wmarkedOptions(bClassic))
o4wsectionend("qfMain")
Return

doCreate:
* generate the page(s) from the quickdraw results
custom_names = ""
custom_values = ""
custom_names_label = ""
custom_values_label = ""
Gosub getLayoutValues
cntr = 1
maxPage = 1
dim pages(5)
mat pages = ""
sectionIsMV = 0
linkURL = "" 
newTabList = ""
tabList = ""
bInDisplayPage = 0
copyright_text = "(c) ":Field(Oconv(DATE(), "D4/"), "/", 3)
overrideLabels = ""
makeSubsection = ""
* passed newForm, table, varfields, formFields, searchFields, resultFields
newForm = param1
table = param2
varfields=param3
formFields=param4
searchFields=param5
resultFields=param6
headerText = TABLE:" Entry Form"
num.fields = dcount(varfields<1>, @VM)

newForm<HEADER_PAGES$> = "Form Details"
newForm<HEADER_PAGE_TYPE$> = "details"                  
currPage = 1
fields = varFields<1>
* organize based on tab information
Gosub orgTabs
target = formFields<1>
tabList = formFields<2>         
bInDisplayPage = 1         
Gosub addFields
* add in buttons to save/delete/cancel/etc.
btnURL = ""
row += 1
btnList = ""
ourCol = 0
btnList<1,-1> = "Save"
btnList<2,-1> = "BTN_SAVE"
btnList<3,-1> = ourCol
btnList<4,-1> = 0
ourCol += defGridWidth
btnList<1,-1> = "Cancel"
btnList<2,-1> = "BTN_CANCEL"
btnList<3,-1> = ourCol
btnList<4,-1> = 0
ourCol += defGridWidth
this.field.name = copyright_text; Gosub addFooterWithButtons
* wrap up the form definition
newForm<HEADER_NEXT_ID$> = cntr
For each.page = 1 To maxPage
 newForm := @RM:pages(each.page)
Next each.page
rslt = newForm
return

addQFHelp:
* passed helpText, helpID
     o4wbreak()
     o4wlink("Help...", O4W_LINKTYPE_LOCAL$, "#", "", "BTN_HELP":helpID)
     o4wtext("<<<":@VM, "help":helpID:"_b", "toggleMe":helpID)
     o4wtext(helpText:@VM:@VM, "help":helpID, "toggleMe":helpID)
     o4wqualifyevent("$", "hide", "help":helpID:"_b")
     o4wqualifyevent("$", "hide", "help":helpID)
     o4wqualifyevent("BTN_HELP":helpID, "toggle", ".toggleMe":helpID)
     o4wbreak()
Return

rearrangeFieldsForWizard:
* passed: passedInfo (selected values - if any)
* returns: updated sortedFields, sortedUnusedFields
sortedFields = fields
sortedUnusedFields = unselectedFields
If passedInfo <> "" Then
     num.text = dcount(passedInfo, @VM)
     For each.text = 1 To num.text
          this.text = passedInfo<1, each.text>
          Locate this.text In sortedFields<1> using @VM setting dummy Then
               sortedFields = Delete(sortedFields, 1, dummy, 0)
          End Else Locate this.text In sortedUnusedFields<1> using @VM setting dummy Then
               sortedUnusedFields = Delete(sortedUnusedFields, 1, dummy, 0)
          End
    Next each.text
    If sortedFields <> "" Then
        sortedFields = passedInfo:@VM:sortedFields
    End Else
        sortedFields = passedInfo
    End
end
num.sFields = dcount(sortedFields, @VM)
num.sUnselected = dcount(sortedUnusedFields, @VM)
Return

addFields:
pages(currPage)<FORMINFO_ID$, 1> = OVERALL_FORM_ID$:"_":currpage
pages(currPage)<FORMINFO_TYPE$> = CONTROL_TYPE_DIV$
pages(currPage)<FORMINFO_POSN$> = "0":@svm:"0":@svm:"12":@svm:"20"
pages(currPage)<FORMINFO_NEXT_POSN$> = "0":@svm:"0"
parent = ""
tabParent = ""
parentID = ""
overallParent = OVERALL_FORM_ID$:"_":currpage
currParent = overallParent
lastTab = ""
sizeStack = ""
* Put up a header
Gosub addHeader
addFields2:
* Now add in all the other fields
assoc = ""
row = 1
bDone = 0
If MakeSubSection <> "" Then
     * make a section, and put these fields inside of it
     Gosub addSubSection
End
num.fields = dcount(fields, @VM)
For each.Field = 1 To num.fields
   this.Field.name = fields<1, each.Field>
   this.field.type = target<1, each.Field>
   this.field.label = overrideLabels<1, each.Field>   
   this.tab = tabList<1, each.Field>
   dict.info = ""
   grid.width = defGridWidth
   If this.field.type <> "0" then 
     If this.tab <>  lastTab Then
          If parent <> "" Then
               * tables can't cross tabs - close out any pending table
               Gosub endTable
               parent = ""
               assoc = ""
          end
          If lastTab <> "" Then
               Gosub endSpecificTab
          End Else
               * first time through?  create our parent element
               Gosub startTabs
          end
          lastTab = this.tab
          Gosub startSpecificTab
          currParent = specificTab
     end
     dict.info = Xlate("DICT.":table, this.field.name, "", "X")
     If this.field.label = "" Then
          this.field.label = dict.info<3>
          If this.field.label = "" Then
               this.field.label = this.field.name
          End
     end
     width = dict.info<10> + 0
     If width = 0 Then width = 1
     screen.part = int(80/width)
     grid.width = int(12 / screen.part)
     If grid.width < defGridWidth Then
          grid.width = defGridWidth
     end
      this.assoc = dict.info<36>
      isMV = 0
      Begin Case
          Case sectionIsMV
               isMV = 1
          Case dict.info<4> _eqc "M" And this.assoc <> ""
               isMV = 1
          Case dict.info<4> _eqc "M"
               * no association name - is this a control type that supports MV fields?
               If this.field.type = "2" Or this.field.type = "3" Then
                    * yes, this type can be MV "by itself", not in a table
               End Else
                    isMV = 1 ;* this must be put in a table
                    * don't let it be associated with anyone else, though
                    this.assoc = this.field.name
               end
      End case
      if isMV Then
         If parent <> "" And this.assoc <> assoc And Not(sectionIsMV) Then
               * end the current table and begin a new one
            Gosub endTable
            parent = ""
         end
         If parent = "" Then
            * create new parent element
            Gosub startTable
            parent = tableID
            assoc = this.assoc
         End
         lPosn = "" ;* label handled specially here
         Gosub addTableColumn
         parentID = newColumnID
           * recalc our width now that we're in a table
           grid.width = int(12 / screen.part)
           If grid.width < defGridWidth Then
               grid.width = defGridWidth
           end            
      end else
         parentID = currParent
         lPosn = newForm<HEADER_DEFAULT_LABELTYPE$>         
         If parent <> "" Then
           * wrap up the parent element from the last MV
           Gosub endTable
           * recalc our width now that we're out of the table
           grid.width = int(12 / screen.part)
           If grid.width < defGridWidth Then
               grid.width = defGridWidth
           end            
         end
         parent = ""
      End
      ourLink = ""
      ourLinkType = ""
      If bDone = 0 Then
         ourLink = linkURL
         ourLinkType = O4W_LINKTYPE_LOCAL$
      End
      Gosub addField
      bDone = 1
   end
Next each.Field
If parent <> "" Then
   * wrap up the parent element from the last MV
   Gosub endTable
End
If lastTab <> "" Then
     Gosub endSpecificTab
End
If tabParent <> "" Then
     * wrap up the tab element
     Gosub endTab
End
If makeSubSection <> "" Then
     Gosub endSection
     makeSubSection = ""
end
* set 'next posn' for the parent container
pages(currPage)<FORMINFO_NEXT_POSN$, 1, FORMINFO_NEXT_POSN_ROW$> = ROW+1
Return

addSubSection:
   * build a sub section of type "makeSubSection"; set our currParent to it
   parentID = currParent
   thisID = ELEMENT_PREFIX$:CNTR
   cntr += 1   
   bProtected = 0
   prop_locn = ""
   prop_locn<1,1,FORMINFO_POSN_COL$> = "0"
   prop_locn<1,1,FORMINFO_POSN_ROW$> = row
   row += 1
   prop_locn<1,1,FORMINFO_POSN_HEIGHT$> = DEFAULT_TABLE_HEIGHT$ ;* MAX_GRID_HEIGHT$
   prop_locn<1,1,FORMINFO_POSN_WIDTH$> = MAX_GRID_WIDTH$ - 2
   bDataBind = 0
   type = makeSubSection
   lPlacement = WIDGET_LABEL_POSN_SXS$
   promptText = ""
   addClass = ""
   addBefore = ""
   Gosub addElement
   saveSectionParent = parentID
   currParent = thisID
   parentID = currParent
   saveSectionRow = row
   row = 0
   ourcol = 0
Return

endSection:
   * make sure all section elements are updated
   row = saveSectionRow + DEFAULT_TABLE_HEIGHT$ ;* MAX_GRID_HEIGHT$
   parentID = saveSectionParent
   currParent = saveSectionParent
Return


addField:
   * given this.field.name, this.field.type, dict.info, parentID, currPage, table, mode, maxID
   * populate pages(currPage)
   associated = ""
   bNeedLabel = 0
   thisID = ELEMENT_PREFIX$:CNTR
   cntr += 1   
   bProtected = 0
   prop_locn = ""
   lPlacement = newForm<HEADER_DEFAULT_LABELTYPE$>
   this.label = this.field.label
   convert @VM:@SVM:@TM to "   " in this.label
   prop_locn<1,1,FORMINFO_POSN_COL$> = "0"
   prop_locn<1,1,FORMINFO_POSN_ROW$> = row
   prop_locn<1,1,FORMINFO_POSN_WIDTH$> = grid.width
   bDataBind = 1
   ourHeight = defGridHeight   
   Begin Case
      Case this.field.type = "0"
         * ignore this one
         return
      Case this.field.type = "1"
         * textbox and label
         bNeedLabel = 1
         type = CONTROL_TYPE_INPUT_TEXT$
      Case this.Field.type = "2"
         * listbox and label
         bNeedLabel = 1
         type = CONTROL_TYPE_SELECT_MENU$
      Case this.field.type = "3"
         * checkbox and label
         bNeedLabel = 0 ;* don't need label - we get the field set
         type = CONTROL_TYPE_CHECK_SET$      
         ourHeight = 3
      Case this.field.type = "4"
         * radio button and label
         bNeedLabel = 0 ;* don't need label - we get the field set
         type = CONTROL_TYPE_RADIO_SET$        
         ourHeight = 3
      Case this.field.type = "5"
         * plain text
         bNeedLabel = 1
         this.label = "^"  ;* just show the current value
         type = CONTROL_TYPE_TEXT$         
      Case this.field.type = "6"
          * date picker
          bNeedLabel = 1
          type = CONTROL_TYPE_DATEPICKER$
          conv = dict.info<7>
		delimChar = ""
		euroFlag = ""
		If conv[1,1] = "D" Then
			* do we have a delimiter?
			delim = ""
			ccntr = 2
			next.char = conv[2,1]
			If next.char <> "E" And Num(next.char) Then
				ccntr = 3
				next.char = conv[3,1]
			End
			If Not(Index("EFGHIJQWASML",NEXT.CHAR,1)) And next.char <> "" Then
				* yes, this is a delimiter
				delimChar = next.char
				ccntr += 1
			End
			If conv[ccntr,1] = "E" Then
				* European format
				euroFlag = "1"
			End
		End
          If delimChar <> "" Then
               custom_names<-1> = WIDGET_MSG_DATE_DELIM$
               custom_values<-1> = delimChar
          End
          If euroFlag <> "" Then
               custom_names<-1> = WIDGET_MSG_DATE_EURO$
               custom_values<-1> = euroFlag
          end
      Case this.field.type = "7"
          * time picker
          bNeedLabel = 1
          type = CONTROL_TYPE_TIMEPICKER$
		show24 = ""
		showSeconds = ""
          conv = dict.info<7>
		If conv[1,2] = "MT" then
			If indexc(conv, "H", 1) = 0 then
				* not in 12 hour format - allow for 24 hour def'n
				show24 = "1"
			End
			If indexc(conv, "S", 1) Then
				* show seconds too
				showSeconds = "1"
			End
		end
          If show24 <> "" Then
               custom_names<-1> = WIDGET_MSG_TIME_24HR$
               custom_values<-1> = show24
          End
          If showSeconds <> "" Then
               custom_names<-1> = WIDGET_MSG_TIME_SECONDS$
               custom_values<-1> = showSeconds
          end
          
      Case this.field.type = "8"
          * NOT USED
          *bNeedLabel = 1
          *type = CONTROL_TYPE_INPUT_NUMBER$
       Case this.field.type = "9"
          * toggle
          bNeedLabel = 0
          type = CONTROL_TYPE_M_TOGGLE$
          ourHeight = 3
       Case this.field.type = "10"
          * button
          bNeedLabel = 0
          type = CONTROL_TYPE_BUTTON$
      Case this.field.type = "11"
          * file upload
          bNeedLabel = 1
          type = CONTROL_TYPE_INPUT_FILE$
       Case this.field.type = "12"
          * text area
          bNeedLabel = 1
          type = CONTROL_TYPE_INPUT_AREA$
      Case this.field.type = "13"
          * color picker
          bNeedLabel = 1
          type = CONTROL_TYPE_COLORPICKER$
      Case this.field.type = "14"
         * password and label
         bNeedLabel = 1
         type = CONTROL_TYPE_INPUT_TEXT$
          custom_names<-1> = WIDGET_MSG_SPECIAL_STYLE$ 
          custom_values<-1> = "password"
      Case this.field.type = "15"
         * hidden field
         bNeedLabel = 0
         type = CONTROL_TYPE_INPUT_TEXT$
          custom_names<-1> = WIDGET_MSG_SPECIAL_STYLE$ 
          custom_values<-1> = "hidden"
      Case this.field.type = "16"
          * image
          bNeedLabel = 1
          type = CONTROL_TYPE_IMAGE$
   End Case
   If IsMV Then
      * never show label for MV fields - already done in table
      bNeedLabel = 0
      lPlacement = WIDGET_LABEL_POSN_NONE$
   End
   promptText = ""
   addClass = ""
   If lPlacement = WIDGET_LABEL_POSN_INLINE$ Then
     bNeedLabel = 0
     promptText = this.label
   End
   row += ourHeight
   prop_locn<1,1,FORMINFO_POSN_HEIGHT$> = ourHeight
   addBefore = ""
   Gosub addElement2 ;* we already have our label
   If bNeedLabel Then
      posn = newposn ;* remember the location of our data element
      custom_names = custom_names_label
      custom_values = custom_values_label
      elementID = thisID
      associated = thisID ;* mark the label's associated field
      bDataBind = 0
      Gosub createLabel
   end
Return

AddElement:
 this.label = this.field.label
 convert @VM:@SVM:@TM to "   " in this.label
AddElement2: * entry point if this.label is already set
 names = ""
 values = ""
 names<1> = WIDGET_MSG_LABEL$
 values<1> = this.label
 names<2> = WIDGET_MSG_LINK$
 If ourLink <> "" Then
     values<2> = "1"
      names<3> = WIDGET_MSG_LINK_URL$
      values<3> = ourLink
      names<4> = WIDGET_MSG_LINK_TYPE$
      values<4> = ourLinkType
End Else
     values<2> = "0"
End
 names<-1> =  WIDGET_MSG_LABEL_PLACEMENT$
 VALUES<-1> = lPlacement
 this.size = dict.info<10>
 If this.size <> "" then
     names<-1> = WIDGET_MSG_SIZE$
     values<-1> = this.size
 end
 If bDataBind Then
    If table <> "" then
         names<-1> = WIDGET_MSG_DB_TABLE$
         values<-1> = table
    End
    If this.field.name <> "" then
         names<-1> = WIDGET_MSG_DB_FIELD$
         values<-1> = this.field.name
         names<-1> = WIDGET_MSG_NAME$
         values<-1> = this.field.name
    end
    names<-1> = WIDGET_MSG_DB_RO$
    isRO = 0
     If (dict.info<1> _eqc "S") And bInDisplayPage Then
          isRO = 2 ;* make it unchangeable
     end
     values<-1> = isRO
     If dict.info<4> _eqc "M" then
          names<-1> = WIDGET_MSG_DB_MV$
          values<-1> = "1"
     end
     names<-1> = WIDGET_MSG_SET_SHOWNONE$
     values<-1> = Not(bInDisplayPage)
     names<-1> = WIDGET_MSG_CONTROL_ALIGN$
     values<-1> = "0" ;* assume all controls will left align
     names<-1> =  WIDGET_MSG_FONT_ALIGN$
     align = "0"
     If dict.info<9> = "R" Then
          align = "2"
     End Else If dict.info<9> = "C" Or dict.info<9> = "T" Then
          align = "1"
     end
     values<-1> = align
     If promptText <> "" Then
          names<-1> = WIDGET_MSG_PROMPT$
          values<-1> = promptText
     End
     If addClass <> "" Then
          names<-1> = WIDGET_MSG_CLASS_ADD$
          values<-1>= addClass
     end
 End
 names<-1> = custom_names
 values<-1> = custom_values
 custom_names = ""
 custom_values = ""
 newForm<HEADER_NEXT_ID$> = cntr ;* make sure this is up to date
 newPosn = o4wi_formdesigner_widget_new(newForm, pages(currPage), thisID, parentID, type, prop_locn, associated, bProtected, addBefore, names, values)
 * maxID may have changed - be sure to refresh it
 cntr = newForm<HEADER_NEXT_ID$>
Return

createLabel:
      * create the label element
      If lPosn = "" Then Return ;* don't put the label element on at all
      thisID = ELEMENT_PREFIX$:CNTR
      cntr += 1
      TYPE = CONTROL_TYPE_TEXT$
      prop_locn = pages(currPage)<FORMINFO_POSN$, posn> ;* let the label assume the 'landing position' from the user
      aelement_locn = prop_locn
      If lPosn = WIDGET_LABEL_POSN_SXS$ Then
         * side-by-side
         * Change the size of the label so it's "standard size"
         prop_locn<1,1,FORMINFO_POSN_WIDTH$> = defGridWidth ;* so everything lines up in the columns
         * now move the associated element so it's in the right place
         aelement_locn<1,1, FORMINFO_POSN_COL$> = prop_locn<1,1, FORMINFO_POSN_COL$> + defGridWidth
      End Else
         * over/under
         aelement_locn<1,1, FORMINFO_POSN_ROW$> = prop_locn<1,1, FORMINFO_POSN_ROW$> + prop_locn<1,1,FORMINFO_POSN_HEIGHT$>         
         * adjust our "next position to use"
         row += prop_locn<1,1,FORMINFO_POSN_HEIGHT$>
         * and finally set our height to 1 (by default the label should only be 1 high)
         aelement_locn<1,1,FORMINFO_POSN_HEIGHT$> = 1
      End
      pages(currPage)<FORMINFO_POSN$, posn> = aelement_locn
      bProtected = 0
      lPlacement = lPosn
      promptText = ""
      addClass = ""
      addBefore = "1"
      Gosub addElement      
      pages(currPage)<FORMINFO_ASSOCIATED$, posn> = thisID ;* tell our associated control who we are
      pages(currPage)<FORMINFO_LABEL_TYPE$, posn> = "2" ;* and that they are the "master"
Return

startTable:
   * create new table element as parent For these
   parentID = currParent
   thisID = ELEMENT_PREFIX$:CNTR
   cntr += 1   
   bProtected = 0
   prop_locn = ""
   prop_locn<1,1,FORMINFO_POSN_COL$> = "0"
   prop_locn<1,1,FORMINFO_POSN_ROW$> = row
   row += 1
   prop_locn<1,1,FORMINFO_POSN_HEIGHT$> = DEFAULT_TABLE_HEIGHT$ ;* MAX_GRID_HEIGHT$
   prop_locn<1,1,FORMINFO_POSN_WIDTH$> = MAX_GRID_WIDTH$ - 2
   bDataBind = 0
   tableID = thisID
   type = CONTROL_TYPE_TABLE$
   lPlacement = WIDGET_LABEL_POSN_SXS$
   promptText = ""
   addClass = ""
   addBefore = ""
   Gosub addElement
   If sectionIsMV = 2 Then
     * mark this as a multiRecord table
     names = WIDGET_MSG_TBL_TYPE$
     values = "2"
     Gosub updateTable
  End
  saveTableRow = row
  sizeStack = Insert(sizeStack, 1, 0, 0, defGridWidth)
  defGridWidth = MAX_GRID_WIDTH$ - 2
Return


addTableColumn:
   * add a new child div To the parent table
   newColName = this.field.label
   convert @VM:@SVM:@TM to "   " in newColName
   newColumnID = ""
      names = ""
      values = ""
      names<1> = WIDGET_MSG_TBL_COLUMN_ADD$
      values<1> = newColName
      newForm<HEADER_NEXT_ID$> = cntr ;* make sure this is up to date
     Gosub updateTable
      * maxID may have changed - be sure to refresh it
      cntr = newForm<HEADER_NEXT_ID$>
      * return our new column ID
      newColumnID = pInfo
      * make sure our children are full sized
      defGridWidth = MAX_GRID_WIDTH$ - 2     
      * And reset our row to the top of the column
      row = 0
Return

updateTable:
   * let the element update itself
   supportName = UCASE(DESIGN_SUPPORT_PREFIX$:CONTROL_TYPE_TABLE$)
   IF RTI_VERIFY_PROC(supportName, 0, 5) = 0 THEN
     * failed
     CALL SET_STATUS(0)
   END Else
      pInfo = Function(@supportName(WIDGET_ACTION_UPDATE$, newForm, pages(currPage), tableID, "", names, values))      
   End
 return

endTable:
   * make sure all table elements are updated
   row = saveTableRow + DEFAULT_TABLE_HEIGHT$ ;* MAX_GRID_HEIGHT$
   defGridWidth = sizeStack<1>
   sizeStack = Delete(sizeStack, 1, 0, 0)
Return

addButton:
   * passed btn (text), btnID, btnURL (optional), ourCol, Row, btnType
   parentID = OVERALL_FORM_ID$:"_":currpage
addButton2:
   * entry point for different parents
   type = btnType
   thisID = ELEMENT_PREFIX$:CNTR
   cntr += 1   
   bProtected = 0
   prop_locn = ""
   prop_locn<1,1,FORMINFO_POSN_COL$> = ourCol
   prop_locn<1,1,FORMINFO_POSN_ROW$> = row
   prop_locn<1,1,FORMINFO_POSN_HEIGHT$> = defGridHeight
   prop_locn<1,1,FORMINFO_POSN_WIDTH$> = defGridWidth
   bDataBind = 0
   associated = ""
   lPlacement = WIDGET_LABEL_POSN_SXS$
   promptText = ""
   addClass = ""
   addBefore = ""
   Gosub addElement
   * let the element update itself
   supportName = UCASE(DESIGN_SUPPORT_PREFIX$:type)
   IF RTI_VERIFY_PROC(supportName, 0, 5) = 0 THEN
       CALL SET_STATUS(0)
   END Else
      names = ""
      values = ""
      names<1> = WIDGET_MSG_LABEL$
      values<1> = btn
      names<2> = WIDGET_MSG_LINK$
      If btnURL = "" Then
        values<2> = 0
     End else
         values<2> = 1
         names<3> = WIDGET_MSG_LINK_URL$
         values<3> = btnURL
         names<4> = WIDGET_MSG_LINK_TYPE$
         values<4> = O4W_LINKTYPE_LOCAL$
      End
      names<-1> = WIDGET_MSG_BTN_DEFAULT$
      values<-1> = bDefault
      newForm<HEADER_NEXT_ID$> = cntr ;* make sure this is up to date
      pInfo = Function(@supportName(WIDGET_ACTION_UPDATE$, newForm, pages(currPage), thisID, "", names, values))      
      * maxID may have changed - be sure to refresh it
      cntr = newForm<HEADER_NEXT_ID$>
   end   
   
Return

orgTabs: * reorganize fields so that each tab is sequential In the list
* passed: fields, formFields<1> (field types) and formFields<2> (tabs)
* sets newTabList, updates formFields, updates fields
num.names = dcount(fields, @VM)
formTypes = formFields<1>
tabList = formFields<2>
If tablist = "" Or tablist = str("0":@VM, num.names-1):"0" then
     * nothing to do here - no tabs
     formFields<2> = ""
     Return
End
newTabList = ""
currTabNum = 0
For each.name = 1 To num.names
     this.name = fields<1, each.name>
     this.tab = tabList<1, each.name>
     this.type = formTypes<1, each.name>
     Begin Case
          Case this.tab = "0" And newTabList <> ""
               * unchanged
               tabNum = currTabNum
          Case this.tab = "-1"
               * general
               TabNum = -1
               currTabNum = tabNum
          Case this.tab = "1" Or newTabList = ""
               * new tab
               currTabNum += 1
               tabNum = currTabNum
     End Case
     Locate tabNum In newTabList<1> by "AR" using @VM setting posn then
          newTabList<2, posn, -1> = this.name
          newTabList<3,posn,-1> = this.type
     End Else
          newTabList = Insert(newTabList, 1, posn, 0, tabNum)
          newTabList = Insert(newTabList, 2, posn, 0, this.name)
          newTabList = Insert(newTabList, 3, posn, 0, this.type)
     End
 Next each.name
 * rebuild the list
 num.tabs = dcount(newTabList<1>, @VM)
 nlist = ""
 list1 = ""
 list2 = ""
 tabcntr = 1
 For each.tab = 1 To num.tabs
     this.tab = newTabList<1, each.tab>
     If this.tab = "-1" Then
          this.tab = ""
     End Else
          this.tab = "Tab ":tabcntr
          tabcntr += 1
     End
     these.names = newTabList<2, each.tab>
     these.types = newTabList<3, each.tab>
     num.names = dcount(these.names, @SVM)
     Convert @SVM To @VM In these.names
     Convert @SVM To @VM In these.types
     nList := these.names:@VM
     list1  := these.types:@VM
     list2  := str(this.tab:@VM, num.names)
Next each.tab
formFields<1> = list1[1, Len(list1)-1]
formFields<2> = list2[1, Len(list2)-1]
fields = nList[1, Len(nList)-1]
Return

startTabs: * determine number of tabs, And create parent And children tab elements
* passed tabList, newTabList
* sets tabParent
   parentID = currParent
   thisID = ELEMENT_PREFIX$:CNTR
   cntr += 1   
   bProtected = 0
   prop_locn = ""
   prop_locn<1,1,FORMINFO_POSN_COL$> = "0"
   prop_locn<1,1,FORMINFO_POSN_ROW$> = row
   row += 1
   prop_locn<1,1,FORMINFO_POSN_HEIGHT$> = MAX_GRID_HEIGHT$
   prop_locn<1,1,FORMINFO_POSN_WIDTH$> = MAX_GRID_WIDTH$-2
   bDataBind = 0
   tableID = thisID
   type = CONTROL_TYPE_TAB$
   lPlacement = WIDGET_LABEL_POSN_SXS$
   promptText = ""
   addClass = ""
   addBefore = ""
   Gosub addElement
   tabParent = thisID
   currParent = thisID
   savedRow = row
Return

Return

startSpecificTab: * create child tab element
* passed lastTab, sets specificTab
* let the element update itself
supportName = UCASE(DESIGN_SUPPORT_PREFIX$:CONTROL_TYPE_TAB$)
IF RTI_VERIFY_PROC(supportName, 0, 5) = 0 THEN
* failed
CALL SET_STATUS(0)
END Else
 newForm<HEADER_NEXT_ID$> = cntr ;* make sure this is up to date
 names = WIDGET_MSG_TBL_COLUMN_ADD$
 values = lastTab
 pInfo = Function(@supportName(WIDGET_ACTION_UPDATE$, newForm, pages(currPage), tabParent,"", names, values))      
 * maxID may have changed - be sure to refresh it
 cntr = newForm<HEADER_NEXT_ID$>
 * return our new column ID
  specificTab = pInfo 
  * and reset our position to top row
  row = 0
End
Return

endSpecificTab: * close child tab element
* passed lastTab
row = savedRow + MAX_GRID_HEIGHT$
Return

endTab: * close overall tab element
* passed tabParent
row = savedRow + MAX_GRID_HEIGHT$
Return

getLayoutValues:
      call Set_Status(0)
      layoutInformation = Repository("ACCESS", @APPID<1>:"*APPROW**O4WCODES:FORMDESIGNER_LAYOUT")
      call Set_Status(0)
      If layoutInformation = "" Then
         layoutInformation = Xlate("O4WCODES", "FORMDESIGNER_LAYOUT", "", "X")
      End      
      maxGridWidth = layoutInformation<CONFIG_GRID_SIZE_MAX$,1>
      If maxGridWidth = "" Then
          maxGridWidth = MAX_GRID_WIDTH$
      End
      maxGridHeight = layoutInformation<CONFIG_GRID_SIZE_MAX$,2>
      If maxGridHeight = "" Then
          maxGridHeight = MAX_GRID_HEIGHT$
      End
      
      defGridWidth = layoutInformation<CONFIG_GRID_SIZE_ELEMENT$,1>
      If defGridWidth = "" Then
          defGridWidth = DEFAULT_GRID_WIDTH$
      End
      defGridHeight = layoutInformation<CONFIG_GRID_SIZE_ELEMENT$,2>
      If defGridHeight = "" Then
          defGridHeight = DEFAULT_GRID_HEIGHT$
      End
      defGridContainerWidth = layoutInformation<CONFIG_GRID_SIZE_CONTAINER$,1>
      If defGridContainerWidth = "" Then
          defGridContainerWidth = DEFAULT_GRID_CONTAINER_WIDTH$
      End
      defGridContainerHeight = layoutInformation<CONFIG_GRID_SIZE_CONTAINER$,2>
      If defGridContainerHeight = "" Then
          defGridContainerHeight = DEFAULT_GRID_CONTAINER_HEIGHT$
      End
      
     cellHeight = layoutInformation<CONFIG_CELL_HEIGHT$>
     If cellHeight = "" Then
          cellHeight = DEFAULT_GRID_CELL_HEIGHT$
     End
Return

addFooterWithButtons: 
* btnList<1,x> = list of button text
* btnList<2,x> = associated list of button IDs
* btnList<3,x> = associated list of button positions
* btnList<4,x> = associated list of "is default button?" flags
* this.field.name = footer text
* first, create the mobile footer itself
save.defGridHeight = defGridHeight
defGridHeight = 2 * defGridHeight
footer.text = this.field.name
this.field.name = "" ;* create without any header text
Gosub addFooter2
footerID = thisID
defGridHeight = save.defGridHeight
* save all the 'real' values
save.parentID = parentID
save.parent = parent
save.tabParent = tabParent
save.overallParent = overallParent
save.currParent = currParent
save.lastTab = lastTab
save.row = row
* next, make a 'button set' to hold the buttons
parentID = footerID
type = CONTROL_TYPE_BUTTON_SET$
associated = ""
thisID = ELEMENT_PREFIX$:CNTR
cntr += 1   
bProtected = 0
prop_locn = ""
prop_locn<1,1,FORMINFO_POSN_COL$> = "0"
prop_locn<1,1,FORMINFO_POSN_ROW$> = 0
prop_locn<1,1,FORMINFO_POSN_HEIGHT$> = defGridHeight
prop_locn<1,1,FORMINFO_POSN_WIDTH$> = maxGridWidth
this.field.value = ""
dict.info = ""
dict.info<10> = 5
isMV = 0
bDataBind = 0
ourLink = ""
ourLinkType = ""
lPlacement = WIDGET_LABEL_POSN_SXS$
promptText = ""
addClass = ""
addBefore = ""
this.field.label = ""
Gosub addElement
bsetID = thisID
* next, put our buttons inside
parentID = bsetID
row = 0
btnType = CONTROL_TYPE_BUTTON$
num.buttons = dcount(btnList<1>, @VM)
save.defGridWidth = defGridWidth
defGridWidth = int(maxGridWidth / num.buttons)
ourCol = 0
For each.btn = 1 To num.buttons
     btn = btnList<1, each.btn>
     btnID = btnList<2, each.btn>
     * ourCol = btnList<3, each.btn>
     bDefault = btnList<4, each.btn>
     Gosub addButton2
     ourCol += defGridWidth
Next each.btn
defGridWidth = save.defGridWidth
* finally, put an explicit header inside
parentID = footerID
type = CONTROL_TYPE_HEADER$
associated = ""
thisID = ELEMENT_PREFIX$:CNTR
cntr += 1   
bProtected = 0
prop_locn = ""
prop_locn<1,1,FORMINFO_POSN_COL$> = "0"
prop_locn<1,1,FORMINFO_POSN_ROW$> = 1
prop_locn<1,1,FORMINFO_POSN_HEIGHT$> = defGridHeight
prop_locn<1,1,FORMINFO_POSN_WIDTH$> = maxGridWidth
this.field.value = ""
dict.info = ""
dict.info<10> = 5
isMV = 0
bDataBind = 0
ourLink = ""
ourLinkType = ""
lPlacement = WIDGET_LABEL_POSN_SXS$
promptText = ""
addClass = ""
addBefore = ""
this.field.label = footer.text
Gosub addElement
* restore everything
parentID = save.parentID
parent = save.parent
tabParent = save.tabParent
overallParent = save.overallParent
currParent = save.currParent
lastTab = save.lastTab
row = save.row
return
         
addFooter:
* add in a footer section
this.field.name = copyright_text
addFooter2:
hfRow = row + 5
If hfRow < MAX_GRID_HEIGHT$ Then
     hfRow = MAX_GRID_HEIGHT$
end
hfSize  = 5
type = CONTROL_TYPE_M_FOOTER$ 
custom_names<1,-1> = WIDGET_MSG_MOB_FIXED$
custom_values<1,-1> = "1"
Goto addHeaderFooter

addHeader:
this.field.name = headerText
hfRow = "0"
hfSize = "3"
type = CONTROL_TYPE_M_HEADER$ 
* fall through

addHeaderFooter:
* passed type, hfRow, hfSize, this.field.name
save.parentID = parentID
save.parent = parent
save.tabParent = tabParent
save.overallParent = overallParent
save.currParent = currParent
save.lastTab = lastTab
associated = ""
parentID = OVERALL_FORM_ID$:"_":currpage
thisID = ELEMENT_PREFIX$:CNTR
cntr += 1   
bProtected = 0
prop_locn = ""
prop_locn<1,1,FORMINFO_POSN_COL$> = "0"
prop_locn<1,1,FORMINFO_POSN_ROW$> = hfRow
prop_locn<1,1,FORMINFO_POSN_HEIGHT$> = defGridHeight
prop_locn<1,1,FORMINFO_POSN_WIDTH$> = maxGridWidth
this.field.value = ""
dict.info = ""
dict.info<10> = hfSize
isMV = 0
bDataBind = 0
ourLink = ""
ourLinkType = ""
lPlacement = WIDGET_LABEL_POSN_SXS$
promptText = ""
addClass = ""
addBefore = ""
this.field.label = this.field.name
Gosub addElement
parentID = save.parentID
parent = save.parent
tabParent = save.tabParent
overallParent = save.overallParent
currParent = save.currParent
lastTab = save.lastTab
Return

