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
|
//
// Node base class header file for the Fast Light Tool Kit (FLTK).
//
// Copyright 1998-2025 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
// file is missing or damaged, see the license at:
//
// https://www.fltk.org/COPYING.php
//
// Please see the following page on how to report bugs and issues:
//
// https://www.fltk.org/bugs.php
//
#ifndef FLUID_NODES_NODE_H
#define FLUID_NODES_NODE_H
#include "io/Code_Writer.h"
#include <FL/Fl_Widget.H>
#include <FL/fl_draw.H>
class Node;
class Group_Node;
class Window_Node;
namespace fld {
namespace io {
class Project_Reader;
class Project_Writer;
} // namespace io
} // namespace fld
/**
Declare where a new type is placed and how to create it.
Placement can be as the first or last child of the anchor, or right after the
anchor. In most cases, the anchor is the last selected type node.
If the source is FROM_USER, widgets may be created with default titles and
labels. Type created FROM_FILE will start with no label, so the label is set
correctly later.
\see Node *Fl_..._Type::make(Strategy strategy) calls `add()`
Add single Type:
Node *add_new_widget_from_user(Node *inPrototype, Strategy strategy, bool and_open)
Node *add_new_widget_from_user(const char *inName, Strategy strategy, bool and_open)
Node *add_new_widget_from_file(const char *inName, Strategy strategy)
Add a hierarchy of Types
void Node::add(Node *p, Strategy strategy)
int read_file(const char *filename, int merge, Strategy strategy)
Node *fld::io::Project_Reader::read_children(Node *p, int merge, Strategy strategy, char skip_options)
int fld::io::Project_Reader::read_project(const char *filename, int merge, Strategy strategy)
*/
typedef struct Strategy {
enum Flags {
AS_FIRST_CHILD = 0x0000,
AS_LAST_CHILD = 0x0001,
AFTER_CURRENT = 0x0002,
PLACEMENT_MASK = 0x000f,
FROM_USER = 0x0000,
FROM_FILE = 0x0010,
SOURCE_MASK = 0x00f0,
FROM_FILE_AS_FIRST_CHILD = 0x0010,
FROM_FILE_AS_LAST_CHILD = 0x0011,
FROM_FILE_AFTER_CURRENT = 0x0012,
};
Flags flags;
Strategy(Flags f) { flags = f; }
void placement(Flags f) { flags = (Flags)((flags & ~PLACEMENT_MASK) | (f & PLACEMENT_MASK)); }
Flags placement() { return (Flags)(flags & PLACEMENT_MASK); }
void source(Flags f) { flags = (Flags)((flags & ~SOURCE_MASK) | (f & SOURCE_MASK)); }
Flags source() { return (Flags)(flags & SOURCE_MASK); }
} Strategy;
enum class Type {
// administrative
Base_, Widget_, Menu_Manager_, Menu_, Browser_, Valuator_,
// non-widget
Function, Code, CodeBlock,
Decl, DeclBlock, Class,
Widget_Class, Comment, Data,
// groups
Window, Group, Pack,
Flex, Tabs, Scroll,
Tile, Wizard, Grid,
// buttons
Button, Return_Button, Light_Button,
Check_Button, Repeat_Button, Round_Button,
// valuators
Slider, Scrollbar, Value_Slider,
Adjuster, Counter, Spinner,
Dial, Roller, Value_Input, Value_Output,
// text
Input, Output, Text_Editor,
Text_Display, File_Input, Terminal,
// menus
Menu_Bar, Menu_Button, Choice,
Input_Choice, Submenu, Menu_Item,
Checkbox_Menu_Item, Radio_Menu_Item,
// browsers
Browser, Check_Browser, File_Browser,
Tree, Help_View, Table,
// misc
Box, Clock, Progress,
Max_
};
void update_visibility_flag(Node *p);
void delete_all(int selected_only=0);
int storestring(const char *n, const char * & p, int nostrip=0);
void select_all_cb(Fl_Widget *,void *);
void select_none_cb(Fl_Widget *,void *);
void earlier_cb(Fl_Widget*,void*);
void later_cb(Fl_Widget*,void*);
#ifndef NDEBUG
void print_project_tree();
bool validate_project_tree();
bool validate_independent_branch(class Node *root);
bool validate_branch(class Node *root);
#endif
/**
\brief This is the base class for all elements in the project tree.
All widgets and other types in the project are derived from Fl_Types. They
are organized in a doubly linked list. Every Type also has depth information
to create a pseudo tree structure. To make walking up the tree faster, Type
also holds a pointer to the `parent` Type.
Types can be identified using the builtin Type system that works like RTTI. The
method `type()` returns the exact type, and the method `is_a(Type)` returns true
if this is the exact type or derived from the type, and a dynamic cast will
work reliably.
\todo it would be nice if we can handle multiple independent trees. To do that
we must remove static members like `first` and `last`.
\todo add virtual methods to handle events, draw widgets, and draw overlays.
It may also make sense to have a virtual method that returns a boolean if
a specific type can be added as a child.
\todo it may make sense to have a readable iterator class instead of relying
on pointer manipulation. Or use std in future releases.
*/
class Node {
/** Copy the label text to Widgets and Windows, does nothing in Type. */
virtual void setlabel(const char *) { } // virtual part of label(char*)
protected:
Node();
/** Name of a widget, or code some non-widget Types. */
const char *name_;
/** Label text of a widget. */
const char *label_;
/** If it is just a word, it's the name of the callback function. Otherwise
it is the full callback C++ code. Can be nullptr. */
const char *callback_;
/** Widget user data field as C++ text. */
const char *user_data_;
/** Widget user data type as C++ text, usually `void*` or `long`. */
const char *user_data_type_;
/** Optional comment for every node in the graph. Visible in browser and
panels, and will also be copied to the source code. */
const char *comment_;
/** a unique ID within the project */
unsigned short uid_;
public: // things that should not be public:
// TODO: reference back to the tree
/** Quick link to the parent Type instead of walking up the linked list. */
Node *parent;
/** This type is rendered "selected" in the tree browser. */
char new_selected; // browser highlight
/** Backup storage for selection if an error occurred during some operation
(see `haderror`). It seems that this is often confused with new_selected
which seems to hold the true and visible selection state. */
char selected; // copied here by selection_changed()
char folded_; // if set, children are not shown in browser
char visible; // true if all parents are open
int level; // number of parents over this
Node *next, *prev;
Node *prev_sibling();
Node *next_sibling();
Node *first_child();
Node *factory;
const char *callback_name(fld::io::Code_Writer& f);
// text positions of this type in code, header, and project file (see codeview)
int code_static_start, code_static_end;
int code1_start, code1_end;
int code2_start, code2_end;
int header1_start, header1_end;
int header2_start, header2_end;
int header_static_start, header_static_end;
int proj1_start, proj1_end;
int proj2_start, proj2_end;
protected:
int user_defined(const char* cbname) const;
public:
virtual ~Node();
virtual Node *make(Strategy strategy) = 0;
Window_Node *window();
Group_Node *group();
void add(Node *parent, Strategy strategy);
void insert(Node *n); // insert into list before n
Node* remove(); // remove from list
void move_before(Node*); // move before a sibling
virtual const char *title(); // string for browser
virtual const char *type_name() = 0; // type for code output
virtual const char *alt_type_name() { return type_name(); } // alternate type for FLTK2 code output
const char *name() const {return name_;}
void name(const char *);
const char *label() const {return label_;}
void label(const char *);
const char *callback() const {return callback_;}
void callback(const char *);
const char *user_data() const {return user_data_;}
void user_data(const char *);
const char *user_data_type() const {return user_data_type_;}
void user_data_type(const char *);
const char *comment() { return comment_; }
void comment(const char *);
virtual Node* click_test(int,int) { return nullptr; }
virtual void add_child(Node*, Node* beforethis) { }
virtual void move_child(Node*, Node* beforethis) { }
virtual void remove_child(Node*) { }
/** Give widgets a chance to arrange their children after all children were added.
If adding individual children, this is called immediately, but if children
are read via a project file, we wait until all children are read and then
lay out the group.
*/
virtual void layout_widget() { }
virtual void open(); // what happens when you double-click
// read and write data to a saved file:
virtual void write(fld::io::Project_Writer &f);
virtual void write_properties(fld::io::Project_Writer &f);
virtual void read_property(fld::io::Project_Reader &f, const char *);
virtual void write_parent_properties(fld::io::Project_Writer &f, Node *child, bool encapsulate);
virtual void read_parent_property(fld::io::Project_Reader &f, Node *child, const char *property);
virtual int read_fdesign(const char*, const char*);
virtual void postprocess_read() { }
// write code, these are called in order:
virtual void write_static(fld::io::Code_Writer& f); // write static stuff to .c file
virtual void write_static_after(fld::io::Code_Writer& f); // write static stuff after children
virtual void write_code1(fld::io::Code_Writer& f); // code and .h before children
virtual void write_code2(fld::io::Code_Writer& f); // code and .h after children
void write_comment_h(fld::io::Code_Writer& f, const char *ind=""); // write the commentary text into the header file
void write_comment_c(fld::io::Code_Writer& f, const char *ind=""); // write the commentary text into the source file
void write_comment_inline_c(fld::io::Code_Writer& f, const char *ind=nullptr); // write the commentary text
// live mode
virtual Fl_Widget *enter_live_mode(int top=0); // build widgets needed for live mode
virtual void leave_live_mode(); // free allocated resources
virtual void copy_properties(); // copy properties from this type into a potential live object
virtual void copy_properties_for_children() { } // copy remaining properties after children were added
// get message number for I18N
int msgnum();
/** Return 1 if the Type can have children. */
virtual int can_have_children() const {return 0;}
/** Return 1 if the type is a widget or menu item. */
virtual int is_widget() const {return 0;}
/** Return 1 if the type is a widget but not a menu item. */
virtual int is_true_widget() const {return 0;}
/** Return 1 if a type behaves like a button (Fl_Button and Fl_Menu_Item and derived, but not Submenu_Node. */
virtual int is_button() const {return 0;}
/** Return 1 if this is a Widget_Class_Node, CodeBlock_Node, or Function_Node */
virtual int is_code_block() const {return 0;}
/** Return 1 if this is a Widget_Class_Node, Class_Node, or DeclBlock_Node */
virtual int is_decl_block() const {return 0;}
/** Return 1 if this is a Class_Node or Widget_Class_Node. */
virtual int is_class() const {return 0;}
/** Return 1 if the type browser shall draw a padlock over the icon. */
virtual int is_public() const {return 1;}
/** Return the type Type for this Type. */
virtual Type type() const { return Type::Base_; }
/** Check if this Type is of the give type Type or derived from that type Type. */
virtual bool is_a(Type inType) const { return (inType==Type::Base_); }
const char* class_name(const int need_nest) const;
bool is_in_class() const;
int has_function(const char*, const char*) const;
unsigned short set_uid(unsigned short suggested_uid=0);
unsigned short get_uid() { return uid_; }
};
#endif // FLUID_NODES_NODE_H
|