Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 195 lines (146 sloc) 7.021 kb
ee8c778 second tutorial snapshot save
megaannum authored
1 # Submit Button
2
3 A 'Submit' Event tells the Form to gather up all of the Glyph tag/value
4 pairs in a Dictionary and return the Dictionary. For most dialog
5 like Forms, there will be a 'cancel' or 'close' (or some similar name)
6 Button. For those
7 Forms that wish to give the user the option of entering information
8 and then having the code that created and launched the Form to
9 get that information, there will also be an 'accept' or 'submit'
10 Button. A developer is, of course, free to have their Form directly
11 set (and get) values from VimL variables defined outside of the
12 scope of the Form, but that will lead to a tight binding between
13 the code exterior to the Form and code that makes up the Form.
14 This would make the Form more brittle and increase potential errors
15 reducing reuse (IMO).
16
17 A Submit Button is created by making a Button where its action is
18 the Forms Submit Action:
19
20 let label = forms#newLabel({'text': "Submit"})
21 let button = forms#newButton({
22 \ 'tag': 'submit',
23 \ 'body': label,
24 \ 'action': g:forms#submitAction})
25
26 In this case, the Button's 'tag' is called 'submit'.
27
28 The above Action is a global defined in the Forms code as:
29
30 function! FormsSubmitAction(...) dict
31 call forms#AppendInput({ 'type': 'Submit' })
32 endfunction
33
34 let g:forms#submitAction = forms#newAction({ 'execute': function("FormsSubmitAction")})
35
36 One can see that the Action's 'execute' attribute is the Function
37 'FormsSubmitAction' which adds a 'Submit' Event to the front of
38 the Forms Input Queue.
39
40 In this example, let us have two CheckBoxes:
41
42 let cb1 = forms#newCheckBox({'tag': 'cbone'})
43 let cb2 = forms#newCheckBox({'tag': 'cbtwo'})
44
45 These have tags that identify them.
46
47 Also, assume that there is a 'Close' Button:
48
49 let label = forms#newLabel({'text': "Close"})
50 let button = forms#newButton({
51 \ 'tag': 'close',
52 \ 'body': label,
53 \ 'action': g:forms#cancelAction})
54
55 If the Submit Button is selected, then a 'Submit' Event is place at the
56 front. In the Viewer 'run()' method there ia a loop that reads
57 input Events/Characters and processes them. The part of that loop
58 that handles a 'Submit' Event follows:
59
60 elseif type == 'Submit'
61 if forms#ViewerStackDepth() > 1
62 call self.unGetChar(event)
63 break
64 else
65 return event
66 endif
67
68 Notice that if the current Viewer is not a top-level Viewer, then
69 the 'Submit' Event it placed back on the front of the Input Queue,
70 the read loop is exited and control is returned to the next higher
71 Viewer. This continues until the Viewer Stack is empty, one is at
72 the top-level Viewer, at which point the Viewer 'run()' method
73 returns the 'Submit' Event to the Form 'run()' method that had
74 originally called the Viewer's method.
75
76 The Form 'run()' method has the code that calls its ProtoType Object
77 'run()' method, the Viewer 'run()' method and then processes
78 any returned value:
79
80 " call Form prototype run() method
81 let p = g:forms#Form._prototype
82 let rval = call(p.run, [], self)
83
84 In the Form 'run()' code that handles the Viewer's 'run()' method
85 returned value:
86
87 let results = {}
88 ....
89 elseif rval.type == 'Submit'
90 call self.generateResults(self.__body, results)
91 return results
92
93 If the return value is an Event of 'type' 'Submit', that is, a 'Submit'
94 Event, then the 'generateResults()' method is called which directly
95 in turn calls the Function forms#GenerateResults():
96
9238e01 fifth tutorial snapshot save
megaannum authored
97 function! forms#GenerateResults(glyph, results)
98 let nodeType = a:glyph.nodeType()
99 if nodeType == g:LEAF_NODE
100 call a:glyph.addResults(a:results)
ee8c778 second tutorial snapshot save
megaannum authored
101
9238e01 fifth tutorial snapshot save
megaannum authored
102 elseif nodeType == g:MONO_NODE
103 call a:glyph.addResults(a:results)
ee8c778 second tutorial snapshot save
megaannum authored
104
9238e01 fifth tutorial snapshot save
megaannum authored
105 call forms#GenerateResults(a:glyph.getBody(), a:results)
ee8c778 second tutorial snapshot save
megaannum authored
106
9238e01 fifth tutorial snapshot save
megaannum authored
107 elseif nodeType == g:POLY_NODE
108 call a:glyph.addResults(a:results)
ee8c778 second tutorial snapshot save
megaannum authored
109
9238e01 fifth tutorial snapshot save
megaannum authored
110 for child in a:glyph.children()
111 call forms#GenerateResults(child, a:results)
112 endfor
ee8c778 second tutorial snapshot save
megaannum authored
113
9238e01 fifth tutorial snapshot save
megaannum authored
114 elseif nodeType == g:GRID_NODE
115 call a:glyph.addResults(a:results)
ee8c778 second tutorial snapshot save
megaannum authored
116
9238e01 fifth tutorial snapshot save
megaannum authored
117 for minor in a:glyph.major()
118 for child in minor
119 call forms#GenerateResults(child, a:results)
120 endfor
ee8c778 second tutorial snapshot save
megaannum authored
121 endfor
122
9238e01 fifth tutorial snapshot save
megaannum authored
123 else
124 throw "Unknown glyph nodeType " . nodeType
125 endif
126 endfunction
ee8c778 second tutorial snapshot save
megaannum authored
127
128 Note that this code recursively walks the Glyph tree visiting
129 each child Glyph and calling each child Glyph's 'addResults()'
130 method. Now, the base Glyph, the Glyph Prototype Object has
131 a 'addResults()' that does nothing:
132
133 function! FORMS_GLYPH_addResults(results) dict
134 endfunction
135 let g:forms#Glyph.addResults = function("FORMS_GLYPH_addResults")
136
137 It adds nothing to the Dictionary results object. So, while the
138 'GenerateResults()' walks the tree for most Glyphs in the tree, nothing
139 is added to the 'results' Dictionary. This is understood when on
140 considers that passive Glyphs such as a Label for formating/layout
141 Glyphs such as Mono or Poly Glyph would generally not have anything
142 interesting to return to the calling code. On the other hand,
143 Glyphs that maintain state entered by the user, do add values to the
144 'results' Dictionary.
145
146 In this example code, both CheckBoxes will add to the 'results'
147 object:
148
149 function! FORMS_CHECKBOX_addResults(results) dict
150 let tag = self.getTag()
151 let a:results[tag] = self.__selected
152 endfunction
153 let g:forms#CheckBox.addResults = function("FORMS_CHECKBOX_addResults")
154
155 They both get their respective 'tag' as a Dictionary key and
156 whether or not they have been selected as the associated value.
157 In addtion, the 'Submit' and 'Close' Buttons also have 'addResults()'
158 methods:
159
160 function! FORMS_BUTTON_addResults(results) dict
161 let tag = self.getTag()
162 let a:results[tag] = self.__selected
163 endfunction
164 let g:forms#RadioButton.addResults = function("FORMS_BUTTON_addResults")
165
166 If the example Form only had the two CheckBoxes and the 'Submit' and
167 'Close' Buttons then the 'results' Dictionary might contain the following:
168
169 { 'submit': 1, 'close': 0, 'cbone' : 0, 'cbtwo' : 0 }
170
171 The 'Submit' Button was pushed, value == 1, and neither CheckBoxes
172 were selected, values == 0.
173 If the CheckBox with tag 'cbone' was selected when the 'Submit'
174 Button was selected the 'results' would contain:
175
176 { 'submit': 1, 'close': 0, 'cbone' : 1, 'cbtwo' : 0 }
177
178 If both CheckBoxes were selected:
179
180 { 'submit': 1, 'close': 0, 'cbone' : 1, 'cbtwo' : 1 }
181
182 Importantly, the 'results' Dictionary only contains data if a
183 'Submit' Event occurred. A 'Cancel' event generated by the 'Close'
184 Button will return an empty Dictionary. So, in the above case, one
185 will never encounter the following:
186
187 { 'submit': 0, 'close': 1, 'cbone' : 0, 'cbtwo' : 0 }
188
189 Because this means that the 'Close' Button was selected, but the
190 'Close' Button generates a 'Cancel' Event and a 'Cancel' Event
191 will only return an empty Dictionary.
192
193
194
Something went wrong with that request. Please try again.