blob: dfbad01d382ff67413f55d80dad26a8cfe247db1 [file] [log] [blame]
Guido van Rossumb00649c1991-12-11 17:29:59 +00001#
2# flp - Module to load fl forms from fd files
3#
4# Jack Jansen, December 1991
5#
6import string
7import path
8import sys
9import fl
10import FL
11
12SPLITLINE = '--------------------'
13FORMLINE = '=============== FORM ==============='
14ENDLINE = '=============================='
15
16error = 'flp.error'
17
18##################################################################
19# Part 1 - The parsing routines #
20##################################################################
21
22#
23# Externally visible function. Load form.
24#
25def parse_form(filename, formname):
26 fp = _open_formfile(filename)
27 nforms = _parse_fd_header(fp)
28 for i in range(nforms):
29 form = _parse_fd_form(fp, formname)
30 if form <> None:
31 return form
32 raise error, 'No such form in fd file'
33
34#
35# Externally visible function. Load all forms.
36#
37def parse_forms(filename):
38 fp = _open_formfile(filename)
39 nforms = _parse_fd_header(fp)
40 forms = {}
41 for i in range(nforms):
42 form = _parse_fd_form(fp, None)
43 forms[form[0].Name] = form
44 return forms
45
46#
47# Internal: Locate form file (using PYTHONPATH) and open file
48#
49def _open_formfile(filename):
50 if filename[-3:] <> '.fd':
51 filename = filename + '.fd'
Guido van Rossumbdfcfcc1992-01-01 19:35:13 +000052 if filename[0] == '/':
Guido van Rossumb00649c1991-12-11 17:29:59 +000053 try:
54 fp = open(filename,'r')
Guido van Rossumb00649c1991-12-11 17:29:59 +000055 except IOError:
56 fp = None
57 else:
58 for pc in sys.path:
59 pn = path.join(pc, filename)
60 try:
61 fp = open(pn, 'r')
62 break
Guido van Rossumb00649c1991-12-11 17:29:59 +000063 except IOError:
64 fp = None
Guido van Rossumbdfcfcc1992-01-01 19:35:13 +000065 if fp == None:
Guido van Rossumb00649c1991-12-11 17:29:59 +000066 raise error, 'Cannot find forms file ' + filename
67 return fp
68
69#
70# Internal: parse the fd file header, return number of forms
71#
72def _parse_fd_header(file):
73 # First read the magic header line
74 datum = _parse_1_line(file)
75 if datum <> ('Magic', 12321):
76 raise error, 'Not a forms definition file'
77 # Now skip until we know number of forms
78 while 1:
79 datum = _parse_1_line(file)
Guido van Rossumbdfcfcc1992-01-01 19:35:13 +000080 if type(datum) == type(()) and datum[0] == 'Numberofforms':
Guido van Rossumb00649c1991-12-11 17:29:59 +000081 break
82 return datum[1]
83#
84# Internal: parse fd form, or skip if name doesn't match.
85# the special value None means 'allways parse it'.
86#
87def _parse_fd_form(file, name):
88 datum = _parse_1_line(file)
89 if datum <> FORMLINE:
90 raise error, 'Missing === FORM === line'
91 form = _parse_object(file)
Guido van Rossumbdfcfcc1992-01-01 19:35:13 +000092 if form.Name == name or name == None:
Guido van Rossumb00649c1991-12-11 17:29:59 +000093 objs = []
94 for j in range(form.Numberofobjects):
95 obj = _parse_object(file)
96 objs.append(obj)
97 return (form, objs)
98 else:
99 for j in range(form.Numberofobjects):
100 _skip_object(file)
101 return None
102
103#
104# Internal class: a convient place to store object info fields
105#
Guido van Rossum869100a1991-12-26 13:03:39 +0000106class _newobj:
Guido van Rossumb00649c1991-12-11 17:29:59 +0000107 def init(self):
108 return self
109 def add(self, (name, value)):
110 cmd = 'self.'+name+' = '+`value`+'\n'
111 exec(cmd)
112
113#
114# Internal parsing routines.
115#
116def _parse_string(str):
Guido van Rossumbefa2931991-12-16 13:10:14 +0000117 return str
Guido van Rossumb00649c1991-12-11 17:29:59 +0000118
119def _parse_num(str):
Guido van Rossumbefa2931991-12-16 13:10:14 +0000120 return eval(str)
Guido van Rossumb00649c1991-12-11 17:29:59 +0000121
122def _parse_numlist(str):
123 slist = string.split(str)
124 nlist = []
125 for i in slist:
126 nlist.append(_parse_num(i))
127 return nlist
128
129# This dictionary maps item names to parsing routines.
130# If no routine is given '_parse_num' is default.
131_parse_func = { \
132 'Name': _parse_string, \
133 'Box': _parse_numlist, \
134 'Colors': _parse_numlist, \
135 'Label': _parse_string, \
136 'Name': _parse_string, \
137 'Callback': _parse_string, \
138 'Argument': _parse_string }
139
140# This function parses a line, and returns either
141# a string or a tuple (name,value)
142
Guido van Rossumbefa2931991-12-16 13:10:14 +0000143import regexp
144
Guido van Rossumb00649c1991-12-11 17:29:59 +0000145def _parse_line(line):
Guido van Rossumbefa2931991-12-16 13:10:14 +0000146 a = regexp.match('^([^:]*): *(.*)', line)
147 if not a:
148 return line
149 name = line[:a[1][1]]
Guido van Rossumbdfcfcc1992-01-01 19:35:13 +0000150 if name[0] == 'N':
Guido van Rossumbefa2931991-12-16 13:10:14 +0000151 name = string.joinfields(string.split(name),'')
152 name = string.lower(name)
Guido van Rossumb00649c1991-12-11 17:29:59 +0000153 name = string.upper(name[0]) + name[1:]
Guido van Rossumbefa2931991-12-16 13:10:14 +0000154 value = line[a[2][0]:]
Guido van Rossumb00649c1991-12-11 17:29:59 +0000155 try:
156 pf = _parse_func[name]
Guido van Rossumb00649c1991-12-11 17:29:59 +0000157 except KeyError:
158 pf = _parse_num
159 value = pf(value)
160 return (name, value)
161
162def _readline(file):
163 line = file.readline()
Guido van Rossumbefa2931991-12-16 13:10:14 +0000164 if not line:
165 raise EOFError
166 return line[:-1]
Guido van Rossumb00649c1991-12-11 17:29:59 +0000167
168def _parse_1_line(file):
Guido van Rossumbefa2931991-12-16 13:10:14 +0000169 line = _readline(file)
Guido van Rossumbdfcfcc1992-01-01 19:35:13 +0000170 while line == '':
Guido van Rossumb00649c1991-12-11 17:29:59 +0000171 line = _readline(file)
172 return _parse_line(line)
173
174def _skip_object(file):
175 line = ''
176 while not line in (SPLITLINE, FORMLINE, ENDLINE):
177 pos = file.tell()
178 line = _readline(file)
Guido van Rossumbdfcfcc1992-01-01 19:35:13 +0000179 if line == FORMLINE:
Guido van Rossumb00649c1991-12-11 17:29:59 +0000180 file.seek(pos)
181
182def _parse_object(file):
183 obj = _newobj().init()
184 while 1:
185 pos = file.tell()
186 datum = _parse_1_line(file)
187 if datum in (SPLITLINE, FORMLINE, ENDLINE):
Guido van Rossumbdfcfcc1992-01-01 19:35:13 +0000188 if datum == FORMLINE:
Guido van Rossumb00649c1991-12-11 17:29:59 +0000189 file.seek(pos)
190 return obj
191 if type(datum) <> type(()):
192 raise error, 'Parse error, illegal line in object: '+datum
193 obj.add(datum)
194
195#################################################################
196# Part 2 - High-level object/form creation routines #
197#################################################################
198
199#
200# External - Create a form an link to an instance variable.
201#
202def create_full_form(inst, (fdata, odatalist)):
203 form = create_form(fdata)
204 exec('inst.'+fdata.Name+' = form\n')
205 for odata in odatalist:
206 create_object_instance(inst, form, odata)
207
208#
209# External - Merge a form into an existing form in an instance
210# variable.
211#
212def merge_full_form(inst, form, (fdata, odatalist)):
213 exec('inst.'+fdata.Name+' = form\n')
214 if odatalist[0].Class <> FL.BOX:
215 raise error, 'merge_full_form() expects FL.BOX as first obj'
216 for odata in odatalist[1:]:
217 create_object_instance(inst, form, odata)
218
219
220#################################################################
221# Part 3 - Low-level object/form creation routines #
222#################################################################
223
224#
225# External Create_form - Create form from parameters
226#
227def create_form(fdata):
228 return fl.make_form(FL.NO_BOX,fdata.Width, fdata.Height)
229
230#
231# External create_object - Create an object. Make sure there are
232# no callbacks. Returns the object created.
233#
234def create_object(form, odata):
235 obj = _create_object(form, odata)
236 if odata.Callback:
237 raise error, 'Creating free object with callback'
238 return obj
239#
240# External create_object_instance - Create object in an instance.
241#
242def create_object_instance(inst, form, odata):
243 obj = _create_object(form, odata)
244 if odata.Callback:
245 cbfunc = eval('inst.'+odata.Callback)
246 obj.set_call_back(cbfunc, odata.Argument)
247 if odata.Name:
248 exec('inst.' + odata.Name + ' = obj\n')
249#
250# Internal _create_object: Create the object and fill options
251#
252def _create_object(form, odata):
253 crfunc = _select_crfunc(form, odata.Class)
254 obj = crfunc(odata.Type, odata.Box[0], odata.Box[1], odata.Box[2], \
255 odata.Box[3], odata.Label)
256 if not odata.Class in (FL.BEGIN_GROUP, FL.END_GROUP):
257 obj.boxtype = odata.Boxtype
258 obj.col1 = odata.Colors[0]
259 obj.col2 = odata.Colors[1]
260 obj.align = odata.Alignment
261 obj.lstyle = odata.Style
262 obj.lsize = odata.Size
263 obj.lcol = odata.Lcol
264 return obj
265#
266# Internal crfunc: helper function that returns correct create function
267#
268def _select_crfunc(fm, cl):
Guido van Rossumbdfcfcc1992-01-01 19:35:13 +0000269 if cl == FL.BEGIN_GROUP: return fm.bgn_group
270 elif cl == FL.END_GROUP: return fm.end_group
271 elif cl == FL.BITMAP: return fm.add_bitmap
272 elif cl == FL.BOX: return fm.add_box
273 elif cl == FL.BROWSER: return fm.add_browser
274 elif cl == FL.BUTTON: return fm.add_button
275 elif cl == FL.CHART: return fm.add_chart
276 elif cl == FL.CHOICE: return fm.add_choice
277 elif cl == FL.CLOCK: return fm.add_clock
278 elif cl == FL.COUNTER: return fm.add_counter
279 elif cl == FL.DIAL: return fm.add_dial
280 elif cl == FL.FREE: return fm.add_free
281 elif cl == FL.INPUT: return fm.add_input
282 elif cl == FL.LIGHTBUTTON: return fm.add_lightbutton
283 elif cl == FL.MENU: return fm.add_menu
284 elif cl == FL.POSITIONER: return fm.add_positioner
285 elif cl == FL.ROUNDBUTTON: return fm.add_roundbutton
286 elif cl == FL.SLIDER: return fm.add_slider
287 elif cl == FL.VALSLIDER: return fm.add_valslider
288 elif cl == FL.TEXT: return fm.add_text
289 elif cl == FL.TIMER: return fm.add_timer
Guido van Rossumb00649c1991-12-11 17:29:59 +0000290 else:
291 raise error, 'Unknown object type: ' + `cl`
292
293
294def test():
295 if len(sys.argv) == 2:
296 forms = parse_forms(sys.argv[1])
297 for i in forms.keys():
298 _printform(forms[i])
299 elif len(sys.argv) == 3:
300 form = parse_form(sys.argv[1], sys.argv[2])
301 _printform(form)
302 else:
303 print 'Usage: test fdfile [form]'
304
305def _printform(form):
306 f = form[0]
307 objs = form[1]
308 print 'Form ', f.Name, ', size: ', f.Width, f.Height, ' Nobj ', f.Numberofobjects
309 for i in objs:
310 print ' Obj ', i.Name, ' type ', i.Class, i.Type
311 print ' Box ', i.Box, ' btype ', i.Boxtype
312 print ' Label ', i.Label, ' size/style/col/align ', i.Size,i.Style, i.Lcol, i.Alignment
313 print ' cols ', i.Colors
314 print ' cback ', i.Callback, i.Argument