summaryrefslogtreecommitdiff
path: root/fluid/README_fl.txt
blob: 1a824b1e2392db3f950a781f9bf38f9da94459d0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538

FLUID .fl file format version 1.4
=================================

This text explains the history of the FLUID .fl format and faithfully describes
all elements of the format and its caveats.


History
-------

FLUID, the Fast Light User Interface Designer was started in the 1990's loosely
based on 'fdesign', a GUI designer that came with the 'Forms Library', later
'XForms Library'. FLUID's .fl file format was originally compatible with the
fdesign '.fd' format, but evolved somewhat ad hoc to become what it is today.


Basics
======

FLUID is a visual editor, storing the user interface description in .fl files
with the ability to create ready-to-compile C++ code. FLUID can also be used
as a command line tool to translate .fl files directly into source code. It
can be integrated into build scripts and most IDEs as an external tool.

.fl files describe a hierarchical graphical user interface for the 'FLTK'
library as a tree structure. Elements in the tree can be FLTK Widgets as well
as functional components like classes, C++ functions, variables, etc. .
FLUID calls all elements in the hierarchy 'Type'.


Line Endings
------------

Although FLUID writes all line endings as '\n', readers should tolerate '\r\n'
MSWindows line endings as well. Except for the Header, the FLUID reader does not
differentiate between a line ending and a space character outside of a 'word'.


Unicode
-------

FLUID does not handle UTF-8 characters in any special manner (unescaped),
but stores and reads them verbatim, making UTF-8 character sequences perfectly
legal in .fl files. FLUID can translate UTF-8 into escape sequence when writing
source code files.


File Structure
--------------

.fl files start with a 'Header', followed by a list of 'Options', followed
by a hierarchy of 'Type' entries, the 'Tree'. All elements besides the Header
are composed of 'Words', 'Strings', and 'Groups'.


Words
-----

Words can be any sequence of ASCII and UTF-8 characters. Words are always
case-sensitive.

Simple Words that are composed of 'a'-'z', 'A'-'Z', '0'-'9', and '_' only are
written verbatim, followed by a space or newline.

All other character sequences are bracketed between between ‘{‘ and ‘}’ without
padding spaces. For example, an empty word with no characters is written
as '{}', and ".hello" is written as '{.hello}'.

The special characters ‘\’ and ‘#’ are escaped by prepending the ‘\’ character,
so "#define" is written as '{\#define}`.

The characters ‘{‘ and ‘}’ are also escaped with a '\' unless every opening
‘{‘ in the Word is matched with a closing ‘}’.

Note: line endings and the following indents are copied verbatim and become
      significant within a Word.


Strings
-------

Strings are generated with 'printf' statements in the hope that the
generated text can be read back as one Word, set against a corresponding
'scanf' to retrieve the original values.

Note: As there are no defined start and end markers to a String, a reader must
      know when these Strings appear and be prepared to read them correctly,
      even if the String itself is not useful to the reader.

Note: All Strings that are generated by the current FLUID source code
      can be read back as a single Word.


Groups
------

To create a hierarchy, Types can be grouped within Types. A Group starts with
a lone '{' and ends with a lone '}'.

Note: To know whether a '{' character starts a Word or a Group, the reader must
      know its position within the Type sequence (see 'Types' below).


Elements
========


Header
------

The Header for any .fl file is

  # data file for the Fltk User Interface Designer (fluid)

followed by a newline, followed by

  version <float v>

wehere 'v' is the version number as in FL_VERSION (major*1.0 + minor * 0.01
+ patch * 0.0001). So for FLTK 1.3.4, 'v' would be 1.0304

Note: the version number corresponds not so much to the version of FLUID, but
      to the version of the underlying FLTK library. So unless the version of
      FLTK is finalised, the file format in the GitHub master branch can still
      change unexpectedly.

Note: if the version number is above the internal version number, FLUID will
      report an error and continue reading, hoping for the best.
      There are no other uses inside the FLUID reader except for features for
      the discontinued fltk2 which is beyond the scope of this document.

Note: fdesign files (.fd) start with the text "Magic:". FLUID can read these
      files, but Forms/XForms files are beyond the scope of this document.


Options
-------

Options are usually comprised of a Word, two Words, or a Word and a String. If
an Option is missing, a default value is assumed.

  "Magic:" : used by fdesign, not written by FLUID

  "define_in_struct" : no longer used

  "do_not_include_H_from_C" : don’t generate #include “myDesign.h”

  "use_FL_COMMAND" : use macOS CMD key instead of Ctrl

  "utf8_in_src" : allow UTF-8 when writing source code, otherwise
      escape UTF-8 sequences in source code

  "avoid_early_includes" : generate the '#include <FL/Fl.H>' statement late

  "i18n_type" <word> : integer 0=default=none, 1=gettext, 2=catgets

--- the following list is valid until June 2023

  "i18n_function" <word> : function name, e.g. “gettext”

  "i18n_static_function" <word> : function name, e.g. “gettext_noop”

  "i18n_file" <word> : file name

  "i18n_set" <word> : string

--- the following list is valid from June 2023

  "i18n_gnu_function" <word> : function name, e.g. “gettext”

  "i18n_gnu_static_function" <word> : function name, e.g. “gettext_noop”

  "i18n_pos_file" <word> : file name

  "i18n_pos_set" <word> : string

--- end of June 2023 changes

  "i18n_include" <word> : file name, e.g. “<libintl.h>”

  "i18n_conditional" <word> : string

  "header_name" <word> : can be the full filename, or just the
      extension e.g. “.h” in which case FLUID will use the same filename
      as the .fl file.

  "code_name" <word> : can be the full filename, or just the
      extension e.g. “.cxx”

  "snap" <word> : starting in V1.4 from May 2023, the 'snap' keyword can be
      used to store the selected layout and preset and include more suites
      of presets. The following block can be skipped by reading it as a
      single word. The format looks like this:

      snap {                         optional snap Word since 5.2023
        ver 1                        version of following data
        current_suite {My Test}      opt. name of suite selected at save time
        current_preset 1             opt. preset selected within suite
        suite {                      optional suite store within project
          name {MyLayout v0.3}       name of the layout
          preset { 1                 3x preset, preset version
            (24 integers)            values representing the layout preset
          }
          ...                        (two more presets)
        }
        ...                          (opt. more suites)
      }

  "gridx" <word> : ignored

  "gridy" <word> : ignored

  "shell_commands" <word> : starting in V1.4 from Sep 2023, the 'shell_commands'
      keyword can be used to store user configurable shell commands in a
      project file. The following block can be skipped by reading it as a
      single word.

      shell_commands {
        command {
          name <string>
          label <string>
          shortcut <int>            (optional if not 0)
          condition <int>         (optional if not 0, see Fd_Shell_Command enum)
          condition_data <string>   (optional if not "")
          command <string>          (optional, but usually there)
          flags <int>         (optional if not 0, see Fd_Shell_Command 2nd enum)
        }                           ( repeat as needed)
      }

Note: There is no keyword that marks the end of the Options section. The
      Option list ends when a Word is not in the Options list and it is in
      the list of known Types.

      If the Word is neither an Option nor a vaild Type, FLUID will give an
      error message and try to continue to read the file. Using new Option
      keywords makes .fl files incompatible to earlier versions of FLUID.
      Due to the forgiving interpreter, files may still be read correctly
      despite error messages.

      If a Word is in the list of known Types, the Type is read, including
      optional children. No more Options are allowed beyond this point.


Tree
====

If a keyword is read that is not in the Option list, we start reading Types.
Types represent all possible entries in the hierarchy including C functions,
class definitions, and of course all Widgets. A Type is any of the supported
Widgets classes, or one of the following (case sensitive):

Function, code, codeblock, decl, data, declblock, comment, class, widget_class

Every Type keyword is followed by a Word, which is usually interpreted as the
C++ name of the Type, followed by an opening `{`, a list of properties, and
a closing ‘}’. If the Type has children, they are stored in a Group between
another opening ‘{‘, followed by a list of Types, followed by a closing ‘}’.

  Fl_Group MyGroup {                    Type name start_of_options
    label Surprise ...                    Option parameter
  } {                                   end_of_options start_of_children
    Fl_Button {} {                        Type name start_of_options
      label {Don't panic...!}               Option parameter
      hide                                  Option
    }                                     end_of_options
  }                                     end_of_children

The file ends when there are no more Types.

Note: the "class" Type may have an additional Word following immediately after
      the keyword. It contains the prefix for the class. A class definition may
      be written as:

        class FL_EXPORT MyClass { ...properties... } { ...children... }

      or without a prefix as

        class MyOtherClass { ...properties... } { ...children... }

      According to the source code, we know if the word after class is a prefix
      if the next word is not a lone '{'. We apologize for the inconvenience.


Types
-----

Type names are based on FLTK class names. Types derive properties from super
Types loosely similar to FLTK.

Note: the hierarchical dependency is implemented twice and somewhat conflicting
      in FLUID via the Fl_..._Type hierarchy, and by using '::is_some_type()'
      virtual functions, which does not always match the Type hierarchy.


The list of known Types and their inheritance is:

  Fl_Type (note: can't be written)
   +-- Function
   +-- code
   +-- codeblock
   +-- decl
   +-- data
   +-- declblock
   +-- comment
   +-- class
   +-- Fl_Widget (note: can't be written)
   |    +-- Fl_Window
   |    |    +-- widget_class
   |    +-- Fl_Group
   |    |    +-- Fl_Pack
   |    |    +-- Fl_Flex
   |    |    +-- Fl_Table
   |    |    +-- Fl_Tabs
   |    |    +-- Fl_Scroll
   |    |    +-- Fl_Terminal
   |    |    +-- Fl_Tile
   |    |    +-- Fl_Wizard
   |    |    +-- Fl_Grid
   |    +-- Fl_Menu_Type (note: can't be written)
   |    |    +-- Fl_Menu_Button
   |    |    +-- Fl_Choice
   |    |    +-- Fl_Input_Choice
   |    |    +-- Fl_Menu_Bar
   |    |    +-- Fl_
   |    +-- Fl_Box
   |    +-- Fl_Button
   |    |    +-- Fl_Return_Button
   |    |    +-- Fl_Light_Button
   |    |    +-- Fl_Check_Button
   |    |    +-- Fl_Round_Button
   |    +-- Fl_Repeat_Button
   |    +-- Fl_Browser
   |    +-- Fl_Check_Browser
   |    +-- Fl_Tree
   |    +-- Fl_File_Browser
   |    +-- Fl_Counter
   |    +-- Fl_Spinner
   |    +-- Fl_Input
   |    |    +-- Fl_Output
   |    +-- Fl_File_Input
   |    +-- Fl_Text_Display
   |    +-- Fl_Text_Editor
   |    +-- Fl_Clock
   |    +-- Fl_Help_View
   |    +-- Fl_Progress
   |    +-- Fl_Adjuster
   |    +-- Fl_Dial
   |    +-- Fl_Roller
   |    +-- Fl_Slider
   |    |    +-- Fl_Scrollbar
   |    |    +-- Fl_Value_Slider
   |    +-- Fl_Value_Input
   |    +-- Fl_Value_Output
   .


Properties
----------

Properties have zero or one Words as their arguments. The number of arguments
are defined per property per Type. The content of the argument Word is defined
by the implementation of the property and can contain mutiple values, as
described above in Strings.

Properties are inherited from super Types. They can be limited to certain Types
by calls to 'MyType->is_some_type()'. All properties are optional, some are
mutually exclusive.

Note: It is possible that the same property by name has different arguments
      when used in a different Type.

Every node can have properties that it holds for its parent. Parent properties
are stored as "parent_properties { ...list... }". If a node encounters this
property tag, it must ask its parent to interpret the contents of that list.
See Fl_Grid for an example.

Type Fl_Type <word>

  "uid" <4-digit-hex> : since Oct 2023, optional, a unique id for this node
      within the project file
  “label” <word> : text
  “user_data” <word> : a value or an expression
  “user_data_type” <word> : usually “void*” or “long”
  “callback” <word> : a function name or a function body
  “comment” <word> : one or many lines of text
  “open” : Group content visible in the FLUID tree browser
  “selected” : Type was selected in tree view

Type "Function" <word> : function signature

  none or "private" or "protected" : for methods in classes, or to mark
      functions static in a file, default is public
  “C” : if set, function is extern “C”
  “return_type” <word> : C or C++ type descriptor, can start with “virtual”
      and/or “static” to further define the function.
  ... : inherits more from Fl_Type

Type codeblock <word> : C++ code, for example "if (test())"

  "after" <word> : C++ code or comment following the closing '}'
  ... : inherits more from Fl_Type

Type "decl" <word> : C++ code to declare a variable or class member

  none or "public" or "private" or "protected" : for declarations within classes
      defaults to "private"
  none or "local" or "global": for declaration in the code body
      defaults to "global"
  ... : inherits more from Fl_Type

Type "data" <word> : C++ variable name

  "filename" <word> : name or path as entered by user, forward slashes
  "textmode" : defaults to binary mode
  "compressed" : defaults to not compressed
  ... : inherits more from decl

Type "declblock" <word> : C++ code

  none or "public" or "protected" : defaults to private
  "after" <word> : C++ code or comment following the block
  ... : inherits more from Fl_Type

Type "comment" <word> : comment text

  "in_source" or "not_in_source": default to in_source
  "in_header" or "not_in_header": default to in_header
  ... : inherits more from Fl_Type

Type "class" <word> <word> : prefix, class name

  none or "private" or "protected" : defaults to public
  ":" <word> : name of super class
  ... : inherits more from Fl_Type

Type "Fl_Widget" <word> : C++ variable name

  none or "private" or "protected" : default is public
  "xywh" <word> : "{%d %d %d %d}" x, y, w, h
  "tooltip" <word> : tooltip text
  "image" <word> : image name
  "compress_image" <word> : integer (1.4 and up, only if `image` is set)
  "bind_image" <word> : integer (1.4 and up)
  "deimage" <word> : deactivated image name
  "compress_deimage" <word> : integer (1.4 and up, only if `deimage` is set)
  "bind_deimage" <word> : integer (1.4 and up)
  "type" <word> : integer
  "box" <word> : text or integer (see FLTK boxtypes)
  "down_box" <word> : (is_button() or Fl_Input_choice" or is_menu_button())
      text or integer (see FLTK boxtypes)
  "value" <word> : (is_button()) integer
  "value" <word> : (is_valuator(), is_spinner()) double
  "color" <word> :
      If Word starts with "0x", the rest of the field is a hex number.
      If two integers follow, this is color and selection_color (deprecated).
      If one integer follows, it's the color index.
  "selection_color" <word> : integer color index
  "labeltype" <word> :
      If the Word is "image", TBD.
      Or one of "NORMAL_LABEL", "SHADOW_LABEL", "ENGRAVED_LABEL",
      "EMBOSSED_LABEL", or "NO_LABEL"
  "labelfont" <word> : integer, font index
  "labelsize" <word> : integer
  "labelcolor" <word> : integer, color index
  "align" <word> : integer, see Fl_Align
  "when" <word> : integer, see Fl_When
  "minimum" <word> : (is_valuator(), is_spinner()) double
  "maximum" <word> : (is_valuator(), is_spinner()) double
  "step" <word> : (is_valuator(), is_spinner()) double
  "slider_size" <word> : (is_valuator()==2) double
  "size" <word> : (is_valuator()==2) double
  "textfont" <word> : integer, font index
  "textsize" <word> : integer
  "textcolor" <word> : integer, color index
  "hide" : default visible
  "deactivate" : default active
  "resizable" : default fixed
  "hotspot" : make a Widget a hotspot
  "divider" : add a divider under a menu item
  "class" <word> : superclass
  "shortcut" <word> : integer
  "code0" or "code1" or "code2" or "code3" <word> : C++ extra code lines
  "extra_code" <word> : C++ extra code lines
  ... : inherits more from Fl_Type

Type "Fl_Button" <word> : C++ variable name

  "compact" <word> : integer, set the flag for compact buttons, defaults to 0

Type "Fl_Flex" <word> : C++ variable name

  "margins" <word> : this Word is written with printf as "{%d %d %d %d}",
      left, top, right, bottom
  "gap" <word> : integer
  "fixed_size_tuples" <word> : this Word is written with printf "{%d", where %d
      encodes the number of tuples to follow, and zero or more " %d %d"
      containing the index and size of that child, followed by a '}'.
  ... : inherits more from Fl_Group

Type "Fl_Window" <word> : C++ variable name

  none or "modal", or "non_modal": defaults to not modal (which is
      different to non_modal!)
  "visible" : show window when opening file in FLUID
  "noborder" : borderless window
  "xclass" <word> : see FLTK
  "size_range" : this Word is written with printf as "{%d %d %d %d}",
      min_w, min_h, max_w, max_h
  "xywh" <word> : this Word is written with printf as "{%d %d %d %d}",
      x, y, w, h. This as actually read in the Fl_Widget Type, but here
      it ensures that window is not created as a subwindow.
  ... : inherits more from Fl_Widget (not Fl_Group)

Type "Fl_Grid" <word> : C++ variable name

  "dimensions" <word> : {int rows, int cols}
  "margin" <word> : {int left, int top, int right, int bottom}
  "gap" <word> : {int row gap, int col gap}
  "rowheights" <word> : {int h, ...*rows}
  "rowweights" <word> : {int h, ...*rows}
  "rowgaps" <word> : {int h, ...*rows}
  "colwidths" <word> : {int h, ...*cols}
  "colweights" <word> : {int h, ...*cols}
  "colgaps" <word> : {int h, ...*cols}

  Fl_Grid can also produce parent properties in their children

  "location" <word> : {int row, int col}
  "colspan" <int>"
  "rowspan" <int>
  "align" <int> : see Fl_Grid_Align enum
  "min_size" <word> : {int width, int height}

Please report errors and omissions to the fltk.coredev or fltk.general
Google group. Thank you.

 - Matthias