diff options
| author | Michael R Sweet <michael.r.sweet@gmail.com> | 1998-10-06 18:21:25 +0000 |
|---|---|---|
| committer | Michael R Sweet <michael.r.sweet@gmail.com> | 1998-10-06 18:21:25 +0000 |
| commit | f9039b2ae21988783feae9b362818e7923e82d14 (patch) | |
| tree | 6d6fe3679d73448758f9794e7d4d4f6b22a4adad /fluid | |
| parent | 67e89232f9ba067825a158734a09e0fa21aacbe3 (diff) | |
Initial revision
git-svn-id: file:///fltk/svn/fltk/trunk@2 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'fluid')
37 files changed, 9836 insertions, 0 deletions
diff --git a/fluid/Fl_Function_Type.cxx b/fluid/Fl_Function_Type.cxx new file mode 100644 index 000000000..21bdb5b37 --- /dev/null +++ b/fluid/Fl_Function_Type.cxx @@ -0,0 +1,669 @@ +/* Fl_Function_Type_Type.C + + Type describing a C function output by Fluid. + +*/ + +#include <FL/Fl.H> +#include "Fl_Type.H" +#include <FL/fl_show_input.H> +#include <string.h> +#include <stdio.h> +#include <ctype.h> + +//////////////////////////////////////////////////////////////// +// quick check of any C code for legality, returns an error message +// these currently require comments to parse correctly! + +static char buffer[128]; // for error messages + +// check a quoted string ending in either " or ' or >: +const char *_q_check(const char * & c, int type) { + for (;;) switch (*c++) { + case '\0': + sprintf(buffer,"missing %c",type); + return buffer; + case '\\': + if (*c) c++; + break; + default: + if (*(c-1) == type) return 0; + } +} + +// check normal code, match braces and parenthesis: +const char *_c_check(const char * & c, int type) { + const char *d; + for (;;) switch (*c++) { + case 0: + if (!type) return 0; + sprintf(buffer, "missing %c", type); + return buffer; + case '{': + if (type==')') goto UNEXPECTED; + d = _c_check(c,'}'); if (d) return d; break; + case '(': + d = _c_check(c,')'); if (d) return d; break; + case '\"': + d = _q_check(c,'\"'); if (d) return d; break; + case '\'': + d = _q_check(c,'\''); if (d) return d; break; + case '}': + case ')': + case '#': + UNEXPECTED: + if (type == *(c-1)) return 0; + sprintf(buffer, "unexpected %c", *(c-1)); + return buffer; + } +} + +const char *c_check(const char *c, int type) { + return _c_check(c,type); +} + +//////////////////////////////////////////////////////////////// + +class Fl_Function_Type : public Fl_Type { + const char* return_type; + char public_, constructor, havewidgets; +public: + Fl_Type *make(); + void write_declare(); + void write_code1(); + void write_code2(); + void open(); + int ismain() {return name_ == 0;} + virtual const char *type_name() {return "Function";} + virtual const char *title() { + return name() ? name() : "main()"; + } + int is_parent() const {return 1;} + int is_code_block() const {return 1;} + void write_properties(); + void read_property(const char *); +}; + +Fl_Type *Fl_Function_Type::make() { + Fl_Type *p = Fl_Type::current; + while (p && !p->is_decl_block()) p = p->parent; + Fl_Function_Type *o = new Fl_Function_Type(); + o->name("make_window()"); + o->return_type = 0; + o->add(p); + o->factory = this; + o->public_ = 1; + return o; +} + +void Fl_Function_Type::write_properties() { + Fl_Type::write_properties(); + if (!public_) write_string("private"); + if (return_type) { + write_string("return_type"); + write_word(return_type); + } +} + +void Fl_Function_Type::read_property(const char *c) { + if (!strcmp(c,"private")) { + public_ = 0; + } else if (!strcmp(c,"return_type")) { + storestring(read_word(),return_type); + } else { + Fl_Type::read_property(c); + } +} + +#include "function_panel.H" +#include <FL/fl_ask.H> + +void Fl_Function_Type::open() { + if (!function_panel) make_function_panel(); + f_return_type_input->static_value(return_type); + f_name_input->static_value(name()); + f_public_button->value(public_); + function_panel->show(); + const char* message = 0; + for (;;) { // repeat as long as there are errors + if (message) fl_alert(message); + for (;;) { + Fl_Widget* w = Fl::readqueue(); + if (w == f_panel_cancel) goto BREAK2; + else if (w == f_panel_ok) break; + else if (!w) Fl::wait(); + } + const char*c = f_name_input->value(); + while (isspace(*c)) c++; + message = c_check(c); if (message) continue; + const char *d = c; + for (; *d != '('; d++) if (isspace(*d) || !*d) break; + if (*c && *d != '(') { + message = "must be name(arguments), try again:"; continue; + } + c = f_return_type_input->value(); + message = c_check(c); if (message) continue; + name(f_name_input->value()); + storestring(c, return_type); + public_ = f_public_button->value(); + break; + } + BREAK2: + function_panel->hide(); +} + +Fl_Function_Type Fl_Function_type; + +void Fl_Function_Type::write_declare() { + ::write_declare("#include <FL/Fl.H>"); +} + +extern const char* subclassname(Fl_Type*); + +void Fl_Function_Type::write_code1() { + constructor=0; + havewidgets = 0; + Fl_Type *child; + const char* widget_type = 0; + for (child = next; child && child->level > level; child = child->next) + if (child->is_widget()) { + havewidgets = 1; + widget_type = subclassname(child); + break; + } + write_c("\n"); + if (ismain()) + write_c("int main(int argc, char **argv) {\n"); + else { + const char* t = return_type; + const char* star = ""; + if (!t) { + if (havewidgets) {t = widget_type; star = "*";} + else t = "void"; + } + const char* k = class_name(); + if (k) { + write_public(public_); + if (name()[0] == '~') + constructor = 1; + else { + size_t n; for (n=0; name()[n] && name()[n]!='('; n++); + if (n == strlen(k) && !strncmp(name(), k, n)) constructor = 1; + } + write_h(" "); + if (!constructor) {write_h("%s%s ", t, star); write_c("%s%s ", t,star);} + write_h("%s;\n", name()); + write_c("%s::%s {\n", k, name()); + } else { + if (public_) write_h("%s%s %s;\n", t, star, name()); + else write_c("static "); + write_c("%s%s %s {\n", t, star, name()); + } + } + if (havewidgets) write_c(" %s* w;\n", widget_type); + indentation += 2; +} + +void Fl_Function_Type::write_code2() { + if (ismain()) { + if (havewidgets) write_c(" w->show(argc, argv);\n"); + write_c(" return Fl::run();\n"); + } else if (havewidgets && !constructor) + write_c(" return w;\n"); + write_c("}\n"); + indentation = 0; +} + +//////////////////////////////////////////////////////////////// + +class Fl_Code_Type : public Fl_Type { +public: + Fl_Type *make(); + void write_declare(); + void write_code1(); + void write_code2(); + void open(); + virtual const char *type_name() {return "code";} + int is_code_block() const {return 0;} +}; + +Fl_Type *Fl_Code_Type::make() { + Fl_Type *p = Fl_Type::current; + while (p && !p->is_code_block()) p = p->parent; + if (!p) { + fl_message("Please select a function"); + return 0; + } + Fl_Code_Type *o = new Fl_Code_Type(); + o->name("printf(\"Hello, World!\\n\");"); + o->add(p); + o->factory = this; + return o; +} + +void Fl_Code_Type::open() { + if (!code_panel) make_code_panel(); + code_input->static_value(name()); + code_panel->show(); + const char* message = 0; + for (;;) { // repeat as long as there are errors + if (message) fl_alert(message); + for (;;) { + Fl_Widget* w = Fl::readqueue(); + if (w == code_panel_cancel) goto BREAK2; + else if (w == code_panel_ok) break; + else if (!w) Fl::wait(); + } + const char*c = code_input->value(); + message = c_check(c); if (message) continue; + name(c); + break; + } + BREAK2: + code_panel->hide(); +} + +Fl_Code_Type Fl_Code_type; + +void Fl_Code_Type::write_declare() {} + +void Fl_Code_Type::write_code1() { + const char* c = name(); + if (!c) return; + write_c("%s%s\n", indent(), c); +} + +void Fl_Code_Type::write_code2() {} + +//////////////////////////////////////////////////////////////// + +class Fl_CodeBlock_Type : public Fl_Type { + const char* after; +public: + Fl_Type *make(); + void write_declare(); + void write_code1(); + void write_code2(); + void open(); + virtual const char *type_name() {return "codeblock";} + int is_code_block() const {return 1;} + int is_parent() const {return 1;} + void write_properties(); + void read_property(const char *); +}; + +Fl_Type *Fl_CodeBlock_Type::make() { + Fl_Type *p = Fl_Type::current; + while (p && !p->is_code_block()) p = p->parent; + if (!p) { + fl_message("Please select a function"); + return 0; + } + Fl_CodeBlock_Type *o = new Fl_CodeBlock_Type(); + o->name("if (test())"); + o->after = 0; + o->add(p); + o->factory = this; + return o; +} + +void Fl_CodeBlock_Type::write_properties() { + Fl_Type::write_properties(); + if (after) { + write_string("after"); + write_word(after); + } +} + +void Fl_CodeBlock_Type::read_property(const char *c) { + if (!strcmp(c,"after")) { + storestring(read_word(),after); + } else { + Fl_Type::read_property(c); + } +} + +void Fl_CodeBlock_Type::open() { + if (!codeblock_panel) make_codeblock_panel(); + code_before_input->static_value(name()); + code_after_input->static_value(after); + codeblock_panel->show(); + const char* message = 0; + for (;;) { // repeat as long as there are errors + if (message) fl_alert(message); + for (;;) { + Fl_Widget* w = Fl::readqueue(); + if (w == codeblock_panel_cancel) goto BREAK2; + else if (w == codeblock_panel_ok) break; + else if (!w) Fl::wait(); + } + const char*c = code_before_input->value(); + message = c_check(c); if (message) continue; + name(c); + c = code_after_input->value(); + message = c_check(c); if (message) continue; + storestring(c, after); + break; + } + BREAK2: + codeblock_panel->hide(); +} + +Fl_CodeBlock_Type Fl_CodeBlock_type; + +void Fl_CodeBlock_Type::write_declare() {} + +void Fl_CodeBlock_Type::write_code1() { + const char* c = name(); + write_c("%s%s {\n", indent(), c ? c : ""); + indentation += 2; +} + +void Fl_CodeBlock_Type::write_code2() { + indentation += 2; + if (after) write_c("%s} %s\n", indent(), after); + else write_c("%s}\n", indent()); +} + +//////////////////////////////////////////////////////////////// + +class Fl_Decl_Type : public Fl_Type { + char public_; +public: + Fl_Type *make(); + void write_declare(); + void write_code1(); + void write_code2(); + void open(); + virtual const char *type_name() {return "decl";} + void write_properties(); + void read_property(const char *); +}; + +Fl_Type *Fl_Decl_Type::make() { + Fl_Type *p = Fl_Type::current; + while (p && !p->is_decl_block()) p = p->parent; + Fl_Decl_Type *o = new Fl_Decl_Type(); + o->public_ = 0; + o->name("int x;"); + o->add(p); + o->factory = this; + return o; +} + +void Fl_Decl_Type::write_properties() { + Fl_Type::write_properties(); + if (public_) write_string("public"); +} + +void Fl_Decl_Type::read_property(const char *c) { + if (!strcmp(c,"public")) { + public_ = 1; + } else { + Fl_Type::read_property(c); + } +} + +void Fl_Decl_Type::open() { + if (!decl_panel) make_decl_panel(); + decl_input->static_value(name()); + decl_public_button->value(public_); + decl_panel->show(); + const char* message = 0; + for (;;) { // repeat as long as there are errors + if (message) fl_alert(message); + for (;;) { + Fl_Widget* w = Fl::readqueue(); + if (w == decl_panel_cancel) goto BREAK2; + else if (w == decl_panel_ok) break; + else if (!w) Fl::wait(); + } + const char*c = decl_input->value(); + while (isspace(*c)) c++; + message = c_check(c&&c[0]=='#' ? c+1 : c); + if (message) continue; + name(c); + public_ = decl_public_button->value(); + break; + } + BREAK2: + decl_panel->hide(); +} + +Fl_Decl_Type Fl_Decl_type; + +void Fl_Decl_Type::write_declare() {} + +void Fl_Decl_Type::write_code1() { + const char* c = name(); + if (!c) return; + // handle putting #include or extern into decl: + if (!isalpha(*c) || !strncmp(c,"extern",6)) { + if (public_) + write_h("%s\n", c); + else + write_c("%s\n", c); + return; + } + // lose all trailing semicolons so I can add one: + const char* e = c+strlen(c); + while (e>c && e[-1]==';') e--; + if (class_name()) { + write_public(public_); + write_h(" %.*s;\n", e-c, c); + } else { + if (public_) { + write_h("extern %.*s;\n", e-c, c); + write_c("%.*s;\n", e-c, c); + } else { + write_c("static %.*s;\n", e-c, c); + } + } +} + +void Fl_Decl_Type::write_code2() {} + +//////////////////////////////////////////////////////////////// + +class Fl_DeclBlock_Type : public Fl_Type { + const char* after; +public: + Fl_Type *make(); + void write_declare(); + void write_code1(); + void write_code2(); + void open(); + virtual const char *type_name() {return "declblock";} + void write_properties(); + void read_property(const char *); + int is_parent() const {return 1;} + int is_decl_block() const {return 1;} +}; + +Fl_Type *Fl_DeclBlock_Type::make() { + Fl_Type *p = Fl_Type::current; + while (p && !p->is_decl_block()) p = p->parent; + Fl_DeclBlock_Type *o = new Fl_DeclBlock_Type(); + o->name("#if 1"); + o->after = strdup("#endif"); + o->add(p); + o->factory = this; + return o; +} + +void Fl_DeclBlock_Type::write_properties() { + Fl_Type::write_properties(); + write_string("after"); + write_word(after); +} + +void Fl_DeclBlock_Type::read_property(const char *c) { + if (!strcmp(c,"after")) { + storestring(read_word(),after); + } else { + Fl_Type::read_property(c); + } +} + +void Fl_DeclBlock_Type::open() { + if (!declblock_panel) make_declblock_panel(); + decl_before_input->static_value(name()); + decl_after_input->static_value(after); + declblock_panel->show(); + const char* message = 0; + for (;;) { // repeat as long as there are errors + if (message) fl_alert(message); + for (;;) { + Fl_Widget* w = Fl::readqueue(); + if (w == declblock_panel_cancel) goto BREAK2; + else if (w == declblock_panel_ok) break; + else if (!w) Fl::wait(); + } + const char*c = decl_before_input->value(); + while (isspace(*c)) c++; + message = c_check(c&&c[0]=='#' ? c+1 : c); + if (message) continue; + name(c); + c = decl_after_input->value(); + while (isspace(*c)) c++; + message = c_check(c&&c[0]=='#' ? c+1 : c); + if (message) continue; + storestring(c,after); + break; + } + BREAK2: + declblock_panel->hide(); +} + +Fl_DeclBlock_Type Fl_DeclBlock_type; + +void Fl_DeclBlock_Type::write_declare() {} + +void Fl_DeclBlock_Type::write_code1() { + const char* c = name(); + if (c) write_c("%s\n", c); +} + +void Fl_DeclBlock_Type::write_code2() { + const char* c = after; + if (c) write_c("%s\n", c); +} + +//////////////////////////////////////////////////////////////// + +class Fl_Class_Type : public Fl_Type { + const char* subclass_of; + char public_; +public: + // state variables for output: + char write_public_state; // true when public: has been printed + Fl_Class_Type* parent_class; // save class if nested +// + Fl_Type *make(); + void write_declare(); + void write_code1(); + void write_code2(); + void open(); + virtual const char *type_name() {return "class";} + int is_parent() const {return 1;} + int is_decl_block() const {return 1;} + int is_class() const {return 1;} + void write_properties(); + void read_property(const char *); +}; + +const char* Fl_Type::class_name() const { + Fl_Type* p = parent; + while (p) {if (p->is_class()) return p->name(); p = p->parent;} + return 0; +} + +Fl_Type *Fl_Class_Type::make() { + Fl_Type *p = Fl_Type::current; + while (p && !p->is_decl_block()) p = p->parent; + Fl_Class_Type *o = new Fl_Class_Type(); + o->name("UserInterface"); + o->subclass_of = 0; + o->public_ = 1; + o->add(p); + o->factory = this; + return o; +} + +void Fl_Class_Type::write_properties() { + Fl_Type::write_properties(); + if (subclass_of) { + write_string(":"); + write_word(subclass_of); + } + if (!public_) write_string("private"); +} + +void Fl_Class_Type::read_property(const char *c) { + if (!strcmp(c,"private")) { + public_ = 0; + } else if (!strcmp(c,":")) { + storestring(read_word(), subclass_of); + } else { + Fl_Type::read_property(c); + } +} + +void Fl_Class_Type::open() { + if (!class_panel) make_class_panel(); + c_name_input->static_value(name()); + c_subclass_input->static_value(subclass_of); + c_public_button->value(public_); + class_panel->show(); + const char* message = 0; + for (;;) { // repeat as long as there are errors + if (message) fl_alert(message); + for (;;) { + Fl_Widget* w = Fl::readqueue(); + if (w == c_panel_cancel) goto BREAK2; + else if (w == c_panel_ok) break; + else if (!w) Fl::wait(); + } + const char*c = c_name_input->value(); + while (isspace(*c)) c++; + if (!*c) goto OOPS; + while (is_id(*c)) c++; + while (isspace(*c)) c++; + if (*c) {OOPS: message = "class name must be C++ identifier"; continue;} + c = c_subclass_input->value(); + message = c_check(c); if (message) continue; + name(c_name_input->value()); + storestring(c, subclass_of); + public_ = c_public_button->value(); + break; + } + BREAK2: + class_panel->hide(); +} + +Fl_Class_Type Fl_Class_type; + +void Fl_Class_Type::write_declare() {} + +static Fl_Class_Type *current_class; +extern int varused_test; +void write_public(int state) { + if (!current_class || varused_test) return; + if (current_class->write_public_state == state) return; + current_class->write_public_state = state; + write_h(state ? "public:\n" : "private:\n"); +} + +void Fl_Class_Type::write_code1() { + parent_class = current_class; + current_class = this; + write_public_state = 0; + write_h("\nclass %s ", name()); + if (subclass_of) write_h(": %s ", subclass_of); + write_h("{\n"); +} + +void Fl_Class_Type::write_code2() { + write_h("};\n"); + current_class = parent_class; +} diff --git a/fluid/Fl_Group_Type.cxx b/fluid/Fl_Group_Type.cxx new file mode 100644 index 000000000..0e499339d --- /dev/null +++ b/fluid/Fl_Group_Type.cxx @@ -0,0 +1,245 @@ +// Fl_Group_Type.C + +// Object describing an Fl_Group +// Probably also links to Fl_Window_Type.C + +// Also the Fl_Tabs widget, with special stuff to select tab items +// and insure that only one is visible. + +#include <FL/Fl.H> +#include <FL/Fl_Group.H> +#include <FL/fl_message.H> +#include "Fl_Widget_Type.H" + +class igroup : public Fl_Group { +public: + void resize(int,int,int,int); + igroup(int x,int y,int w,int h) : Fl_Group(x,y,w,h) {Fl_Group::current(0);} +}; +// Override group's resize behavior to do nothing to children: +void igroup::resize(int X, int Y, int W, int H) { + Fl_Widget::resize(X,Y,W,H); + redraw(); +} + +class Fl_Group_Type : public Fl_Widget_Type { +public: + virtual const char *type_name() {return "Fl_Group";} + Fl_Widget *widget(int x,int y,int w,int h) { + igroup *g = new igroup(x,y,w,h); Fl_Group::current(0); return g;} + Fl_Widget_Type *_make() {return new Fl_Group_Type();} + Fl_Type *make(); + void write_code1(); + void write_code2(); + void add_child(Fl_Type*, Fl_Type*); + void move_child(Fl_Type*, Fl_Type*); + void remove_child(Fl_Type*); + int is_parent() const {return 1;} + int is_group() const {return 1;} +}; +Fl_Group_Type Fl_Group_type; // the "factory" + +Fl_Type *Fl_Group_Type::make() { + return Fl_Widget_Type::make(); +} + +void fix_group_size(Fl_Type *tt) { + if (!tt || !tt->is_group()) return; + Fl_Group_Type* t = (Fl_Group_Type*)tt; + int X = t->o->x(); + int Y = t->o->y(); + int R = X+t->o->w(); + int B = Y+t->o->h(); + for (Fl_Type *nn = t->next; nn && nn->level > t->level; nn = nn->next) { + if (!nn->is_widget() || nn->is_menu_item()) continue; + Fl_Widget_Type* n = (Fl_Widget_Type*)nn; + int x = n->o->x(); if (x < X) X = x; + int y = n->o->y(); if (y < Y) Y = y; + int r = x+n->o->w();if (r > R) R = r; + int b = y+n->o->h();if (b > B) B = b; + } + t->o->resize(X,Y,R-X,B-Y); +} + +extern int force_parent; + +void group_cb(Fl_Widget *, void *) { + // Find the current widget: + Fl_Type *qq = Fl_Type::current; + while (qq && (!qq->is_widget() || qq->is_menu_item())) qq = qq->parent; + if (!qq || qq->level <= 1) { + fl_message("Please select widgets to group"); + return; + } + Fl_Widget_Type* q = (Fl_Widget_Type*)qq; + force_parent = 1; + Fl_Group_Type *n = (Fl_Group_Type*)(Fl_Group_type.make()); + n->move_before(q); + n->o->resize(q->o->x(),q->o->y(),q->o->w(),q->o->h()); + for (Fl_Type *t = Fl_Type::first; t;) { + if (t->level != n->level || t == n || !t->selected) { + t = t->next; continue;} + Fl_Type *nxt = t->remove(); + t->add(n); + t = nxt; + } + fix_group_size(n); +} + +void ungroup_cb(Fl_Widget *, void *) { + // Find the group: + Fl_Type *q = Fl_Type::current; + while (q && (!q->is_widget() || q->is_menu_item())) q = q->parent; + if (q) q = q->parent; + if (!q || q->level <= 1) { + fl_message("Please select widgets in a group"); + return; + } + Fl_Type* n; + for (n = q->next; n && n->level > q->level; n = n->next) { + if (n->level == q->level+1 && !n->selected) { + fl_message("Please select all widgets in group"); + return; + } + } + for (n = q->next; n && n->level > q->level;) { + Fl_Type *nxt = n->remove(); + n->insert(q); + n = nxt; + } + delete q; +} + +//////////////////////////////////////////////////////////////// + +#include <stdio.h> + +void Fl_Group_Type::write_code1() { + Fl_Widget_Type::write_code1(); +} + +void Fl_Group_Type::write_code2() { + write_c("%so->end();\n", indent()); + if (resizable()) write_c("%sFl_Group::current()->resizable(o);\n", indent()); + Fl_Widget_Type::write_code2(); +} + +//////////////////////////////////////////////////////////////// + +#include <FL/Fl_Tabs.H> + +class itabs : public Fl_Tabs { +public: + void resize(int,int,int,int); + itabs(int x,int y,int w,int h) : Fl_Tabs(x,y,w,h) {} +}; +// Override group's resize behavior to do nothing to children: +void itabs::resize(int X, int Y, int W, int H) { + Fl_Widget::resize(X,Y,W,H); + redraw(); +} + +static const char tabs_type_name[] = "Fl_Tabs"; + +class Fl_Tabs_Type : public Fl_Group_Type { +public: + virtual const char *type_name() {return tabs_type_name;} + Fl_Widget *widget(int x,int y,int w,int h) { + itabs *g = new itabs(x,y,w,h); Fl_Group::current(0); return g;} + Fl_Widget_Type *_make() {return new Fl_Tabs_Type();} + Fl_Type* click_test(int,int); + void add_child(Fl_Type*, Fl_Type*); + void remove_child(Fl_Type*); +}; +Fl_Tabs_Type Fl_Tabs_type; // the "factory" + +// This is called when user clicks on a widget in the window. See +// if it is a tab title, and adjust visibility and return new selection: +// If none, return o unchanged: + +Fl_Type* Fl_Tabs_Type::click_test(int x, int y) { + Fl_Tabs *t = (Fl_Tabs*)o; + Fl_Widget *a = t->which(x,y); + if (!a) return 0; // didn't click on tab + // okay, run the tabs ui until they let go of mouse: + t->handle(FL_PUSH); + Fl::pushed(t); + while (Fl::pushed()==t) Fl::wait(); + return (Fl_Type*)(t->value()->user_data()); +} + +// This is called when o is created. If it is in the tab group make +// sure it is visible: + +void Fl_Group_Type::add_child(Fl_Type* cc, Fl_Type* before) { + Fl_Widget_Type* c = (Fl_Widget_Type*)cc; + Fl_Widget* b = before ? ((Fl_Widget_Type*)before)->o : 0; + ((Fl_Group*)o)->insert(*(c->o), b); + o->redraw(); +} + +void Fl_Tabs_Type::add_child(Fl_Type* c, Fl_Type* before) { + Fl_Group_Type::add_child(c, before); + ((Fl_Tabs*)o)->value(0); +} + +// This is called when o is deleted. If it is in the tab group make +// sure it is not visible: + +void Fl_Group_Type::remove_child(Fl_Type* cc) { + Fl_Widget_Type* c = (Fl_Widget_Type*)cc; + ((Fl_Group*)o)->remove(c->o); + o->redraw(); +} + +void Fl_Tabs_Type::remove_child(Fl_Type* cc) { + Fl_Widget_Type* c = (Fl_Widget_Type*)cc; + Fl_Tabs *t = (Fl_Tabs*)o; + if (t->value() == c->o) t->value(0); + Fl_Group_Type::remove_child(c); +} + +// move, don't change selected value: + +void Fl_Group_Type::move_child(Fl_Type* cc, Fl_Type* before) { + Fl_Widget_Type* c = (Fl_Widget_Type*)cc; + Fl_Widget* b = before ? ((Fl_Widget_Type*)before)->o : 0; + ((Fl_Group*)o)->remove(c->o); + ((Fl_Group*)o)->insert(*(c->o), b); + o->redraw(); +} + +//////////////////////////////////////////////////////////////// +// some other group subclasses that fluid does not treat specially: + +#include <FL/Fl_Scroll.H> + +static const char scroll_type_name[] = "Fl_Scroll"; + +static Fl_Menu_Item scroll_type_menu[] = { + {"BOTH", 0, 0, 0/*(void*)Fl_Scroll::BOTH*/}, + {"HORIZONTAL", 0, 0, (void*)Fl_Scroll::HORIZONTAL}, + {"VERTICAL", 0, 0, (void*)Fl_Scroll::VERTICAL}, + {"HORIZONTAL_ALWAYS", 0, 0, (void*)Fl_Scroll::HORIZONTAL_ALWAYS}, + {"VERTICAL_ALWAYS", 0, 0, (void*)Fl_Scroll::VERTICAL_ALWAYS}, + {"BOTH_ALWAYS", 0, 0, (void*)Fl_Scroll::BOTH_ALWAYS}, + {0}}; + +class Fl_Scroll_Type : public Fl_Group_Type { + Fl_Menu_Item *subtypes() {return scroll_type_menu;} +public: + virtual const char *type_name() {return scroll_type_name;} + Fl_Widget_Type *_make() {return new Fl_Scroll_Type();} +}; +Fl_Scroll_Type Fl_Scroll_type; // the "factory" + +//////////////////////////////////////////////////////////////// + +static const char tile_type_name[] = "Fl_Tile"; + +class Fl_Tile_Type : public Fl_Group_Type { +public: + virtual const char *type_name() {return tile_type_name;} + Fl_Widget_Type *_make() {return new Fl_Tile_Type();} +}; +Fl_Tile_Type Fl_Tile_type; // the "factory" diff --git a/fluid/Fl_Menu_Type.cxx b/fluid/Fl_Menu_Type.cxx new file mode 100644 index 000000000..02318602c --- /dev/null +++ b/fluid/Fl_Menu_Type.cxx @@ -0,0 +1,487 @@ +// Fl_Menu_Type.C + +// Menu items are kludged by making a phony Fl_Box widget so the normal +// widget panel can be used to control them. + +// This file also contains code to make Fl_Menu_Button, Fl_Menu_Bar, +// etc widgets. + +#include <FL/Fl.H> +#include "Fl_Widget_Type.H" +#include <FL/fl_message.H> +#include <FL/Fl_Menu_.H> +#include <FL/Fl_Button.H> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> + +static Fl_Menu_Item menu_item_type_menu[] = { + {"Normal",0,0,(void*)0}, + {"Toggle",0,0,(void*)FL_MENU_BOX}, + {"Radio",0,0,(void*)FL_MENU_RADIO}, + {0}}; + +class Fl_Menu_Item_Type : public Fl_Widget_Type { +public: + Fl_Menu_Item* subtypes() {return menu_item_type_menu;} + const char* type_name() {return "menuitem";} + Fl_Type* make(); + int is_menu_item() const {return 1;} + int is_button() const {return 1;} // this gets shortcut to work + Fl_Widget* widget(int,int,int,int) {return 0;} + Fl_Widget_Type* _make() {return 0;} + void write_declare(); + const char* menu_name(int& i); + int flags(); + void write_static(); + void write_item(); + void write_code1(); + void write_code2(); +}; + +class Fl_Submenu_Type : public Fl_Menu_Item_Type { +public: + Fl_Menu_Item* subtypes() {return 0;} + const char* type_name() {return "submenu";} + int is_parent() const {return 1;} + int is_button() const {return 0;} // disable shortcut + Fl_Type* make(); + // changes to submenu must propagate up so build_menu is called + // on the parent Fl_Menu_Type: + void add_child(Fl_Type*a, Fl_Type*b) {parent->add_child(a,b);} + void move_child(Fl_Type*a, Fl_Type*b) {parent->move_child(a,b);} + void remove_child(Fl_Type*a) {parent->remove_child(a);} +}; + +extern int reading_file; +extern int force_parent; + +static char submenuflag; + +Fl_Type *Fl_Menu_Item_Type::make() { + // Find the current menu item: + Fl_Type* q = Fl_Type::current; + Fl_Type* p = q; + if (p) { + if (force_parent && q->is_menu_item() || !q->is_parent()) p = p->parent; + } + force_parent = 0; + if (!p || !(p->is_menu_button() || p->is_menu_item() && p->is_parent())) { + fl_message("Please select a menu to add to"); + return 0; + } + if (!o) { + o = new Fl_Button(0,0,100,20); // create template widget + } + + Fl_Menu_Item_Type* t = submenuflag ? new Fl_Submenu_Type() : new Fl_Menu_Item_Type(); + t->o = new Fl_Button(0,0,100,20); + t->factory = this; + t->add(p); + if (!reading_file) t->label(submenuflag ? "submenu" : "item"); + return t; +} + +Fl_Type *Fl_Submenu_Type::make() { + submenuflag = 1; + Fl_Type* t = Fl_Menu_Item_Type::make(); + submenuflag = 0; + return t; +} + +Fl_Menu_Item_Type Fl_Menu_Item_type; +Fl_Submenu_Type Fl_Submenu_type; + +//////////////////////////////////////////////////////////////// +// Writing the C code: + +#include <ctype.h> + +// test functions in Fl_Widget_Type.C: +int is_name(const char *c); +const char *array_name(Fl_Widget_Type *o); +int isdeclare(const char *c); + +void Fl_Menu_Item_Type::write_declare() { + if (callback() && is_name(callback())) + ::write_declare("extern void %s(Fl_Menu_*, %s);", callback(), + user_data_type() ? user_data_type() : "void*"); + for (int n=0; n < NUM_EXTRA_CODE; n++) { + if (extra_code(n) && isdeclare(extra_code(n))) + ::write_declare("%s", extra_code(n)); + } +} + +const char* Fl_Menu_Item_Type::menu_name(int& i) { + i = 0; + Fl_Type* t = prev; + while (t && t->is_menu_item()) { + // be sure to count the {0} that ends a submenu: + if (t->level > t->next->level || + // detect empty submenu: + t->level==t->next->level &&t->is_parent()) + i++; + t = t->prev; i++; + } + return unique_id(t, "menu", t->name(), t->label()); +} + +#include "Fluid_Image.H" + +void Fl_Menu_Item_Type::write_static() { + if (callback() && !is_name(callback())) { + // see if 'o' or 'v' used, to prevent unused argument warnings: + int use_o = 0; + int use_v = 0; + const char *d; + for (d = callback(); *d;) { + if (*d == 'o' && !is_id(d[1])) use_o = 1; + if (*d == 'v' && !is_id(d[1])) use_v = 1; + do d++; while (is_id(*d)); + while (*d && !is_id(*d)) d++; + } + const char* cn = callback_name(); + const char* k = class_name(); + if (k) { + write_c("\ninline void %s::%s_i(Fl_Menu_*", k, cn); + } else { + write_c("\nstatic void %s(Fl_Menu_*", cn); + } + if (use_o) write_c(" o"); + const char* ut = user_data_type() ? user_data_type() : "void*"; + write_c(", %s", ut); + if (use_v) write_c(" v"); + write_c(") {\n %s", callback()); + if (*(d-1) != ';') write_c(";"); + write_c("\n}\n"); + if (k) { + write_c("void %s::%s(Fl_Menu_* o, %s v) {\n", k, cn, ut); + write_c(" ((%s*)(o->", k); + Fl_Type* t = parent; while (t->is_menu_item()) t = t->parent; + for (t = t->parent; t->is_widget(); t = t->parent) write_c("parent()->"); + write_c("user_data()))->%s_i(o,v);\n}\n", cn); + } + } + if (image) { + if (image->written != write_number) { + image->write_static(); + image->written = write_number; + } + } + if (next && next->is_menu_item()) return; + // okay, when we hit last item in the menu we have to write the + // entire array out: + int level; + const char* k = class_name(); + if (k) { + write_c("\nFl_Menu_Item %s::%s[] = {\n", k, menu_name(level)); + } else + write_c("\nFl_Menu_Item %s[] = {\n", menu_name(level)); + Fl_Type* t = prev; while (t && t->is_menu_item()) t = t->prev; + level = t->level+1; + for (Fl_Type* q = t->next; q && q->is_menu_item(); q = q->next) { + ((Fl_Menu_Item_Type*)q)->write_item(); + if (q->is_parent()) level++; + int l1 = + (q->next && q->next->is_menu_item()) ? q->next->level : t->next->level; + while (level > l1) {write_c(" {0},\n"); level--;} + level = l1; + } + write_c(" {0}\n};\n"); +} + +int Fl_Menu_Item_Type::flags() { + int i = o->type(); + if (((Fl_Button*)o)->value()) i |= FL_MENU_VALUE; + if (!o->active()) i |= FL_MENU_INACTIVE; + if (!o->visible()) i |= FL_MENU_INVISIBLE; + if (is_parent()) i |= FL_SUBMENU; + if (hotspot()) i |= FL_MENU_DIVIDER; + return i; +} + +void Fl_Menu_Item_Type::write_item() { + write_c(" {"); + if (image) write_c("0"); + else if (label()) write_cstring(label()); + else write_c("\"\""); + if (((Fl_Button*)o)->shortcut()) + write_c(", 0x%x, ", ((Fl_Button*)o)->shortcut()); + else + write_c(", 0, "); + if (callback()) { + const char* k = class_name(); + if (k) { + write_c(" (Fl_Callback*)%s::%s,", k, callback_name()); + } else { + write_c(" (Fl_Callback*)%s,", callback_name()); + } + } else + write_c(" 0,"); + if (user_data()) + write_c(" (void*)(%s),", user_data()); + else + write_c(" 0,"); + write_c(" %d, %d, %d, %d, %d", flags(), + o->labeltype(), o->labelfont(), o->labelsize(), o->labelcolor()); + write_c("},\n"); +} + +void Fl_Menu_Item_Type::write_code1() { + if (!prev->is_menu_item()) { + // for first menu item, declare the array + int i; const char* n = menu_name(i); + if (class_name()) + write_h(" static Fl_Menu_Item %s[];\n", n); + else + write_h("extern Fl_Menu_Item %s[];\n", n); + } + + const char *c = array_name(this); + if (c) { + int i; const char* n = menu_name(i); + write_h("#define %s (%s+%d)\n", c, n, i); + } + + if (callback()) { + if (!is_name(callback()) && class_name()) { + const char* cn = callback_name(); + const char* ut = user_data_type() ? user_data_type() : "void*"; + write_public(0); + write_h(" inline void %s_i(Fl_Menu_*, %s);\n", cn, ut); + write_h(" static void %s(Fl_Menu_*, %s);\n", cn, ut); + } + } + + int init = 0; + if (image) { + int i; const char* n = menu_name(i); + write_c(" {Fl_Menu_Item* o = &%s[%d];\n", n, i); + init = 1; + image->write_code(); + } + for (int n=0; n < NUM_EXTRA_CODE; n++) + if (extra_code(n) && !isdeclare(extra_code(n))) { + if (!init) { + init = 1; + int i; const char* n = menu_name(i); + write_c("%s{ Fl_Menu_Item* o = &%s[%d];\n", indent(), n, i); + } + write_c("%s %s\n", indent(), extra_code(n)); + } + if (init) write_c("%s}\n",indent()); +} + +void Fl_Menu_Item_Type::write_code2() {} + +//////////////////////////////////////////////////////////////// +// This is the base class for widgets that contain a menu (ie +// subclasses of Fl_Menu_. +// This is a parent widget and menu items can be added as +// children. An actual array of Fl_Menu_Items is kept parallel +// with the child objects and updated as they change. + +class Fl_Menu_Type : public Fl_Widget_Type { + int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) { + Fl_Menu_ *o = (Fl_Menu_*)(w==4 ? ((Fl_Widget_Type*)this->factory)->o : this->o); + switch (w) { + case 4: + case 0: f = o->textfont(); s = o->textsize(); c = o->textcolor(); break; + case 1: o->textfont(f); break; + case 2: o->textsize(s); break; + case 3: o->textcolor(c); break; + } + return 1; + } +public: + int is_menu_button() const {return 1;} + int is_parent() const {return 1;} + int menusize; + void build_menu(); + Fl_Menu_Type() : Fl_Widget_Type() {menusize = 0;} + ~Fl_Menu_Type() { + if (menusize) delete[] (Fl_Menu_Item*)(((Fl_Menu_*)o)->menu()); + } + void add_child(Fl_Type*, Fl_Type*) {build_menu();} + void move_child(Fl_Type*, Fl_Type*) {build_menu();} + void remove_child(Fl_Type*) {build_menu();} + Fl_Type* click_test(int x, int y); + void write_code2(); +}; + +void Fl_Menu_Type::build_menu() { + Fl_Menu_* w = (Fl_Menu_*)o; + // count how many Fl_Menu_Item structures needed: + int n = 0; + Fl_Type* q; + for (q = next; q && q->level > level; q = q->next) { + if (q->is_parent()) n++; // space for null at end of submenu + n++; + } + if (!n) { + if (menusize) delete[] (Fl_Menu_Item*)(w->menu()); + w->menu(0); + menusize = 0; + } else { + n++; // space for null at end of menu + if (menusize<n) { + if (menusize) delete[] (Fl_Menu_Item*)(w->menu()); + menusize = n+10; + w->menu(new Fl_Menu_Item[menusize]); + } + // fill them all in: + Fl_Menu_Item* m = (Fl_Menu_Item*)(w->menu()); + int lvl = level+1; + for (q = next; q && q->level > level; q = q->next) { + Fl_Menu_Item_Type* i = (Fl_Menu_Item_Type*)q; + m->label(i->o->label()); + m->shortcut(((Fl_Button*)(i->o))->shortcut()); + m->callback(0,(void*)i); + m->flags = i->flags(); + m->labeltype(i->o->labeltype()); + m->labelfont(i->o->labelfont()); + m->labelsize(i->o->labelsize()); + m->labelcolor(i->o->labelcolor()); + m++; + if (q->is_parent()) lvl++; + int l1 = + (q->next && q->next->is_menu_item()) ? q->next->level : level; + while (lvl > l1) {m->label(0); m++; lvl--;} + lvl = l1; + } + } + o->redraw(); +} + +Fl_Type* Fl_Menu_Type::click_test(int, int) { + if (selected) return 0; // let user move the widget + Fl_Menu_* w = (Fl_Menu_*)o; + if (!menusize) return 0; + const Fl_Menu_Item* save = w->mvalue(); + w->value((Fl_Menu_Item*)0); + Fl::pushed(w); + w->handle(FL_PUSH); + const Fl_Menu_Item* m = w->mvalue(); + if (m) { + // restore the settings of toggles & radio items: + if (m->flags & (FL_MENU_RADIO | FL_MENU_TOGGLE)) build_menu(); + return (Fl_Type*)(m->user_data()); + } + w->value(save); + return this; +} + +void Fl_Menu_Type::write_code2() { + if (next && next->is_menu_item()) + write_c("%so->menu(%s);\n", indent(), + unique_id(this, "menu", name(), label())); + Fl_Widget_Type::write_code2(); +} + +//////////////////////////////////////////////////////////////// + +#include <FL/Fl_Menu_Button.H> +static Fl_Menu_Item button_type_menu[] = { + {"normal",0,0,(void*)0}, + {"popup1",0,0,(void*)Fl_Menu_Button::POPUP1}, + {"popup2",0,0,(void*)Fl_Menu_Button::POPUP2}, + {"popup3",0,0,(void*)Fl_Menu_Button::POPUP3}, + {"popup12",0,0,(void*)Fl_Menu_Button::POPUP12}, + {"popup23",0,0,(void*)Fl_Menu_Button::POPUP23}, + {"popup13",0,0,(void*)Fl_Menu_Button::POPUP13}, + {"popup123",0,0,(void*)Fl_Menu_Button::POPUP123}, + {0}}; +class Fl_Menu_Button_Type : public Fl_Menu_Type { + Fl_Menu_Item *subtypes() {return button_type_menu;} +public: + virtual const char *type_name() {return "Fl_Menu_Button";} + Fl_Widget *widget(int x,int y,int w,int h) { + return new Fl_Menu_Button(x,y,w,h,"menu");} + Fl_Widget_Type *_make() {return new Fl_Menu_Button_Type();} +}; +Fl_Menu_Button_Type Fl_Menu_Button_type; + +//////////////////////////////////////////////////////////////// + +#include <FL/Fl_Choice.H> + +static Fl_Menu_Item dummymenu[] = {{"CHOICE"},{0}}; + +class Fl_Choice_Type : public Fl_Menu_Type { +public: + virtual const char *type_name() {return "Fl_Choice";} + Fl_Widget *widget(int x,int y,int w,int h) { + Fl_Choice *o = new Fl_Choice(x,y,w,h,"choice:"); + o->menu(dummymenu); + return o; + } + Fl_Widget_Type *_make() {return new Fl_Choice_Type();} +}; +Fl_Choice_Type Fl_Choice_type; + +//////////////////////////////////////////////////////////////// + +#include <FL/Fl_Menu_Bar.H> +class Fl_Menu_Bar_Type : public Fl_Menu_Type { +public: + virtual const char *type_name() {return "Fl_Menu_Bar";} + Fl_Widget *widget(int x,int y,int w,int h) { + return new Fl_Menu_Bar(x,y,w,h);} + Fl_Widget_Type *_make() {return new Fl_Menu_Bar_Type();} +}; +Fl_Menu_Bar_Type Fl_Menu_Bar_type; + +//////////////////////////////////////////////////////////////// +// Shortcut entry item in panel: + +#include <FL/Fl_Output.H> +#include "Shortcut_Button.H" +#include <FL/fl_draw.H> + +void Shortcut_Button::draw() { + if (value()) draw_box(FL_THIN_DOWN_BOX, (Fl_Color)9); + else draw_box(FL_THIN_UP_BOX, FL_WHITE); + fl_font(FL_HELVETICA,14); fl_color(FL_BLACK); + fl_draw(fl_shortcut_label(svalue),x()+6,y(),w(),h(),FL_ALIGN_LEFT); +} + +int Shortcut_Button::handle(int e) { + when(0); type(FL_TOGGLE_BUTTON); + if (e == FL_KEYBOARD) { + if (!value()) return 0; + int v = Fl::event_text()[0]; + if (v > 32 && v < 0x7f || v > 0xa0 && v <= 0xff) { + v = v | Fl::event_state()&(FL_META|FL_ALT|FL_CTRL); + } else { + v = Fl::event_state()&(FL_META|FL_ALT|FL_CTRL|FL_SHIFT) | Fl::event_key(); + if (v == FL_BackSpace && svalue) v = 0; + } + if (v != svalue) {svalue = v; set_changed(); redraw();} + return 1; + } else if (e == FL_UNFOCUS) { + int c = changed(); value(0); if (c) set_changed(); + return 1; + } else if (e == FL_FOCUS) { + return value(); + } else { + int r = Fl_Button::handle(e); + if (e == FL_RELEASE && value() && Fl::focus() != this) take_focus(); + return r; + } +} + +void shortcut_in_cb(Shortcut_Button* i, void* v) { + if (v == LOAD) { + if (!current_widget->is_button()) {i->hide(); return;} + i->show(); + i->svalue = ((Fl_Button*)(current_widget->o))->shortcut(); + i->redraw(); + } else { + for (Fl_Type *o = Fl_Type::first; o; o = o->next) + if (o->selected && o->is_button()) { + Fl_Button* b = (Fl_Button*)(((Fl_Widget_Type*)o)->o); + b->shortcut(i->svalue); + if (o->is_menu_item()) ((Fl_Widget_Type*)o)->redraw(); + } + } +} diff --git a/fluid/Fl_Type.cxx b/fluid/Fl_Type.cxx new file mode 100644 index 000000000..f57a970d4 --- /dev/null +++ b/fluid/Fl_Type.cxx @@ -0,0 +1,617 @@ +/* Fl_Type.C + + Each object described by Fluid is one of these objects. They + are all stored in a double-linked list. + + They "type" of the object is covered by the virtual functions. + There will probably be a lot of these virtual functions. + + The type browser is also a list of these objects, but they + are "factory" instances, not "real" ones. These objects exist + only so the "make" method can be called on them. They are + not in the linked list and are not written to files or + copied or otherwise examined. + +*/ + +#include <FL/Fl.H> +#include <FL/Fl_Browser_.H> +#include <FL/fl_draw.H> +#include <ctype.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> + +#include "Fl_Type.H" + +//////////////////////////////////////////////////////////////// + +class Widget_Browser : public Fl_Browser_ { + friend class Fl_Type; + + // required routines for Fl_Browser_ subclass: + void *item_first() const ; + void *item_next(void *) const ; + void *item_prev(void *) const ; + int item_selected(void *) const ; + void item_select(void *,int); + int item_width(void *) const ; + int item_height(void *) const ; + void item_draw(void *,int,int,int,int) const ; + int incr_height() const ; + +public: + + int handle(int); + void callback(); + Widget_Browser(int,int,int,int,const char * =0); +}; + +static Widget_Browser *widget_browser; +Fl_Widget *make_widget_browser(int x,int y,int w,int h) { + return (widget_browser = new Widget_Browser(x,y,w,h)); +} + +void select(Fl_Type *o, int v) { + widget_browser->select(o,v,1); + // Fl_Type::current = o; +} + +void select_only(Fl_Type *o) { + widget_browser->select_only(o,1); +} + +void deselect() { + widget_browser->deselect(); + //Fl_Type::current = 0; // this breaks the paste & merge functions +} + +Fl_Type *Fl_Type::first; +Fl_Type *Fl_Type::last; + +static void Widget_Browser_callback(Fl_Widget *o,void *) { + ((Widget_Browser *)o)->callback(); +} + +Widget_Browser::Widget_Browser(int x,int y,int w,int h,const char*l) +: Fl_Browser_(x,y,w,h,l) { + type(FL_MULTI_BROWSER); + Fl_Widget::callback(Widget_Browser_callback); + when(FL_WHEN_RELEASE); +} + +void *Widget_Browser::item_first() const {return Fl_Type::first;} + +void *Widget_Browser::item_next(void *l) const {return ((Fl_Type*)l)->next;} + +void *Widget_Browser::item_prev(void *l) const {return ((Fl_Type*)l)->prev;} + +int Widget_Browser::item_selected(void *l) const {return ((Fl_Type*)l)->new_selected;} + +void Widget_Browser::item_select(void *l,int v) {((Fl_Type*)l)->new_selected = v;} + +int Widget_Browser::item_height(void *l) const { + return ((Fl_Type *)l)->visible ? textsize()+2 : 0; +} + +int Widget_Browser::incr_height() const {return textsize()+2;} + +static Fl_Type* pushedtitle; + +// Generate a descriptive text for this item, to put in browser & window titles +const char* Fl_Type::title() { + const char* c = name(); if (c) return c; + return type_name(); +} + +extern const char* subclassname(Fl_Type*); + +void Widget_Browser::item_draw(void *v, int x, int y, int, int) const { + Fl_Type *l = (Fl_Type *)v; + x += 3 + l->level * 10; + fl_color(FL_BLACK); + if (l->is_parent()) { + if (!l->next || l->next->level <= l->level) { + if (l->open_!=(l==pushedtitle)) { + fl_loop(x,y+7,x+5,y+12,x+10,y+7); + } else { + fl_loop(x+2,y+2,x+7,y+7,x+2,y+12); + } + } else { + if (l->open_!=(l==pushedtitle)) { + fl_polygon(x,y+7,x+5,y+12,x+10,y+7); + } else { + fl_polygon(x+2,y+2,x+7,y+7,x+2,y+12); + } + } + x += 10; + } + if (l->is_widget() || l->is_class()) { + const char* c = subclassname(l); + if (!strncmp(c,"Fl_",3)) c += 3; + fl_font(textfont(), textsize()); + fl_draw(c, x, y+13); + x += int(fl_width(c)+fl_width('n')); + c = l->name(); + if (c) { + fl_font(textfont()|FL_BOLD, textsize()); + fl_draw(c, x, y+13); + } else if ((c=l->label())) { + char buf[50]; char* p = buf; + *p++ = '"'; + for (int i = 20; i--;) { + if (! (*c & -32)) break; + *p++ = *c++; + } + if (*c) {strcpy(p,"..."); p+=3;} + *p++ = '"'; + *p = 0; + fl_draw(buf, x, y+13); + } + } else { + const char* c = l->title(); + char buf[60]; char* p = buf; + for (int i = 55; i--;) { + if (! (*c & -32)) break; + *p++ = *c++; + } + if (*c) {strcpy(p,"..."); p+=3;} + *p = 0; + fl_font(textfont() | (l->is_code_block() && (l->level==0 || l->parent->is_class())?0:FL_BOLD), textsize()); + fl_draw(buf, x, y+13); + } +} + +int Widget_Browser::item_width(void *v) const { + Fl_Type *l = (Fl_Type *)v; + + if (!l->visible) return 0; + + int w = 3 + l->level*10; + if (l->is_parent()) w += 10; + + if (l->is_widget() || l->is_class()) { + const char* c = l->type_name(); + if (!strncmp(c,"Fl_",3)) c += 3; + fl_font(textfont(), textsize()); + w += int(fl_width(c) + fl_width('n')); + c = l->name(); + if (c) { + fl_font(textfont()|FL_BOLD, textsize()); + w += int(fl_width(c)); + } else if ((c=l->label())) { + char buf[50]; char* p = buf; + *p++ = '"'; + for (int i = 20; i--;) { + if (! (*c & -32)) break; + *p++ = *c++; + } + if (*c) {strcpy(p,"..."); p+=3;} + *p++ = '"'; + *p = 0; + w += int(fl_width(buf)); + } + } else { + const char* c = l->title(); + char buf[60]; char* p = buf; + for (int i = 55; i--;) { + if (! (*c & -32)) break; + *p++ = *c++; + } + if (*c) {strcpy(p,"..."); p+=3;} + *p = 0; + fl_font(textfont() | (l->is_code_block() && (l->level==0 || l->parent->is_class())?0:FL_BOLD), textsize()); + w += int(fl_width(buf)); + } + + return w; +} + +void redraw_browser() { + widget_browser->redraw(); +} + +void Widget_Browser::callback() { + selection_changed((Fl_Type*)selection()); +} + +int Widget_Browser::handle(int e) { + static Fl_Type *title; + Fl_Type *l; + int X,Y,W,H; bbox(X,Y,W,H); + switch (e) { + case FL_PUSH: + if (!Fl::event_inside(X,Y,W,H)) break; + l = (Fl_Type*)find_item(Fl::event_y()); + if (l) { + X += 10*l->level; + if (l->is_parent() && Fl::event_x()>X && Fl::event_x()<X+13) { + title = pushedtitle = l; + redraw_line(l); + return 1; + } + } + break; + case FL_DRAG: + if (!title) break; + l = (Fl_Type*)find_item(Fl::event_y()); + if (l) { + X += 10*l->level; + if (l->is_parent() && Fl::event_x()>X && Fl::event_x()<X+13) ; + else l = 0; + } + if (l != pushedtitle) { + if (pushedtitle) redraw_line(pushedtitle); + if (l) redraw_line(l); + pushedtitle = l; + } + return 1; + case FL_RELEASE: + if (!title) { + l = (Fl_Type*)find_item(Fl::event_y()); + if (l && l->new_selected && (Fl::event_clicks() || Fl::event_state(FL_CTRL))) + l->open(); + break; + } + l = pushedtitle; + title = pushedtitle = 0; + if (l) { + if (l->open_) { + l->open_ = 0; + for (Fl_Type*k = l->next; k&&k->level>l->level; k = k->next) + k->visible = 0; + } else { + l->open_ = 1; + for (Fl_Type*k=l->next; k&&k->level>l->level;) { + k->visible = 1; + if (k->is_parent() && !k->open_) { + Fl_Type *j; + for (j = k->next; j && j->level>k->level; j = j->next); + k = j; + } else + k = k->next; + } + } + redraw(); + } + return 1; + } + return Fl_Browser_::handle(e); +} + +Fl_Type::Fl_Type() { + factory = 0; + parent = 0; + next = prev = 0; + selected = new_selected = 0; + visible = 0; + name_ = 0; + label_ = 0; + user_data_ = 0; + user_data_type_ = 0; + callback_ = 0; + rtti = 0; + level = 0; +} + +static void fixvisible(Fl_Type *p) { + Fl_Type *t = p; + for (;;) { + if (t->parent) t->visible = t->parent->visible && t->parent->open_; + else t->visible = 1; + t = t->next; + if (!t || t->level <= p->level) break; + } +} + +// turn a click at x,y on this into the actual picked object: +Fl_Type* Fl_Type::click_test(int,int) {return 0;} +void Fl_Type::add_child(Fl_Type*, Fl_Type*) {} +void Fl_Type::move_child(Fl_Type*, Fl_Type*) {} +void Fl_Type::remove_child(Fl_Type*) {} + +// add a list of widgets as a new child of p: +void Fl_Type::add(Fl_Type *p) { + parent = p; + Fl_Type *end = this; + while (end->next) end = end->next; + Fl_Type *q; + int newlevel; + if (p) { + for (q = p->next; q && q->level > p->level; q = q->next); + newlevel = p->level+1; + } else { + q = 0; + newlevel = 0; + } + for (Fl_Type *t = this->next; t; t = t->next) t->level += (newlevel-level); + level = newlevel; + if (q) { + prev = q->prev; + prev->next = this; + q->prev = end; + end->next = q; + } else if (first) { + prev = last; + prev->next = this; + end->next = 0; + last = end; + } else { + first = this; + last = end; + prev = end->next = 0; + } + if (p) p->add_child(this,0); + open_ = 1; + fixvisible(this); + modflag = 1; + widget_browser->redraw(); +} + +// add to a parent before another widget: +void Fl_Type::insert(Fl_Type *g) { + Fl_Type *end = this; + while (end->next) end = end->next; + parent = g->parent; + int newlevel = g->level; + visible = g->visible; + for (Fl_Type *t = this->next; t; t = t->next) t->level += newlevel-level; + level = newlevel; + prev = g->prev; + if (prev) prev->next = this; else first = this; + end->next = g; + g->prev = end; + fixvisible(this); + if (parent) parent->add_child(this, g); + widget_browser->redraw(); +} + +// delete from parent: +Fl_Type *Fl_Type::remove() { + Fl_Type *end = this; + for (;;) { + if (!end->next || end->next->level <= level) break; + end = end->next; + } + if (prev) prev->next = end->next; + else first = end->next; + if (end->next) end->next->prev = prev; + else last = prev; + Fl_Type *r = end->next; + prev = end->next = 0; + if (parent) parent->remove_child(this); + parent = 0; + widget_browser->redraw(); + selection_changed(0); + return r; +} + +// update a string member: +int storestring(const char *n, const char * & p, int nostrip) { + if (n == p) return 0; + int length = 0; + if (n) { // see if blank, strip leading & trailing blanks + if (!nostrip) while (isspace(*n)) n++; + const char *e = n + strlen(n); + if (!nostrip) while (e > n && isspace(*(e-1))) e--; + length = e-n; + if (!length) n = 0; + } + if (n == p) return 0; + if (n && p && !strncmp(n,p,length) && !p[length]) return 0; + if (p) free((void *)p); + if (!n || !*n) { + p = 0; + } else { + char *q = (char *)malloc(length+1); + strncpy(q,n,length); + q[length] = 0; + p = q; + } + modflag = 1; + return 1; +} + +void Fl_Type::name(const char *n) { + if (storestring(n,name_)) { + if (visible) widget_browser->redraw(); + } +} + +void Fl_Type::label(const char *n) { + if (storestring(n,label_,1)) { + setlabel(label_); + if (visible && !name_) widget_browser->redraw(); + } +} + +void Fl_Type::callback(const char *n) { + storestring(n,callback_); +} + +void Fl_Type::user_data(const char *n) { + storestring(n,user_data_); +} + +void Fl_Type::user_data_type(const char *n) { + storestring(n,user_data_type_); +} + +void Fl_Type::open() { + printf("Open of '%s' is not yet implemented\n",type_name()); +} + +void Fl_Type::setlabel(const char *) {} + +Fl_Type::~Fl_Type() { + if (parent) parent->remove_child(this); + // warning: destructor only works for widgets that have been add()ed. + if (widget_browser) widget_browser->deleting(this); + if (prev) prev->next = next; else first = next; + if (next) next->prev = prev; else last = prev; + if (current == this) current = 0; + modflag = 1; +} + +int Fl_Type::is_parent() const {return 0;} +int Fl_Type::is_widget() const {return 0;} +int Fl_Type::is_valuator() const {return 0;} +int Fl_Type::is_button() const {return 0;} +int Fl_Type::is_menu_item() const {return 0;} +int Fl_Type::is_menu_button() const {return 0;} +int Fl_Type::is_group() const {return 0;} +int Fl_Type::is_window() const {return 0;} +int Fl_Type::is_code_block() const {return 0;} +int Fl_Type::is_decl_block() const {return 0;} +int Fl_Type::is_class() const {return 0;} + +//////////////////////////////////////////////////////////////// + +Fl_Type *in_this_only; // set if menu popped-up in window + +void select_all_cb(Fl_Widget *,void *) { + Fl_Type *p = Fl_Type::current ? Fl_Type::current->parent : 0; + if (in_this_only) { + Fl_Type *t = p; + for (; t && t != in_this_only; t = t->parent); + if (t != in_this_only) p = in_this_only; + } + for (;;) { + if (p) { + int foundany = 0; + for (Fl_Type *t = p->next; t && t->level>p->level; t = t->next) { + if (!t->new_selected) {widget_browser->select(t,1,0); foundany = 1;} + } + if (foundany) break; + p = p->parent; + } else { + for (Fl_Type *t = Fl_Type::first; t; t = t->next) + widget_browser->select(t,1,0); + break; + } + } + selection_changed(p); +} + +static void delete_children(Fl_Type *p) { + Fl_Type *f; + for (f = p; f && f->next && f->next->level > p->level; f = f->next); + for (; f != p; ) { + Fl_Type *g = f->prev; + delete f; + f = g; + } +} + +void delete_all(int selected_only) { + for (Fl_Type *f = Fl_Type::first; f;) { + if (f->selected || !selected_only) { + delete_children(f); + Fl_Type *g = f->next; + delete f; + f = g; + } else f = f->next; + } + selection_changed(0); +} + +// move f (and it's children) into list before g: +// returns pointer to whatever is after f & children +void Fl_Type::move_before(Fl_Type* g) { + if (level != g->level) printf("move_before levels don't match! %d %d\n", + level, g->level); + Fl_Type* n; + for (n = next; n && n->level > level; n = n->next); + if (n == g) return; + Fl_Type *l = n ? n->prev : Fl_Type::last; + prev->next = n; + if (n) n->prev = prev; else Fl_Type::last = prev; + prev = g->prev; + l->next = g; + if (prev) prev->next = this; else Fl_Type::first = this; + g->prev = l; + if (parent) parent->move_child(this,g); + widget_browser->redraw(); +} + +// move selected widgets in their parent's list: +void earlier_cb(Fl_Widget*,void*) { + Fl_Type *f; + for (f = Fl_Type::first; f; f=f->next) if (f->selected) { + Fl_Type *g; + for (g = f->prev; g && g->level > f->level; g = g->prev); + if (g && g->level == f->level) f->move_before(g); + } +} + +void later_cb(Fl_Widget*,void*) { + Fl_Type *f; + for (f = Fl_Type::last; f; f=f->prev) if (f->selected) { + Fl_Type *g; + for (g = f->next; g && g->level > f->level; g = g->next); + if (g && g->level == f->level && !g->selected) g->move_before(f); + } +} + +//////////////////////////////////////////////////////////////// + +// write a widget and all it's children: +void Fl_Type::write() { + write_indent(level); + write_word(type_name()); + write_word(name()); + write_open(level); + write_properties(); + write_close(level); + if (!is_parent()) return; + // now do children: + write_open(level); + Fl_Type *child; + for (child = next; child && child->level > level; child = child->next) + if (child->level == level+1) child->write(); + write_close(level); +} + +void Fl_Type::write_properties() { + // repeat this for each attribute: + if (label()) { + write_indent(level+1); + write_word("label"); + write_word(label()); + } + if (user_data()) { + write_indent(level+1); + write_word("user_data"); + write_word(user_data()); + if (user_data_type()) { + write_word("user_data_type"); + write_word(user_data_type()); + } + } + if (callback()) { + write_indent(level+1); + write_word("callback"); + write_word(callback()); + } + if (is_parent() && open_) write_word("open"); + if (selected) write_word("selected"); +} + +void Fl_Type::read_property(const char *c) { + if (!strcmp(c,"label")) + label(read_word()); + else if (!strcmp(c,"user_data")) + user_data(read_word()); + else if (!strcmp(c,"user_data_type")) + user_data_type(read_word()); + else if (!strcmp(c,"callback")) + callback(read_word()); + else if (!strcmp(c,"open")) + open_ = 1; + else if (!strcmp(c,"selected")) + select(this,1); + else + read_error("Unknown property \"%s\"", c); +} + +int Fl_Type::read_fdesign(const char*, const char*) {return 0;} diff --git a/fluid/Fl_Type.h b/fluid/Fl_Type.h new file mode 100644 index 000000000..737423a1d --- /dev/null +++ b/fluid/Fl_Type.h @@ -0,0 +1,142 @@ +// Fl_Type.H + +// Each object described by Fluid is one of these objects. They +// are all stored in a double-linked list. + +// There is also a single "factory" instance of each type of this. +// The method "make()" is called on this factory to create a new +// instance of this object. It could also have a "copy()" function, +// but it was easier to implement this by using the file read/write +// that is needed to save the setup anyways. + +#include <FL/Fl_Widget.H> +#include <FL/Fl_Menu.H> + +class Fl_Type { + + friend class Widget_Browser; + friend Fl_Widget *make_type_browser(int,int,int,int,const char *l=0); + friend class Fl_Window_Type; + virtual void setlabel(const char *); // virtual part of label(char*) + +protected: + + Fl_Type(); + + const char *name_; + const char *label_; + const char *callback_; + const char *user_data_; + const char *user_data_type_; + +public: // things that should not be public: + + Fl_Type *parent; // parent, which is previous in list + char new_selected; // browser highlight + char selected; // copied here by selection_changed() + char open_; // state of triangle in browser + char visible; // true if all parents are open + char rtti; // hack because I have no rtti, this is 0 for base class + int level; // number of parents over this + static Fl_Type *first, *last; // linked list of all objects + Fl_Type *next, *prev; // linked list of all objects + + Fl_Type *factory; + const char *callback_name(); + +public: + + virtual ~Fl_Type(); + virtual Fl_Type *make() = 0; + + void add(Fl_Type *parent); // add as new child + void insert(Fl_Type *n); // insert into list before n + Fl_Type* remove(); // remove from list + void move_before(Fl_Type*); // move before a sibling + + virtual const char *title(); // string for browser + virtual const char *type_name() = 0; // type for 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 *); + + virtual Fl_Type* click_test(int,int); + virtual void add_child(Fl_Type*, Fl_Type* beforethis); + virtual void move_child(Fl_Type*, Fl_Type* beforethis); + virtual void remove_child(Fl_Type*); + + static Fl_Type *current; // most recently picked object + virtual void open(); // what happens when you double-click + + // read and write data to a saved file: + void write(); + virtual void write_properties(); + virtual void read_property(const char *); + virtual int read_fdesign(const char*, const char*); + + // write code, these are called in order: + virtual void write_declare(); // write #include and #define to .h file + virtual void write_static(); // write static stuff to .c file + virtual void write_code1(); // code and .h before children + virtual void write_code2(); // code and .h after children + + // fake rtti: + virtual int is_parent() const; + virtual int is_widget() const; + virtual int is_button() const; + virtual int is_valuator() const; + virtual int is_menu_item() const; + virtual int is_menu_button() const; + virtual int is_group() const; + virtual int is_window() const; + virtual int is_code_block() const; + virtual int is_decl_block() const; + virtual int is_class() const; + + const char* class_name() const; +}; + +// object list operations: +Fl_Widget *make_widget_browser(int x,int y,int w,int h); +extern int modflag; +void delete_all(int selected_only=0); +void selection_changed(Fl_Type* new_current); + +// file operations: +void write_word(const char *); +void write_string(const char *,...); +int write_file(const char *, int selected_only = 0); +int write_code(const char *cfile, const char *hfile); + +int write_declare(const char *, ...); +int is_id(char); +const char* unique_id(void* o, const char*, const char*, const char*); +void write_c(const char*, ...); +void write_h(const char*, ...); +void write_cstring(const char *); +void write_cstring(const char *,int length); +void write_indent(int n); +void write_open(int); +void write_close(int n); +extern int write_number; +void write_public(int state); // writes pubic:/private: as needed +extern int indentation; +extern const char* indent(); + +int read_file(const char *, int merge); +const char *read_word(int wantbrace = 0); +void read_error(const char *format, ...); + +// check legality of c code (sort of) and return error: +const char *c_check(const char *c, int type = 0); + +// replace a string pointer with new value, strips leading/trailing blanks: +int storestring(const char *n, const char * & p, int nostrip=0); diff --git a/fluid/Fl_Widget_Type.cxx b/fluid/Fl_Widget_Type.cxx new file mode 100644 index 000000000..96c22acea --- /dev/null +++ b/fluid/Fl_Widget_Type.cxx @@ -0,0 +1,1676 @@ +// Fl_Widget_Type.C + +#include <FL/Fl.H> +#include <FL/Fl_Group.H> +#include "Fl_Widget_Type.H" +#include <FL/fl_message.H> +#include <FL/Fl_Slider.H> +#include <FL/Fl_Window.H> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> + +// Make an Fl_Widget_Type subclass instance. +// It figures out the automatic size and parent of the new widget, +// creates the Fl_Widget (by calling the virtual function _make), +// adds it to the Fl_Widget hierarchy, creates a new Fl_Type +// instance, sets the widget pointers, and makes all the display +// update correctly... + +extern int reading_file; +int force_parent; +extern int gridx; +extern int gridy; + +int Fl_Widget_Type::is_widget() const {return 1;} + +const char* subclassname(Fl_Type* l) { + if (l->is_widget()) { + Fl_Widget_Type* p = (Fl_Widget_Type*)l; + const char* c = p->subclass(); + if (c) return c; + if (p->o->type() == FL_WINDOW+1) return "Fl_Double_Window"; + } + return l->type_name(); +} + +Fl_Type *Fl_Widget_Type::make() { + // Find the current widget, or widget to copy: + Fl_Type *qq = Fl_Type::current; + while (qq && (!qq->is_widget() || qq->is_menu_item())) qq = qq->parent; + if (!qq) { + fl_message("Please select a widget"); + return 0; + } + Fl_Widget_Type* q = (Fl_Widget_Type*)qq; + // find the parent widget: + Fl_Widget_Type* p = q; + if ((force_parent || !p->is_group()) && p->parent->is_widget()) + p = (Fl_Widget_Type*)(p->parent); + force_parent = 0; + + // Figure out a border between widget and window: + int B = p->o->w()/2; if (p->o->h()/2 < B) B = p->o->h()/2; if (B>25) B = 25; + + int ULX,ULY; // parent's origin in window + if (!p->is_window()) { // if it is a group, add corner + ULX = p->o->x(); ULY = p->o->y(); + } else { + ULX = ULY = 0; + } + + // Figure out a position and size for the widget + int X,Y,W,H; + if (is_group()) { // fill the parent with the widget + X = ULX+B; + W = p->o->w()-B; + Y = ULY+B; + H = p->o->h()-B; + } else if (q != p) { // copy position and size of current widget + W = q->o->w(); + H = q->o->h(); + X = q->o->x()+W; + Y = q->o->y(); + if (X+W > ULX+p->o->w()) { + X = q->o->x(); + Y = q->o->y()+H; + if (Y+H > ULY+p->o->h()) Y = ULY+B; + } + } else { // just make it small and square... + X = ULX+B; + Y = ULY+B; + W = H = B; + } + + // satisfy the grid requirements (otherwise it edits really strangely): + if (gridx>1) { + X = (X/gridx)*gridx; + W = ((W-1)/gridx+1)*gridx; + } + if (gridy>1) { + Y = (Y/gridy)*gridy; + H = ((H-1)/gridy+1)*gridy; + } + + // Construct the Fl_Type: + Fl_Widget_Type *t = _make(); + if (!o) o = widget(0,0,100,100); // create template widget + t->factory = this; + // Construct the Fl_Widget: + t->o = widget(X,Y,W,H); + if (reading_file) t->o->label(0); + else if (t->o->label()) t->label(t->o->label()); // allow editing + t->o->user_data((void*)t); + // Put it in the parent: + // ((Fl_Group *)(p->o))->add(t->o); (done by Fl_Type::add()) + // add to browser: + t->add(p); + t->redraw(); + return t; +} + +#include "Fluid_Image.H" + +void Fl_Widget_Type::setimage(Fluid_Image *i) { + if (i == image) return; + if (image) image->decrement(); + if (i) i->increment(); + image = i; + if (i) i->label(o); + else o->labeltype(FL_NORMAL_LABEL); + redraw(); +} + +static char dont_touch_image; +void Fl_Widget_Type::setlabel(const char *n) { + if (image) { + if (dont_touch_image) return; + Fluid_Image *i = Fluid_Image::find(n); + setimage(i); + if (i) return; + } + o->label(n); + redraw(); +} + +Fl_Widget_Type::Fl_Widget_Type() { + for (int n=0; n<NUM_EXTRA_CODE; n++) {extra_code_[n] = 0; subclass_ = 0;} + hotspot_ = 0; + image = 0; + xclass = 0; + o = 0; + public_ = 1; +} + +Fl_Widget_Type::~Fl_Widget_Type() { + if (o) { + o->hide(); + if (o->parent()) ((Fl_Group*)o->parent())->remove(*o); + delete o; + } +} + +void Fl_Widget_Type::extra_code(int m,const char *n) { + storestring(n,extra_code_[m]); +} + +extern void redraw_browser(); +void Fl_Widget_Type::subclass(const char *n) { + if (storestring(n,subclass_) && visible) + redraw_browser(); +} + +void Fl_Widget_Type::redraw() { + Fl_Type *t = this; + if (is_menu_item()) { + // find the menu button that parents this menu: + do t = t->parent; while (t && t->is_menu_item()); + // kludge to cause build_menu to be called again: + t->add_child(0,0); + } else { + while (t->parent && t->parent->is_widget()) t = t->parent; + ((Fl_Widget_Type*)t)->o->redraw(); + } +} + +// the recursive part sorts all children, returns pointer to next: +Fl_Type *sort(Fl_Type *parent) { + Fl_Type *f,*n=0; + for (f = parent ? parent->next : Fl_Type::first; ; f = n) { + if (!f || parent && f->level <= parent->level) return f; + n = sort(f); + if (!f->selected || (!f->is_widget() || f->is_menu_item())) continue; + Fl_Widget* fw = ((Fl_Widget_Type*)f)->o; + Fl_Type *g; // we will insert before this + for (g = parent->next; g != f; g = g->next) { + if (!g->selected || g->level > f->level) continue; + Fl_Widget* gw = ((Fl_Widget_Type*)g)->o; + if (gw->y() > fw->y()) break; + if (gw->y() == fw->y() && gw->x() > fw->x()) break; + } + if (g != f) f->move_before(g); + } +} + +//////////////////////////////////////////////////////////////// +// The control panels! + +#include "widget_panel.H" +#include <FL/fl_show_colormap.H> + +// All the callbacks use the argument to indicate whether to load or store. +// This avoids the need for pointers to all the widgets, and keeps the +// code localized in the callbacks. +// A value of LOAD means to load. The hope is that this will not collide +// with any actual useful values for the argument. I also use this to +// initialized parts of the widget that are nyi by fluid. + +Fl_Widget_Type *current_widget; // one of the selected ones +static int numselected; // number selected +static int haderror; + +void name_cb(Fl_Input* o, void *v) { + if (v == LOAD) { + if (numselected != 1) { + static char buf[16]; + sprintf(buf,"(%d widgets)",numselected); + ((Fl_Window*)(o->parent()))->label(buf); + o->hide(); + } else { + o->static_value(current_widget->name()); + o->show(); + ((Fl_Window*)(o->parent()))->label(current_widget->title()); + } + } else { + if (numselected == 1) { + current_widget->name(o->value()); + // I don't update window title, as it probably is being closed + // and wm2 (a window manager) barfs if you retitle and then + // hide a window: + // ((Fl_Window*)(o->parent()))->label(current_widget->title()); + } + } +} + +void name_public_cb(Fl_Light_Button* i, void* v) { + if (v == LOAD) { + i->value(current_widget->public_); + } else { + for (Fl_Type *o = Fl_Type::first; o; o = o->next) + if (o->selected && o->is_widget()) + ((Fl_Widget_Type*)o)->public_ = i->value(); + } +} + +static char* oldlabel; +static unsigned oldlabellen; +static Fl_Input *label_input; + +void label_cb(Fl_Input* i, void *v) { + if (v == LOAD) { + label_input = i; + i->static_value(current_widget->label()); + if (strlen(i->value()) >= oldlabellen) { + oldlabellen = strlen(i->value())+128; + oldlabel = (char*)realloc(oldlabel,oldlabellen); + } + strcpy(oldlabel,i->value()); + if (current_widget->image) i->deactivate(); + else i->activate(); + } else { + for (Fl_Type *o = Fl_Type::first; o; o = o->next) + if (o->selected && o->is_widget()) o->label(i->value()); + } +} + +//////////////////////////////////////////////////////////////// + +// turn number to string or string to number for saving to file: +// does not work for hierarchial menus! + +const char *item_name(Fl_Menu_Item* m, int i) { + if (m) { + while (m->label()) { + if (m->argument() == i) return m->label(); + m++; + } + } + static char buffer[20]; + sprintf(buffer, "%d", i); + return buffer; +} +int item_number(Fl_Menu_Item* m, const char* i) { + if (m && i) { + if (i[0]=='F' && i[1]=='L' && i[2]=='_') i += 3; + while (m->label()) { + if (!strcmp(m->label(), i)) return int(m->argument()); + m++; + } + } + return atoi(i); +} + +#define ZERO_ENTRY 1000 + +Fl_Menu_Item boxmenu[] = { +{"NO_BOX",0,0,(void *)ZERO_ENTRY}, +{"boxes",0,0,0,FL_SUBMENU}, +{"UP_BOX",0,0,(void *)FL_UP_BOX}, +{"DOWN_BOX",0,0,(void *)FL_DOWN_BOX}, +{"FLAT_BOX",0,0,(void *)FL_FLAT_BOX}, +{"BORDER_BOX",0,0,(void *)FL_BORDER_BOX}, +{"THIN_UP_BOX",0,0,(void *)FL_THIN_UP_BOX}, +{"THIN_DOWN_BOX",0,0,(void *)FL_THIN_DOWN_BOX}, +{"ENGRAVED_BOX",0,0,(void *)FL_ENGRAVED_BOX}, +{"EMBOSSED_BOX",0,0,(void *)FL_EMBOSSED_BOX}, +{"ROUND_UP_BOX",0,0,(void *)FL_ROUND_UP_BOX}, +{"ROUND_DOWN_BOX",0,0,(void *)FL_ROUND_DOWN_BOX}, +{"DIAMOND_UP_BOX",0,0,(void *)FL_DIAMOND_UP_BOX}, +{"DIAMOND_DOWN_BOX",0,0,(void *)FL_DIAMOND_DOWN_BOX}, +{"SHADOW_BOX",0,0,(void *)FL_SHADOW_BOX}, +{"ROUNDED_BOX",0,0,(void *)FL_ROUNDED_BOX}, +{"RSHADOW_BOX",0,0,(void *)FL_RSHADOW_BOX}, +{"RFLAT_BOX",0,0,(void *)FL_RFLAT_BOX}, +{"OVAL_BOX",0,0,(void *)FL_OVAL_BOX}, +{"OSHADOW_BOX",0,0,(void *)FL_OSHADOW_BOX}, +{"OFLAT_BOX",0,0,(void *)FL_OFLAT_BOX}, +{0}, +{"frames",0,0,0,FL_SUBMENU}, +{"UP_FRAME",0,0,(void *)FL_UP_FRAME}, +{"DOWN_FRAME",0,0,(void *)FL_DOWN_FRAME}, +{"THIN_UP_FRAME",0,0,(void *)FL_THIN_UP_FRAME}, +{"THIN_DOWN_FRAME",0,0,(void *)FL_THIN_DOWN_FRAME}, +{"ENGRAVED_FRAME",0,0,(void *)FL_ENGRAVED_FRAME}, +{"EMBOSSED_FRAME",0,0,(void *)FL_EMBOSSED_FRAME}, +{"BORDER_FRAME",0,0,(void *)FL_BORDER_FRAME}, +{"SHADOW_FRAME",0,0,(void *)FL_SHADOW_FRAME}, +{"ROUNDED_FRAME",0,0,(void *)FL_ROUNDED_FRAME}, +{"OVAL_FRAME",0,0,(void *)FL_OVAL_FRAME}, +{0}, +{0}}; + +const char *boxname(int i) { + if (!i) i = ZERO_ENTRY; + for (int j = 0; j < int(sizeof(boxmenu)/sizeof(*boxmenu)); j++) + if (boxmenu[j].argument() == i) return boxmenu[j].label(); + return 0; +} + +int boxnumber(const char *i) { + if (i[0]=='F' && i[1]=='L' && i[2]=='_') i += 3; + for (int j = 0; j < int(sizeof(boxmenu)/sizeof(*boxmenu)); j++) + if (boxmenu[j].label() && !strcmp(boxmenu[j].label(), i)) { + return int(boxmenu[j].argument()); + } + return 0; +} + +void box_cb(Fl_Choice* i, void *v) { + if (v == LOAD) { + if (current_widget->is_menu_item()) {i->hide(); return;} else i->show(); + int n = current_widget->o->box(); if (!n) n = ZERO_ENTRY; + for (int j = 0; j < int(sizeof(boxmenu)/sizeof(*boxmenu)); j++) + if (boxmenu[j].argument() == n) {i->value(j); break;} + } else { + int m = i->value(); + int n = int(boxmenu[m].argument()); + if (!n) return; // should not happen + if (n == ZERO_ENTRY) n = 0; + for (Fl_Type *o = Fl_Type::first; o; o = o->next) + if (o->selected && o->is_widget()) { + Fl_Widget_Type* q = (Fl_Widget_Type*)o; + q->o->box((Fl_Boxtype)n); + q->redraw(); + } + } +} + +void down_box_cb(Fl_Choice* i, void *v) { + if (v == LOAD) { + int n; + if (current_widget->is_button() && !current_widget->is_menu_item()) + n = ((Fl_Button*)(current_widget->o))->down_box(); + else if (current_widget->is_menu_button()) + n = ((Fl_Menu_*)(current_widget->o))->down_box(); + else { + i->hide(); return; + } + i->show(); + if (!n) n = ZERO_ENTRY; + for (int j = 0; j < int(sizeof(boxmenu)/sizeof(*boxmenu)); j++) + if (boxmenu[j].argument() == n) {i->value(j); break;} + } else { + int m = i->value(); + int n = int(boxmenu[m].argument()); + if (!n) return; // should not happen + if (n == ZERO_ENTRY) n = 0; + for (Fl_Type *o = Fl_Type::first; o; o = o->next) if (o->selected) { + if (o->is_button() && !o->is_menu_item()) { + Fl_Widget_Type* q = (Fl_Widget_Type*)o; + ((Fl_Button*)(q->o))->down_box((Fl_Boxtype)n); + if (((Fl_Button*)(q->o))->value()) q->redraw(); + } else if (o->is_menu_button()) { + Fl_Widget_Type* q = (Fl_Widget_Type*)o; + ((Fl_Menu_*)(q->o))->down_box((Fl_Boxtype)n); + } + } + } +} + +//////////////////////////////////////////////////////////////// + +Fl_Menu_Item whenmenu[] = { + {"never",0,0,(void*)ZERO_ENTRY}, + {"Release",0,0,(void*)FL_WHEN_RELEASE}, + {"Changed",0,0,(void*)FL_WHEN_CHANGED}, + {"Enter key",0,0,(void*)FL_WHEN_ENTER_KEY}, + //{"Release or Enter",0,0,(void*)(FL_WHEN_ENTER_KEY|FL_WHEN_RELEASE)}, + {0}}; + +void when_cb(Fl_Choice* i, void *v) { + if (v == LOAD) { + if (current_widget->is_menu_item()) {i->hide(); return;} else i->show(); + int n = current_widget->o->when() & (~FL_WHEN_NOT_CHANGED); + if (!n) n = ZERO_ENTRY; + for (int j = 0; j < int(sizeof(whenmenu)/sizeof(*whenmenu)); j++) + if (whenmenu[j].argument() == n) {i->value(j); break;} + } else { + int m = i->value(); + int n = int(whenmenu[m].argument()); + if (!n) return; // should not happen + if (n == ZERO_ENTRY) n = 0; + for (Fl_Type *o = Fl_Type::first; o; o = o->next) + if (o->selected && o->is_widget()) { + Fl_Widget_Type* q = (Fl_Widget_Type*)o; + q->o->when(n|(q->o->when()&FL_WHEN_NOT_CHANGED)); + } + } +} + +void when_button_cb(Fl_Light_Button* i, void *v) { + if (v == LOAD) { + if (current_widget->is_menu_item()) {i->hide(); return;} else i->show(); + i->value(current_widget->o->when()&FL_WHEN_NOT_CHANGED); + } else { + int n = i->value() ? FL_WHEN_NOT_CHANGED : 0; + for (Fl_Type *o = Fl_Type::first; o; o = o->next) + if (o->selected && o->is_widget()) { + Fl_Widget_Type* q = (Fl_Widget_Type*)o; + q->o->when(n|(q->o->when()&~FL_WHEN_NOT_CHANGED)); + } + } +} + +uchar Fl_Widget_Type::resizable() const { + if (is_window()) return ((Fl_Window*)o)->resizable() != 0; + Fl_Group* p = (Fl_Group*)o->parent(); + if (p) return p->resizable() == o; + else return 0; +} + +void Fl_Widget_Type::resizable(uchar v) { + if (v) { + if (resizable()) return; + if (is_window()) ((Fl_Window*)o)->resizable(o); + else { + Fl_Group* p = (Fl_Group*)o->parent(); + if (p) p->resizable(o); + } + } else { + if (!resizable()) return; + if (is_window()) { + ((Fl_Window*)o)->resizable(0); + } else { + Fl_Group* p = (Fl_Group*)o->parent(); + if (p) p->resizable(0); + } + } +} + +void resizable_cb(Fl_Light_Button* i,void* v) { + if (v == LOAD) { + if (current_widget->is_menu_item()) {i->hide(); return;} + if (numselected > 1) {i->hide(); return;} + i->show(); + i->value(current_widget->resizable()); + } else { + current_widget->resizable(i->value()); + } +} + +void hotspot_cb(Fl_Light_Button* i,void* v) { + if (v == LOAD) { + if (numselected > 1) {i->hide(); return;} + if (current_widget->is_menu_item()) i->label("divider"); + else i->label("hotspot"); + i->show(); + i->value(current_widget->hotspot()); + } else { + current_widget->hotspot(i->value()); + if (current_widget->is_menu_item()) {current_widget->redraw(); return;} + if (i->value()) { + Fl_Type *p = current_widget->parent; + if (!p || !p->is_widget()) return; + while (!p->is_window()) p = p->parent; + for (Fl_Type *o = p->next; o && o->level > p->level; o = o->next) { + if (o->is_widget() && o != current_widget) + ((Fl_Widget_Type*)o)->hotspot(0); + } + } + } +} + +void visible_cb(Fl_Light_Button* i, void* v) { + if (v == LOAD) { + i->value(current_widget->o->visible()); + } else { + int n = i->value(); + for (Fl_Type *o = Fl_Type::first; o; o = o->next) + if (o->selected && o->is_widget()) { + Fl_Widget_Type* q = (Fl_Widget_Type*)o; + n ? q->o->show() : q->o->hide(); + q->redraw(); + } + } +} + +void active_cb(Fl_Light_Button* i, void* v) { + if (v == LOAD) { + i->value(current_widget->o->active()); + } else { + int n = i->value(); + for (Fl_Type *o = Fl_Type::first; o; o = o->next) + if (o->selected && o->is_widget()) { + Fl_Widget_Type* q = (Fl_Widget_Type*)o; + n ? q->o->activate() : q->o->deactivate(); + q->redraw(); + } + } +} + +//////////////////////////////////////////////////////////////// + +Fl_Menu_Item fontmenu[] = { +{"Helvetica"}, +{"Helvetica bold"}, +{"Helvetica italic"}, +{"Helvetica bold italic"}, +{"Courier"}, +{"Courier bold"}, +{"Courier italic"}, +{"Courier bold italic"}, +{"Times"}, +{"Times bold"}, +{"Times italic"}, +{"Times bold italic"}, +{"Symbol"}, +{"Terminal"}, +{"Terminal Bold"}, +{"Zapf Dingbats"}, +{0}}; + +void labelfont_cb(Fl_Choice* i, void *v) { + if (v == LOAD) { + int n = current_widget->o->labelfont(); + if (n > 15) n = 0; + i->value(n); + } else { + int n = i->value(); + for (Fl_Type *o = Fl_Type::first; o; o = o->next) + if (o->selected && o->is_widget()) { + Fl_Widget_Type* q = (Fl_Widget_Type*)o; + q->o->labelfont(n); + q->redraw(); + } + } +} + +void labelsize_cb(Fl_Value_Input* i, void *v) { + int n; + if (v == LOAD) { + n = current_widget->o->labelsize(); + } else { + n = int(i->value()); + if (n <= 0) n = FL_NORMAL_SIZE; + for (Fl_Type *o = Fl_Type::first; o; o = o->next) + if (o->selected && o->is_widget()) { + Fl_Widget_Type* q = (Fl_Widget_Type*)o; + q->o->labelsize(n); + q->redraw(); + } + } + i->value(n); +} + +extern const char *ui_find_image_name; +void image_cb(Fl_Widget *a, void *) { + Fluid_Image *i = ui_find_image(current_widget->label()); + if (!ui_find_image_name) return; // user hit "Cancel" + // if i is zero then user picked a non-existent file. So that the + // directory they chose is preserved, we change to a normal text label. + for (Fl_Type *o = Fl_Type::first; o; o = o->next) + if (o->selected && o->is_widget()) { + Fl_Widget_Type* p = (Fl_Widget_Type*)o; + dont_touch_image = 1; + p->setimage(i); + p->label(ui_find_image_name); + dont_touch_image = 0; + } + label_cb(label_input,LOAD); + a->when(FL_WHEN_RELEASE|FL_WHEN_NOT_CHANGED); +} + +Fl_Menu_Item labeltypemenu[] = { + {"Image...",0,image_cb,(void*)(-1)}, + {"NORMAL_LABEL",0,0,(void*)0}, + {"SYMBOL_LABEL",0,0,(void*)FL_SYMBOL_LABEL}, + {"SHADOW_LABEL",0,0,(void*)FL_SHADOW_LABEL}, + {"ENGRAVED_LABEL",0,0,(void*)FL_ENGRAVED_LABEL}, + {"EMBOSSED_LABEL",0,0,(void*)FL_EMBOSSED_LABEL}, + {"NO_LABEL",0,0,(void*)(FL_NO_LABEL)}, +{0}}; + +void labeltype_cb(Fl_Choice* i, void *v) { + if (v == LOAD) { + int n; + if (current_widget->image) { + n = -1; + i->when(FL_WHEN_RELEASE|FL_WHEN_NOT_CHANGED); + } else { + n = current_widget->o->labeltype(); + i->when(FL_WHEN_RELEASE); + } + for (int j = 0; j < int(sizeof(labeltypemenu)/sizeof(*labeltypemenu)); j++) + if (labeltypemenu[j].argument() == n) {i->value(j); break;} + } else { + int m = i->value(); + int n = int(labeltypemenu[m].argument()); + if (n<0) return; // should not happen + if (current_widget->image) label_input->activate(); + for (Fl_Type *o = Fl_Type::first; o; o = o->next) + if (o->selected && o->is_widget()) { + Fl_Widget_Type* p = (Fl_Widget_Type*)o; + if (p->image) { + p->setimage(0); + p->o->label(p->label()); + } + p->o->labeltype((Fl_Labeltype)n); + p->redraw(); + } + } +} + +//////////////////////////////////////////////////////////////// + +void color_cb(Fl_Button* i, void *v) { + Fl_Color c = current_widget->o->color(); + if (v == LOAD) { + if (current_widget->is_menu_item()) {i->hide(); return;} else i->show(); + } else { + Fl_Color d = fl_show_colormap(c); + if (d == c) return; + c = d; + for (Fl_Type *o = Fl_Type::first; o; o = o->next) + if (o->selected && o->is_widget()) { + Fl_Widget_Type* q = (Fl_Widget_Type*)o; + q->o->color(c); q->o->redraw(); + } + } + i->color(c); i->labelcolor(contrast(FL_BLACK,c)); i->redraw(); +} + +void color2_cb(Fl_Button* i, void *v) { + Fl_Color c = current_widget->o->selection_color(); + if (v == LOAD) { + if (current_widget->is_menu_item()) {i->hide(); return;} else i->show(); + } else { + Fl_Color d = fl_show_colormap(c); + if (d == c) return; + c = d; + for (Fl_Type *o = Fl_Type::first; o; o = o->next) + if (o->selected && o->is_widget()) { + Fl_Widget_Type* q = (Fl_Widget_Type*)o; + q->o->selection_color(c); q->o->redraw(); + } + } + i->color(c); i->labelcolor(contrast(FL_BLACK,c)); i->redraw(); +} + +void labelcolor_cb(Fl_Button* i, void *v) { + Fl_Color c = current_widget->o->labelcolor(); + if (v != LOAD) { + Fl_Color d = fl_show_colormap(c); + if (d == c) return; + c = d; + for (Fl_Type *o = Fl_Type::first; o; o = o->next) + if (o->selected && o->is_widget()) { + Fl_Widget_Type* q = (Fl_Widget_Type*)o; + q->o->labelcolor(c); q->redraw(); + } + } + i->color(c); i->labelcolor(contrast(FL_BLACK,c)); i->redraw(); +} + +static Fl_Button* relative(Fl_Widget* o, int i) { + Fl_Group* g = (Fl_Group*)(o->parent()); + return (Fl_Button*)(g->child(g->find(*o)+i)); +} + +void align_cb(Fl_Button* i, void *v) { + int b = int(long(i->user_data())); + if (v == LOAD) { + if (current_widget->is_menu_item()) {i->hide(); return;} else i->show(); + i->value(current_widget->o->align() & b); + } else { + for (Fl_Type *o = Fl_Type::first; o; o = o->next) + if (o->selected && o->is_widget()) { + Fl_Widget_Type* q = (Fl_Widget_Type*)o; + int x = q->o->align(); + int y; + if (i->value()) { + y = x | b; + if (b == FL_ALIGN_LEFT || b == FL_ALIGN_TOP) { + Fl_Button *b1 = relative(i,+1); + b1->clear(); + y = y & ~(b1->argument()); + } + if (b == FL_ALIGN_RIGHT || b == FL_ALIGN_BOTTOM) { + Fl_Button *b1 = relative(i,-1); + b1->clear(); + y = y & ~(b1->argument()); + } + } else { + y = x & ~b; + } + if (x != y) {q->o->align(y); q->redraw();} + } + } +} + +//////////////////////////////////////////////////////////////// + +void callback_cb(Fl_Input* i, void *v) { + if (v == LOAD) { + i->static_value(current_widget->callback()); + } else { + const char *c = i->value(); + const char *d = c_check(c); + if (d) {fl_show_message("Error in callback:",d,0); haderror = 1; return;} + for (Fl_Type *o = Fl_Type::first; o; o = o->next) if (o->selected) { + o->callback(c); + } + } +} + +void user_data_cb(Fl_Input *i, void *v) { + if (v == LOAD) { + i->static_value(current_widget->user_data()); + } else { + const char *c = i->value(); + const char *d = c_check(c); + if (d) {fl_show_message("Error in user_data:",d,0); haderror = 1; return;} + for (Fl_Type *o = Fl_Type::first; o; o = o->next) if (o->selected) { + o->user_data(c); + } + } +} + +void user_data_type_cb(Fl_Input *i, void *v) { + static const char *dflt = "void*"; + if (v == LOAD) { + const char *c = current_widget->user_data_type(); + if (!c) c = dflt; + i->static_value(c); + } else { + const char *c = i->value(); + if (!*c) i->value(dflt); + else if (!strcmp(c,dflt)) c = 0; + const char *d = c_check(c); + if (!d) { + if (c && *c && c[strlen(c)-1] != '*' && strcmp(c,"long")) + d = "must be pointer or long"; + } + if (d) {fl_show_message("Error in type:",d,0); haderror = 1; return;} + for (Fl_Type *o = Fl_Type::first; o; o = o->next) if (o->selected) { + o->user_data_type(c); + } + } +} + +// "v_attributes" let user type in random code for attribute settings: + +void v_input_cb(Fl_Input* i, void* v) { + int n = int(long(i->user_data())); + if (v == LOAD) { + i->static_value(current_widget->extra_code(n)); + } else { + const char *c = i->value(); + const char *d = c_check(c&&c[0]=='#' ? c+1 : c); + if (d) {fl_show_message("Error in",i->label(),d); haderror = 1; return;} + for (Fl_Type *o = Fl_Type::first; o; o = o->next) + if (o->selected && o->is_widget()) { + Fl_Widget_Type *t = (Fl_Widget_Type*)o; + t->extra_code(n,c); + } + } +} + +void subclass_cb(Fl_Input* i, void* v) { + if (v == LOAD) { + if (current_widget->is_menu_item()) {i->hide(); return;} else i->show(); + i->static_value(current_widget->subclass()); + } else { + const char *c = i->value(); + for (Fl_Type *o = Fl_Type::first; o; o = o->next) + if (o->selected && o->is_widget()) { + Fl_Widget_Type *t = (Fl_Widget_Type*)o; + t->subclass(c); + } + } +} + +//////////////////////////////////////////////////////////////// + +// textstuff: set textfont, textsize, textcolor attributes: + +// default widget returns 0 to indicate not-implemented: +int Fl_Widget_Type::textstuff(int, Fl_Font&, int&, Fl_Color&) {return 0;} + +void textfont_cb(Fl_Choice* i, void* v) { + Fl_Font n; int s; Fl_Color c; + if (v == LOAD) { + if (!current_widget->textstuff(0,n,s,c)) {i->hide(); return;} + i->show(); + if (n > 15) n = FL_HELVETICA; + i->value(n); + } else { + n = (Fl_Font)i->value(); + for (Fl_Type *o = Fl_Type::first; o; o = o->next) + if (o->selected && o->is_widget()) { + Fl_Widget_Type* q = (Fl_Widget_Type*)o; + q->textstuff(1,n,s,c); + q->o->redraw(); + } + } +} + +void textsize_cb(Fl_Value_Input* i, void* v) { + Fl_Font n; int s; Fl_Color c; + if (v == LOAD) { + if (!current_widget->textstuff(0,n,s,c)) {i->hide(); return;} + i->show(); + } else { + s = int(i->value()); + if (s <= 0) s = FL_NORMAL_SIZE; + for (Fl_Type *o = Fl_Type::first; o; o = o->next) + if (o->selected && o->is_widget()) { + Fl_Widget_Type* q = (Fl_Widget_Type*)o; + q->textstuff(2,n,s,c); + q->o->redraw(); + } + } + i->value(s); +} + +void textcolor_cb(Fl_Button* i, void* v) { + Fl_Font n; int s; Fl_Color c; + if (v == LOAD) { + if (!current_widget->textstuff(0,n,s,c)) {i->hide(); return;} + i->show(); + } else { + c = i->labelcolor(); + Fl_Color d = fl_show_colormap(c); + if (d == c) return; + c = d; + for (Fl_Type *o = Fl_Type::first; o; o = o->next) + if (o->selected && o->is_widget()) { + Fl_Widget_Type* q = (Fl_Widget_Type*)o; + q->textstuff(3,n,s,c); q->o->redraw(); + } + } + i->color(c); i->labelcolor(contrast(FL_BLACK,c)); i->redraw(); +} + +//////////////////////////////////////////////////////////////// +// Kludges to the panel for subclasses: + +void slider_size_cb(Fl_Value_Input* i, void* v) { + if (v == LOAD) { + if (current_widget->is_valuator()!=2) {i->hide(); return;} + i->show(); + i->value(((Fl_Slider*)(current_widget->o))->slider_size()); + } else { + double n = i->value(); + for (Fl_Type *o = Fl_Type::first; o; o = o->next) + if (o->selected && o->is_widget()) { + Fl_Widget_Type* q = (Fl_Widget_Type*)o; + if (q->is_valuator()==2) { + ((Fl_Slider*)(q->o))->slider_size(n); + q->o->redraw(); + } + } + } +} + +void min_cb(Fl_Value_Input* i, void* v) { + if (v == LOAD) { + if (!current_widget->is_valuator()) {i->hide(); return;} + i->show(); + i->value(((Fl_Valuator*)(current_widget->o))->minimum()); + } else { + double n = i->value(); + for (Fl_Type *o = Fl_Type::first; o; o = o->next) + if (o->selected && o->is_widget()) { + Fl_Widget_Type* q = (Fl_Widget_Type*)o; + if (q->is_valuator()) { + ((Fl_Valuator*)(q->o))->minimum(n); + q->o->redraw(); + } + } + } +} + +void max_cb(Fl_Value_Input* i, void* v) { + if (v == LOAD) { + if (!current_widget->is_valuator()) {i->hide(); return;} + i->show(); + i->value(((Fl_Valuator*)(current_widget->o))->maximum()); + } else { + double n = i->value(); + for (Fl_Type *o = Fl_Type::first; o; o = o->next) + if (o->selected && o->is_widget()) { + Fl_Widget_Type* q = (Fl_Widget_Type*)o; + if (q->is_valuator()) { + ((Fl_Valuator*)(q->o))->maximum(n); + q->o->redraw(); + } + } + } +} + +void step_cb(Fl_Value_Input* i, void* v) { + if (v == LOAD) { + if (!current_widget->is_valuator()) {i->hide(); return;} + i->show(); + i->value(((Fl_Valuator*)(current_widget->o))->step()); + } else { + double n = i->value(); + for (Fl_Type *o = Fl_Type::first; o; o = o->next) + if (o->selected && o->is_widget()) { + Fl_Widget_Type* q = (Fl_Widget_Type*)o; + if (q->is_valuator()) { + ((Fl_Valuator*)(q->o))->step(n); + q->o->redraw(); + } + } + } +} + +void value_cb(Fl_Value_Input* i, void* v) { + if (v == LOAD) { + if (current_widget->is_valuator()) { + i->show(); + i->value(((Fl_Valuator*)(current_widget->o))->value()); + } else if (current_widget->is_button()) { + i->show(); + i->value(((Fl_Button*)(current_widget->o))->value()); + } else + i->hide(); + } else { + double n = i->value(); + for (Fl_Type *o = Fl_Type::first; o; o = o->next) + if (o->selected && o->is_widget()) { + Fl_Widget_Type* q = (Fl_Widget_Type*)o; + if (q->is_valuator()) { + ((Fl_Valuator*)(q->o))->value(n); + } else if (q->is_button()) { + ((Fl_Button*)(q->o))->value(n != 0); + if (q->is_menu_item()) q->redraw(); + } + } + } +} + +//////////////////////////////////////////////////////////////// + +// subtypes: + +Fl_Menu_Item *Fl_Widget_Type::subtypes() {return 0;} + +void subtype_cb(Fl_Choice* i, void* v) { + if (v == LOAD) { + Fl_Menu_Item* m = current_widget->subtypes(); + if (!m) {i->hide(); return;} + i->menu(m); + int j; + for (j = 0;; j++) { + if (!m[j].text) {j = 0; break;} + if (m[j].argument() == current_widget->o->type()) break; + } + i->value(j); + i->show(); + i->redraw(); + } else { + int n = int(i->mvalue()->argument()); + Fl_Menu_Item* m = current_widget->subtypes(); + for (Fl_Type *o = Fl_Type::first; o; o = o->next) + if (o->selected && o->is_widget()) { + Fl_Widget_Type* q = (Fl_Widget_Type*)o; + if (q->subtypes()==m) { + q->o->type(n); + q->redraw(); + } + } + } +} + +//////////////////////////////////////////////////////////////// + +static Fl_Window *the_panel; + +void propagate_load(Fl_Group* g, void* v) { + if (v == LOAD) { + Fl_Widget*const* a = g->array(); + for (int i=g->children(); i--;) { + Fl_Widget* o = *a++; + o->do_callback(o,LOAD); + } + } +} + +void set_cb(Fl_Button*, void*) { + haderror = 0; + Fl_Widget*const* a = the_panel->array(); + for (int i=the_panel->children(); i--;) { + Fl_Widget* o = *a++; + if (o->changed()) { + o->do_callback(); + if (haderror) return; + o->clear_changed(); + } + } +} + +void ok_cb(Fl_Return_Button* o, void* v) { + set_cb(o,v); + if (!haderror) the_panel->hide(); +} + +void revert_cb(Fl_Button*, void*) { + // We have to revert all dynamically changing fields: + // but for now only the first label works... + if (numselected == 1) current_widget->label(oldlabel); + propagate_load(the_panel, LOAD); +} + +void cancel_cb(Fl_Button* o, void* v) { + revert_cb(o,v); + the_panel->hide(); +} + +void toggle_overlays(Fl_Widget *,void *); // in Fl_Window_Type.C +void overlay_cb(Fl_Button*o,void *v) { + toggle_overlays(o,v); +} + +// update the panel according to current widget set: +static void load_panel() { + if (!the_panel) return; + + // find all the Fl_Widget subclasses currently selected: + numselected = 0; + current_widget = 0; + if (Fl_Type::current) { + if (Fl_Type::current->is_widget()) + current_widget=(Fl_Widget_Type*)Fl_Type::current; + for (Fl_Type *o = Fl_Type::first; o; o = o->next) { + if (o->is_widget() && o->selected) { + numselected++; + if (!current_widget) current_widget = (Fl_Widget_Type*)o; + } + } + } + if (numselected) + propagate_load(the_panel, LOAD); + else + the_panel->hide(); +} + +// This is called when user double-clicks an item, open or update the panel: +void Fl_Widget_Type::open() { + if (!the_panel) the_panel = make_widget_panel(); + load_panel(); + if (numselected) the_panel->show(); +} + +Fl_Type *Fl_Type::current; + +extern void redraw_overlays(); +extern void redraw_browser(); + +// Called when ui changes what objects are selected: +// p is selected object, null for all deletions (we must throw away +// old panel in that case, as the object may no longer exist) +void selection_changed(Fl_Type *p) { + // store all changes to the current selected objects: + if (p && the_panel && the_panel->visible()) { + set_cb(0,0); + // if there was an error, we try to leave the selected set unchanged: + if (haderror) { + Fl_Type *q = 0; + for (Fl_Type *o = Fl_Type::first; o; o = o->next) { + o->new_selected = o->selected; + if (!q && o->selected) q = o; + } + if (!p || !p->selected) p = q; + Fl_Type::current = p; + redraw_browser(); + return; + } + } + // update the selected flags to new set: + Fl_Type *q = 0; + for (Fl_Type *o = Fl_Type::first; o; o = o->next) { + o->selected = o->new_selected; + if (!q && o->selected) q = o; + } + if (!p || !p->selected) p = q; + Fl_Type::current = p; + redraw_overlays(); + // load the panel with the new settings: + load_panel(); +} + +//////////////////////////////////////////////////////////////// +// Writing the C code: + +#include <ctype.h> + +// test to see if user named a function, or typed in code: +int is_name(const char *c) { + for (; *c; c++) if (ispunct(*c) && *c!='_') return 0; + return 1; +} + +// Test to see if name() is an array entry. If so, and this is the +// highest number, return name[num+1]. Return null if not the highest +// number or a field or function. Return name() if not an array entry. +const char *array_name(Fl_Widget_Type *o) { + const char *c = o->name(); + if (!c) return 0; + const char *d; + for (d = c; *d != '['; d++) { + if (!*d) return c; + if (ispunct(*d) && *d!='_') return 0; + } + int num = atoi(d+1); + int sawthis = 0; + for (Fl_Type *t = Fl_Type::first; t; t = t->next) { + if (t == o) {sawthis=1; continue;} + const char *e = t->name(); + if (!e) continue; + if (strncmp(c,e,d-c)) continue; + int n1 = atoi(e+(d-c)+1); + if (n1 > num || n1==num && sawthis) return 0; + } + static char buffer[128]; + strncpy(buffer,c,d-c+1); + sprintf(buffer+(d-c+1),"%d]",num+1); + return buffer; +} + +// Test to see if extra code is a declaration: +int isdeclare(const char *c) { + while (isspace(*c)) c++; + if (*c == '#') return 1; + if (!strncmp(c,"extern",6)) return 1; + return 0; +} + +void Fl_Widget_Type::write_declare() { + const char *t = subclassname(this); + if (!subclass()) ::write_declare("#include <FL/%s.H>", t); + if (callback() && is_name(callback())) + ::write_declare("extern void %s(%s*, %s);", callback(), t, + user_data_type() ? user_data_type() : "void*"); + for (int n=0; n < NUM_EXTRA_CODE; n++) { + if (extra_code(n) && isdeclare(extra_code(n))) + ::write_declare("%s", extra_code(n)); + } +} + +void Fl_Widget_Type::write_static() { + const char* t = subclassname(this); + const char* c = array_name(this); + const char* k = class_name(); + if (c && !k) { + write_c("\n"); + if (!public_) write_c("static "); + else write_h("extern %s *%s;\n", t, c); + write_c("%s *%s;\n", t, c); + } + if (callback() && !is_name(callback())) { + // see if 'o' or 'v' used, to prevent unused argument warnings: + int use_o = 0; + int use_v = 0; + const char *d; + for (d = callback(); *d;) { + if (*d == 'o' && !is_id(d[1])) use_o = 1; + if (*d == 'v' && !is_id(d[1])) use_v = 1; + do d++; while (is_id(*d)); + while (*d && !is_id(*d)) d++; + } + const char* cn = callback_name(); + if (k) { + write_c("\ninline void %s::%s_i(%s*", k, cn, t); + } else { + write_c("\nstatic void %s(%s*", cn, t); + } + if (use_o) write_c(" o"); + const char* ut = user_data_type() ? user_data_type() : "void*"; + write_c(", %s", ut); + if (use_v) write_c(" v"); + write_c(") {\n %s", callback()); + if (*(d-1) != ';') write_c(";"); + write_c("\n}\n"); + if (k) { + write_c("void %s::%s(%s* o, %s v) {\n", k, cn, t, ut); + write_c(" ((%s*)(o->", k); + for (Fl_Type* p = parent; p->is_widget(); p = p->parent) + write_c("parent()->"); + write_c("user_data()))->%s_i(o,v);\n}\n", cn); + } + } + if (image) { + if (image->written != write_number) { + image->write_static(); + image->written = write_number; + } + } +} + +const char *Fl_Type::callback_name() { + if (is_name(callback())) return callback(); + return unique_id(this, "cb", name(), label()); +} + +extern int varused_test, varused; + +void Fl_Widget_Type::write_code1() { + const char* t = subclassname(this); + const char *c = array_name(this); + if (c) { + if (class_name()) { + write_public(public_); + write_h(" %s *%s;\n", t, c); + } else if (!public_) + write_h("extern %s *%s;\n", t, c); + } + if (class_name() && callback() && !is_name(callback())) { + const char* cn = callback_name(); + const char* ut = user_data_type() ? user_data_type() : "void*"; + write_public(0); + write_h(" inline void %s_i(%s*, %s);\n", cn, t, ut); + write_h(" static void %s(%s*, %s);\n", cn, t, ut); + } + // figure out if local varaible will be used (prevent compiler warnings): + if (is_parent()) + varused = 1; + else { + varused_test = 1; varused = 0; + write_widget_code(); + varused_test = 0; + for (int n=0; n < NUM_EXTRA_CODE; n++) + if (extra_code(n) && !isdeclare(extra_code(n))) varused = 1; + } + write_c(indent()); + if (varused) write_c("{ %s* o = ", t); + if (name()) write_c("%s = ", name()); + if (is_window()) { + write_c("w = new %s(%d, %d", t, o->w(), o->h()); + // prevent type() code from being emitted: + ((Fl_Widget_Type*)factory)->o->type(o->type()); + } else { + write_c("new %s(%d, %d, %d, %d", t, o->x(), o->y(), o->w(), o->h()); + } + if (!image && label() && *label()) { + write_c(", "); + write_cstring(label()); + } + write_c(");\n"); + indentation += 2; + if (varused) write_widget_code(); +} + +// this is split from write_code1() for Fl_Window_Type: +void Fl_Widget_Type::write_widget_code() { + Fl_Widget* tplate = ((Fl_Widget_Type*)factory)->o; + if (o->type() != tplate->type()) + write_c("%so->type(%d);\n", indent(), o->type()); + if (o->box() != tplate->box()) + write_c("%so->box(FL_%s);\n", indent(), boxname(o->box())); + if (is_button()) { + Fl_Button* b = (Fl_Button*)o; + if (b->down_box()) write_c("%so->down_box(FL_%s);\n", indent(), + boxname(b->down_box())); + if (b->value()) write_c("%so->value(1);\n", indent()); + if (b->shortcut()) + write_c("%so->shortcut(0x%x);\n", indent(), b->shortcut()); + } + if (is_menu_button()) { + Fl_Menu_* b = (Fl_Menu_*)o; + if (b->down_box()) write_c("%so->down_box(FL_%s);\n", indent(), + boxname(b->down_box())); + } + if (o->color() != tplate->color()) + write_c("%so->color(%d);\n", indent(), o->color()); + if (o->selection_color() != tplate->selection_color()) + write_c("%so->selection_color(%d);\n", indent(), o->selection_color()); + if (image) + image->write_code(); + else if (o->labeltype() != tplate->labeltype()) + write_c("%so->labeltype(FL_%s);\n", indent(), + item_name(labeltypemenu, o->labeltype())); + if (o->labelfont() != tplate->labelfont()) + write_c("%so->labelfont(%d);\n", indent(), o->labelfont()); + if (o->labelsize() != tplate->labelsize()) + write_c("%so->labelsize(%d);\n", indent(), o->labelsize()); + if (o->labelcolor() != tplate->labelcolor()) + write_c("%so->labelcolor(%d);\n", indent(), o->labelcolor()); + if (is_valuator()) { + Fl_Valuator* v = (Fl_Valuator*)o; + Fl_Valuator* f = (Fl_Valuator*)(tplate); + if (v->minimum()!=f->minimum()) + write_c("%so->minimum(%g);\n", indent(), v->minimum()); + if (v->maximum()!=f->maximum()) + write_c("%so->maximum(%g);\n", indent(), v->maximum()); + if (v->step()!=f->step()) + write_c("%so->step(%g);\n", indent(), v->step()); + if (v->value()) + write_c("%so->value(%g);\n", indent(), v->value()); + if (is_valuator()==2) { + double x = ((Fl_Slider*)v)->slider_size(); + double y = ((Fl_Slider*)f)->slider_size(); + if (x != y) write_c("%so->slider_size(%g);\n", indent(), x); + } + } + {Fl_Font ff; int fs; Fl_Color fc; if (textstuff(4,ff,fs,fc)) { + Fl_Font f; int s; Fl_Color c; textstuff(0,f,s,c); + if (f != ff) write_c("%so->textfont(%d);\n", indent(), f); + if (s != fs) write_c("%so->textsize(%d);\n", indent(), s); + if (c != fc) write_c("%so->textcolor(%d);\n",indent(), c); + }} + const char* ud = user_data(); + if (class_name() && !parent->is_widget()) ud = "this"; + if (callback()) { + write_c("%so->callback((Fl_Callback*)%s", indent(), callback_name()); + if (ud) + write_c(", (void*)(%s));\n", ud); + else + write_c(");\n"); + } else if (ud) { + write_c("%so->user_data((void*)(%s));\n", indent(), ud); + } + if (o->align() != tplate->align()) + write_c("%so->align(%d);\n", indent(), o->align()); + if (o->when() != tplate->when()) + write_c("%so->when(%d);\n", indent(), o->when()); + if (!o->visible() && o->parent()) + write_c("%so->hide();\n", indent()); + if (!o->active()) + write_c("%so->deactivate();\n", indent()); + if (!is_group() && resizable()) + write_c("%sFl_Group::current()->resizable(o);\n",indent()); + if (hotspot()) + write_c("%sw->hotspot(o);\n", indent()); +} + +void Fl_Widget_Type::write_code2() { + indentation -= 2; + if (!is_parent() && !varused) return; + for (int n=0; n < NUM_EXTRA_CODE; n++) + if (extra_code(n) && !isdeclare(extra_code(n))) + write_c("%s %s\n", indent(), extra_code(n)); + write_c("%s}\n", indent()); +} + +//////////////////////////////////////////////////////////////// + +void Fl_Widget_Type::write_properties() { + Fl_Type::write_properties(); + write_indent(level+1); + if (!public_) write_string("private"); + write_string("xywh {%d %d %d %d}", o->x(), o->y(), o->w(), o->h()); + Fl_Widget* tplate = ((Fl_Widget_Type*)factory)->o; + if (o->type() != tplate->type()) { + write_string("type"); + write_word(item_name(subtypes(), o->type())); + } + if (o->box() != tplate->box()) { + write_string("box"); write_word(boxname(o->box()));} + if (is_button()) { + Fl_Button* b = (Fl_Button*)o; + if (b->down_box()) { + write_string("down_box"); write_word(boxname(b->down_box()));} + if (b->shortcut()) write_string("shortcut 0x%x", b->shortcut()); + if (b->value()) write_string("value 1"); + } + if (is_menu_button()) { + Fl_Menu_* b = (Fl_Menu_*)o; + if (b->down_box()) { + write_string("down_box"); write_word(boxname(b->down_box()));} + } + if (o->color()!=tplate->color()) + write_string("color %d", o->color()); + if (o->selection_color()!=tplate->selection_color()) + write_string("selection_color %d", o->selection_color()); + if (image) + write_string("labeltype image"); + else if (o->labeltype()!=tplate->labeltype()) { + write_string("labeltype"); + write_word(item_name(labeltypemenu, o->labeltype())); + } + if (o->labelfont()!=tplate->labelfont()) + write_string("labelfont %d", o->labelfont()); + if (o->labelsize()!=tplate->labelsize()) + write_string("labelsize %d", o->labelsize()); + if (o->labelcolor()!=tplate->labelcolor()) + write_string("labelcolor %d", o->labelcolor()); + if (o->align()!=tplate->align()) + write_string("align %d", o->align()); + if (o->when() != tplate->when()) + write_string("when %d", o->when()); + if (is_valuator()) { + Fl_Valuator* v = (Fl_Valuator*)o; + Fl_Valuator* f = (Fl_Valuator*)(tplate); + if (v->minimum()!=f->minimum()) write_string("minimum %g",v->minimum()); + if (v->maximum()!=f->maximum()) write_string("maximum %g",v->maximum()); + if (v->step()!=f->step()) write_string("step %g",v->step()); + if (v->value()!=0.0) write_string("value %g",v->value()); + if (is_valuator()==2) { + double x = ((Fl_Slider*)v)->slider_size(); + double y = ((Fl_Slider*)f)->slider_size(); + if (x != y) write_string("slider_size %g", x); + } + } + {Fl_Font ff; int fs; Fl_Color fc; if (textstuff(4,ff,fs,fc)) { + Fl_Font f; int s; Fl_Color c; textstuff(0,f,s,c); + if (f != ff) write_string("textfont %d", f); + if (s != fs) write_string("textsize %d", s); + if (c != fc) write_string("textcolor %d", c); + }} + if (!o->visible()) write_string("hide"); + if (!o->active()) write_string("deactivate"); + if (resizable()) write_string("resizable"); + if (hotspot()) write_string(is_menu_item() ? "divider" : "hotspot"); + for (int n=0; n < NUM_EXTRA_CODE; n++) if (extra_code(n)) { + write_indent(level+1); + write_string("code%d",n); + write_word(extra_code(n)); + } + if (subclass()) { + write_indent(level+1); + write_string("class"); + write_word(subclass()); + } +} + +int pasteoffset; + +void Fl_Widget_Type::read_property(const char *c) { + int x,y,w,h; Fl_Font f; int s; Fl_Color cc; + if (!strcmp(c,"private")) { + public_ = 0; + } else if (!strcmp(c,"xywh")) { + if (sscanf(read_word(),"%d %d %d %d",&x,&y,&w,&h) == 4) { + x += pasteoffset; + y += pasteoffset; + o->resize(x,y,w,h); + } + } else if (!strcmp(c,"type")) { + o->type(item_number(subtypes(), read_word())); + } else if (!strcmp(c,"box")) { + const char* value = read_word(); + if ((x = boxnumber(value))) { + if (x == ZERO_ENTRY) x = 0; + o->box((Fl_Boxtype)x); + } else if (sscanf(value,"%d",&x) == 1) o->box((Fl_Boxtype)x); + } else if (is_button() && !strcmp(c,"down_box")) { + const char* value = read_word(); + if ((x = boxnumber(value))) { + if (x == ZERO_ENTRY) x = 0; + ((Fl_Button*)o)->down_box((Fl_Boxtype)x); + } + } else if (is_menu_button() && !strcmp(c,"down_box")) { + const char* value = read_word(); + if ((x = boxnumber(value))) { + if (x == ZERO_ENTRY) x = 0; + ((Fl_Menu_*)o)->down_box((Fl_Boxtype)x); + } + } else if (is_button() && !strcmp(c,"value")) { + const char* value = read_word(); + ((Fl_Button*)o)->value(atoi(value)); + } else if (!strcmp(c,"color")) { + int n = sscanf(read_word(),"%d %d",&x,&y); + if (n == 2) { // back compatability... + if (x != 47) o->color(x); + o->selection_color(y); + } else { + o->color(x); + } + } else if (!strcmp(c,"selection_color")) { + if (sscanf(read_word(),"%d",&x)) o->selection_color(x); + } else if (!strcmp(c,"labeltype")) { + c = read_word(); + if (!strcmp(c,"image")) { + Fluid_Image *i = Fluid_Image::find(label()); + if (!i) read_error("Image file '%s' not found", label()); + else setimage(i); + } else { + o->labeltype((Fl_Labeltype)item_number(labeltypemenu,c)); + } + } else if (!strcmp(c,"labelfont")) { + if (sscanf(read_word(),"%d",&x) == 1) o->labelfont(x); + } else if (!strcmp(c,"labelsize")) { + if (sscanf(read_word(),"%d",&x) == 1) o->labelsize(x); + } else if (!strcmp(c,"labelcolor")) { + if (sscanf(read_word(),"%d",&x) == 1) o->labelcolor(x); + } else if (!strcmp(c,"align")) { + if (sscanf(read_word(),"%d",&x) == 1) o->align(x); + } else if (!strcmp(c,"when")) { + if (sscanf(read_word(),"%d",&x) == 1) o->when(x); + } else if (!strcmp(c,"minimum") && is_valuator()) { + ((Fl_Valuator*)o)->minimum(strtod(read_word(),0)); + } else if (!strcmp(c,"maximum") && is_valuator()) { + ((Fl_Valuator*)o)->maximum(strtod(read_word(),0)); + } else if (!strcmp(c,"step") && is_valuator()) { + ((Fl_Valuator*)o)->step(strtod(read_word(),0)); + } else if (!strcmp(c,"value") && is_valuator()) { + ((Fl_Valuator*)o)->value(strtod(read_word(),0)); + } else if ((!strcmp(c,"slider_size")||!strcmp(c,"size"))&&is_valuator()==2) { + ((Fl_Slider*)o)->slider_size(strtod(read_word(),0)); + } else if (!strcmp(c,"textfont")) { + if (sscanf(read_word(),"%d",&x) == 1) {f=(Fl_Font)x; textstuff(1,f,s,cc);} + } else if (!strcmp(c,"textsize")) { + if (sscanf(read_word(),"%d",&x) == 1) {s=x; textstuff(2,f,s,cc);} + } else if (!strcmp(c,"textcolor")) { + if (sscanf(read_word(),"%d",&x) == 1) {cc=(Fl_Color)x;textstuff(3,f,s,cc);} + } else if (!strcmp(c,"hide")) { + o->hide(); + } else if (!strcmp(c,"deactivate")) { + o->deactivate(); + } else if (!strcmp(c,"resizable")) { + resizable(1); + } else if (!strcmp(c,"hotspot") || !strcmp(c, "divider")) { + hotspot(1); + } else if (!strcmp(c,"class")) { + subclass(read_word()); + } else if (is_button() && !strcmp(c,"shortcut")) { + ((Fl_Button*)o)->shortcut(strtol(read_word(),0,0)); + } else { + if (!strncmp(c,"code",4)) { + int n = atoi(c+4); + if (n >= 0 && n <= NUM_EXTRA_CODE) { + extra_code(n,read_word()); + return; + } + } + Fl_Type::read_property(c); + } +} + +Fl_Menu_Item boxmenu1[] = { + // these extra ones are for looking up fdesign saved strings: + {"NO_FRAME", 0,0,(void *)FL_NO_BOX}, + {"ROUNDED3D_UPBOX", 0,0,(void *)_FL_ROUND_UP_BOX}, + {"ROUNDED3D_DOWNBOX", 0,0,(void *)_FL_ROUND_DOWN_BOX}, + {"OVAL3D_UPBOX", 0,0,(void *)_FL_ROUND_UP_BOX}, + {"OVAL3D_DOWNBOX", 0,0,(void *)_FL_ROUND_DOWN_BOX}, + {"0", 0,0,(void *)ZERO_ENTRY}, + {"1", 0,0,(void *)FL_UP_BOX}, + {"2", 0,0,(void *)FL_DOWN_BOX}, + {"3", 0,0,(void *)FL_FLAT_BOX}, + {"4", 0,0,(void *)FL_BORDER_BOX}, + {"5", 0,0,(void *)FL_SHADOW_BOX}, + {"6", 0,0,(void *)FL_FRAME_BOX}, + {"7", 0,0,(void *)FL_ROUNDED_BOX}, + {"8", 0,0,(void *)FL_RFLAT_BOX}, + {"9", 0,0,(void *)FL_RSHADOW_BOX}, + {"10", 0,0,(void *)FL_UP_FRAME}, + {"11", 0,0,(void *)FL_DOWN_FRAME}, +{0}}; + +extern int fdesign_flip; +int lookup_symbol(const char *, int &, int numberok = 0); + +int Fl_Widget_Type::read_fdesign(const char* name, const char* value) { + int v; + if (!strcmp(name,"box")) { + float x,y,w,h; + if (sscanf(value,"%f %f %f %f",&x,&y,&w,&h) == 4) { + if (fdesign_flip) { + Fl_Type *p; + for (p = parent; p && !p->is_window(); p = p->parent); + if (p && p->is_widget()) y = ((Fl_Widget_Type*)p)->o->h()-(y+h); + } + x += pasteoffset; + y += pasteoffset; + o->resize(int(x),int(y),int(w),int(h)); + } + } else if (!strcmp(name,"label")) { + label(value); + if (value[0] == '@') o->labeltype(FL_SYMBOL_LABEL); + } else if (!strcmp(name,"name")) { + this->name(value); + } else if (!strcmp(name,"callback")) { + callback(value); user_data_type("long"); + } else if (!strcmp(name,"argument")) { + user_data(value); + } else if (!strcmp(name,"shortcut")) { + if (value[0]) { + char buf[128]; sprintf(buf,"o->shortcut(\"%s\");",value); + extra_code(0,buf); + } + } else if (!strcmp(name,"style")) { + if (!strncmp(value,"FL_NORMAL",9)) return 1; + if (!lookup_symbol(value,v,1)) return 0; + o->labelfont(v); o->labeltype((Fl_Labeltype)(v>>8)); + } else if (!strcmp(name,"size")) { + if (!lookup_symbol(value,v,1)) return 0; + o->labelsize(v); + } else if (!strcmp(name,"type")) { + if (!strncmp(value,"NORMAL",6)) return 1; + if (lookup_symbol(value,v,1)) {o->type(v); return 1;} + if (!strcmp(value+strlen(value)-5,"FRAME")) goto TRY_BOXTYPE; + if (!strcmp(value+strlen(value)-3,"BOX")) goto TRY_BOXTYPE; + return 0; + } else if (!strcmp(name,"lcol")) { + if (!lookup_symbol(value,v,1)) return 0; + o->labelcolor(v); + } else if (!strcmp(name,"return")) { + if (!lookup_symbol(value,v,0)) return 0; + o->when(v|FL_WHEN_RELEASE); + } else if (!strcmp(name,"alignment")) { + if (!lookup_symbol(value,v)) { + // convert old numeric values: + int v1 = atoi(value); if (v1 <= 0 && strcmp(value,"0")) return 0; + v = 0; + if (v1 >= 5) {v = FL_ALIGN_INSIDE; v1 -= 5;} + switch (v1) { + case 0: v += FL_ALIGN_TOP; break; + case 1: v += FL_ALIGN_BOTTOM; break; + case 2: v += FL_ALIGN_LEFT; break; + case 3: v += FL_ALIGN_RIGHT; break; + case 4: v += FL_ALIGN_CENTER; break; + default: return 0; + } + } + o->align(v); + } else if (!strcmp(name,"resizebox")) { + resizable(1); + } else if (!strcmp(name,"colors")) { + char* p = (char*)value; + while (*p != ' ') {if (!*p) return 0; p++;} + *p = 0; + int v1; + if (!lookup_symbol(value,v,1) || !lookup_symbol(p+1,v1,1)) { + *p=' '; return 0;} + o->color(v,v1); + } else if (!strcmp(name,"resize")) { + return !strcmp(value,"FL_RESIZE_ALL"); + } else if (!strcmp(name,"gravity")) { + return !strcmp(value,"FL_NoGravity FL_NoGravity"); + } else if (!strcmp(name,"boxtype")) { + TRY_BOXTYPE: + int x = boxnumber(value); + if (!x) {x = item_number(boxmenu1, value); if (x < 0) return 0;} + if (x == ZERO_ENTRY) { + x = 0; + if (o->box() != ((Fl_Widget_Type*)factory)->o->box()) return 1; // kludge for frame + } + o->box((Fl_Boxtype)x); + } else { + return 0; + } + return 1; +} diff --git a/fluid/Fl_Widget_Type.h b/fluid/Fl_Widget_Type.h new file mode 100644 index 000000000..c911054fa --- /dev/null +++ b/fluid/Fl_Widget_Type.h @@ -0,0 +1,67 @@ +// Fl_Widget_Type.H + +// Type for creating all subclasses of Fl_Widget +// This should have the widget pointer in it, but it is still in the +// Fl_Type base class. + +#include "Fl_Type.H" + +struct Fl_Menu_Item; +class Fluid_Image; + +#define NUM_EXTRA_CODE 4 + +class Fl_Widget_Type : public Fl_Type { + virtual Fl_Widget *widget(int,int,int,int) = 0; + virtual Fl_Widget_Type *_make() = 0; // virtual constructor + virtual void setlabel(const char *); + + const char *extra_code_[NUM_EXTRA_CODE]; + const char *subclass_; + uchar hotspot_; + +protected: + + void write_declare(); + void write_static(); + void write_code1(); + void write_widget_code(); + void write_code2(); + +public: + + const char *xclass; // junk string, used for shortcut + Fl_Widget *o; + int public_; + + Fluid_Image *image; + void setimage(Fluid_Image *); + + Fl_Widget_Type(); + Fl_Type *make(); + void open(); + + const char *extra_code(int n) const {return extra_code_[n];} + void extra_code(int n,const char *); + const char *subclass() const {return subclass_;} + void subclass(const char *); + uchar hotspot() const {return hotspot_;} + void hotspot(uchar v) {hotspot_ = v;} + uchar resizable() const; + void resizable(uchar v); + + virtual int textstuff(int what, Fl_Font &, int &, Fl_Color &); + virtual Fl_Menu_Item *subtypes(); + + virtual int is_widget() const; + + virtual void write_properties(); + virtual void read_property(const char *); + virtual int read_fdesign(const char*, const char*); + + ~Fl_Widget_Type(); + void redraw(); +}; + +void* const LOAD = (void *)9831; +extern Fl_Widget_Type *current_widget; // one of the selected ones diff --git a/fluid/Fl_Window_Type.cxx b/fluid/Fl_Window_Type.cxx new file mode 100644 index 000000000..044c8233f --- /dev/null +++ b/fluid/Fl_Window_Type.cxx @@ -0,0 +1,666 @@ +/* Fl_Window_Type.C + + The widget describing an Fl_Window. This is also all the code + for interacting with the overlay, which allows the user to + select, move, and resize the children widgets. + +*/ + +#include <FL/Fl.H> +#include <FL/Fl_Overlay_Window.H> +#include <FL/fl_message.H> +#include <FL/fl_draw.H> +#include <FL/Fl_Menu_Item.H> +#include "Fl_Widget_Type.H" +#include <math.h> +#include <stdlib.h> +#include "alignment_panel.H" +#include <stdio.h> + +int gridx = 5; +int gridy = 5; +int snap = 3; + +void alignment_cb(Fl_Input *i, long v) { + int n = atoi(i->value()); + if (n < 0) n = 0; + switch (v) { + case 1: gridx = n; break; + case 2: gridy = n; break; + case 3: snap = n; break; + } +} + +extern const char* header_file_name; +extern const char* code_file_name; + +void show_alignment_cb(Fl_Widget *, void *) { + make_alignment_window(); + header_file_input->value(header_file_name); + code_file_input->value(code_file_name); + char buf[128]; + sprintf(buf,"%d",gridx); horizontal_input->value(buf); + sprintf(buf,"%d",gridy); vertical_input->value(buf); + sprintf(buf,"%d",snap); snap_input->value(buf); + alignment_window->show(); +} + +void header_input_cb(Fl_Input* i, void*) { + header_file_name = i->value(); +} +void code_input_cb(Fl_Input* i, void*) { + code_file_name = i->value(); + printf("code file name set to %s\n", code_file_name); +} + +//////////////////////////////////////////////////////////////// + +static Fl_Menu_Item window_type_menu[] = { + {"Single",0,0,(void*)FL_WINDOW}, + {"Double",0,0,(void*)(FL_WINDOW+1)}, + {0}}; +class Fl_Window_Type : public Fl_Widget_Type { + Fl_Menu_Item* subtypes() {return window_type_menu;} + + friend class Overlay_Window; + int mx,my; // mouse position during dragging + int x1,y1; // initial position of selection box + int bx,by,br,bt; // bounding box of selection + int dx,dy; + int drag; // which parts of bbox are being moved + int numselected; // number of children selected + enum {LEFT=1,RIGHT=2,BOTTOM=4,TOP=8,DRAG=16,BOX=32}; + void draw_overlay(); + void newdx(); + void newposition(Fl_Widget_Type *,int &x,int &y,int &w,int &h); + int handle(int); + virtual void setlabel(const char *); + void write_code1(); + void write_code2(); + Fl_Widget_Type *_make() {return 0;} // we don't call this + Fl_Widget *widget(int,int,int,int) {return 0;} + int recalc; // set by fix_overlay() + +public: + + uchar modal, non_modal; + + Fl_Type *make(); + virtual const char *type_name() {return "Fl_Window";} + + void open(); + + void fix_overlay(); // update the bounding box, etc + + virtual void write_properties(); + virtual void read_property(const char *); + virtual int read_fdesign(const char*, const char*); + + void add_child(Fl_Type*, Fl_Type*); + void move_child(Fl_Type*, Fl_Type*); + void remove_child(Fl_Type*); + + int is_parent() const {return 1;} + int is_group() const {return 1;} + int is_window() const {return 1;} +}; + +static int overlays_invisible; + +// The following Fl_Widget is used to simulate the windows. It has +// an overlay for the fluid ui, and special-cases the FL_NO_BOX. + +class Overlay_Window : public Fl_Overlay_Window { + void draw(); + void draw_overlay(); +public: + Fl_Window_Type *window; + int handle(int); + Overlay_Window(int w,int h) : Fl_Overlay_Window(w,h) {Fl_Group::current(0);} + void resize(int,int,int,int); +}; +void Overlay_Window::draw() { + const int CHECKSIZE = 8; + // see if box is clear or a frame or rounded: + if ((damage()&128) && + (!box() || (box()>=4&&!(box()&2)) || box()>=_FL_ROUNDED_BOX)) { + // if so, draw checkerboard so user can see what areas are clear: + for (int y = 0; y < h(); y += CHECKSIZE) + for (int x = 0; x < w(); x += CHECKSIZE) { + fl_color(((y/(2*CHECKSIZE))&1) != ((x/(2*CHECKSIZE))&1) ? + FL_WHITE : FL_BLACK); + fl_rectf(x,y,CHECKSIZE,CHECKSIZE); + } + } + Fl_Overlay_Window::draw(); +} + +void Overlay_Window::draw_overlay() { + window->draw_overlay(); +} +int Overlay_Window::handle(int e) { + return window->handle(e); +} + +Fl_Type *Fl_Window_Type::make() { + Fl_Type *p = Fl_Type::current; + while (p && !p->is_code_block()) p = p->parent; + if (!p) { + fl_message("Please select a function"); + return 0; + } + Fl_Window_Type *o = new Fl_Window_Type(); + if (!this->o) {// template widget + this->o = new Fl_Window(100,100); + Fl_Group::current(0); + } + o->factory = this; + o->drag = 0; + o->numselected = 0; + Overlay_Window *w = new Overlay_Window(100,100); + w->window = o; + o->o = w; + o->add(p); + o->modal = 0; + o->non_modal = 0; + return o; +} + +void Fl_Window_Type::add_child(Fl_Type* cc, Fl_Type* before) { + Fl_Widget_Type* c = (Fl_Widget_Type*)cc; + Fl_Widget* b = before ? ((Fl_Widget_Type*)before)->o : 0; + ((Fl_Window*)o)->insert(*(c->o), b); + o->redraw(); +} + +void Fl_Window_Type::remove_child(Fl_Type* cc) { + Fl_Widget_Type* c = (Fl_Widget_Type*)cc; + ((Fl_Window*)o)->remove(c->o); + o->redraw(); +} + +void Fl_Window_Type::move_child(Fl_Type* cc, Fl_Type* before) { + Fl_Widget_Type* c = (Fl_Widget_Type*)cc; + ((Fl_Window*)o)->remove(c->o); + Fl_Widget* b = before ? ((Fl_Widget_Type*)before)->o : 0; + ((Fl_Window*)o)->insert(*(c->o), b); + o->redraw(); +} + +//////////////////////////////////////////////////////////////// + +// Double-click on window widget shows the window, or if already shown, +// it shows the control panel. +void Fl_Window_Type::open() { + Overlay_Window *w = (Overlay_Window *)o; + if (w->shown()) { + w->show(); + Fl_Widget_Type::open(); + } else { + Fl_Widget *p = w->resizable(); + if (!p) w->resizable(w); + w->show(); + w->resizable(p); + } +} + +// control panel items: +#include "widget_panel.H" + +void modal_cb(Fl_Light_Button* i, void* v) { + if (v == LOAD) { + if (!current_widget->is_window()) {i->hide(); return;} + i->show(); + i->value(((Fl_Window_Type *)current_widget)->modal); + } else { + ((Fl_Window_Type *)current_widget)->modal = i->value(); + } +} + +void non_modal_cb(Fl_Light_Button* i, void* v) { + if (v == LOAD) { + if (!current_widget->is_window()) {i->hide(); return;} + i->show(); + i->value(((Fl_Window_Type *)current_widget)->non_modal); + } else { + ((Fl_Window_Type *)current_widget)->non_modal = i->value(); + } +} + +void border_cb(Fl_Light_Button* i, void* v) { + if (v == LOAD) { + if (!current_widget->is_window()) {i->hide(); return;} + i->show(); + i->value(((Fl_Window*)(current_widget->o))->border()); + } else { + ((Fl_Window*)(current_widget->o))->border(i->value()); + } +} + +void xclass_cb(Fl_Input* i, void* v) { + if (v == LOAD) { + if (!current_widget->is_window()) {i->hide(); return;} + i->show(); + i->value(((Fl_Widget_Type *)current_widget)->xclass); + } else { + for (Fl_Type *o = Fl_Type::first; o; o = o->next) + if (o->selected && o->is_widget()) { + Fl_Widget_Type* w = (Fl_Widget_Type*)o; + if (w->is_window() || w->is_button()) + storestring(i->value(),w->xclass); + if (w->is_window()) ((Fl_Window*)(w->o))->xclass(w->xclass); + else if (w->is_menu_item()) w->redraw(); + } + } +} + +//////////////////////////////////////////////////////////////// + +void Fl_Window_Type::setlabel(const char *n) { + if (o) ((Fl_Window *)o)->label(n); +} + +// make() is called on this widget when user picks window off New menu: +Fl_Window_Type Fl_Window_type; + +// Resize from window manager, try to resize it back to a legal size. +// This is not proper X behavior, but works on 4DWM and fvwm +void Overlay_Window::resize(int X,int Y,int W,int H) { + if (!visible() || W==w() && H==h()) { + Fl_Overlay_Window::resize(X,Y,W,H); + return; + } + int nw = gridx&&W!=w() ? ((W+gridx/2)/gridx)*gridx : W; + int nh = gridy&&H!=h() ? ((H+gridy/2)/gridy)*gridy : H; + Fl_Widget* t = resizable(); resizable(0); + Fl_Overlay_Window::resize(X,Y,W,H); + resizable(t); + // make sure new window size surrounds the widgets: + int b = 0; + int r = 0; + for (Fl_Type *o=window->next; o && o->level>window->level; o=o->next) + if (o->is_widget() && !o->is_menu_item()) { + Fl_Widget* w = ((Fl_Widget_Type*)o)->o; + if (w->x()+w->w() > r) r = w->x()+w->w(); + if (w->y()+w->h() > b) b = w->y()+w->h(); + } + if (nh < b) nh = b; + if (nw < r) nw = r; + // If changed, tell the window manager. Skip really big windows + // that might be bigger than screen: + if (nw != W && nw < Fl::w()-100 || nh != H && nh < Fl::h()-100) size(nw,nh); +} + +// calculate actual move by moving mouse position (mx,my) to +// nearest multiple of gridsize, and snap to original position +void Fl_Window_Type::newdx() { + int dx, dy; + if (Fl::event_state(FL_ALT)) { + dx = mx-x1; + dy = my-y1; + } else { + int dx0 = mx-x1; + int ix = (drag&RIGHT) ? br : bx; + dx = gridx ? ((ix+dx0+gridx/2)/gridx)*gridx - ix : dx0; + if (dx0 > snap) { + if (dx < 0) dx = 0; + } else if (dx0 < -snap) { + if (dx > 0) dx = 0; + } else + dx = 0; + int dy0 = my-y1; + int iy = (drag&BOTTOM) ? by : bt; + dy = gridy ? ((iy+dy0+gridy/2)/gridy)*gridy - iy : dy0; + if (dy0 > snap) { + if (dy < 0) dy = 0; + } else if (dy0 < -snap) { + if (dy > 0) dy = 0; + } else + dy = 0; + } + if (this->dx != dx || this->dy != dy) { + this->dx = dx; this->dy = dy; + ((Overlay_Window *)(this->o))->redraw_overlay(); + } +} + +// Move a widget according to dx and dy calculated above +void Fl_Window_Type::newposition(Fl_Widget_Type *o,int &X,int &Y,int &R,int &T) { + X = o->o->x(); + Y = o->o->y(); + R = X+o->o->w(); + T = Y+o->o->h(); + if (!drag) return; + if (drag&DRAG) { + X += dx; + Y += dy; + R += dx; + T += dy; + } else { + if (drag&LEFT) if (X==bx) X += dx; else if (X<bx+dx) X = bx+dx; + if (drag&BOTTOM) if (Y==by) Y += dy; else if (Y<by+dy) Y = by+dy; + if (drag&RIGHT) if (R==br) R += dx; else if (R>br+dx) R = br+dx; + if (drag&TOP) if (T==bt) T += dy; else if (T>bt+dx) T = bt+dx; + } + if (R<X) {int n = X; X = R; R = n;} + if (T<Y) {int n = Y; Y = T; T = n;} +} + +void Fl_Window_Type::draw_overlay() { + if (recalc) { + bx = o->w(); by = o->h(); br = 0; bt = 0; + numselected = 0; + for (Fl_Type *q=next; q && q->level>level; q=q->next) + if (q->selected && q->is_widget() && !q->is_menu_item()) { + numselected++; + Fl_Widget_Type* o = (Fl_Widget_Type*)q; + if (o->o->x() < bx) bx = o->o->x(); + if (o->o->y() < by) by = o->o->y(); + if (o->o->x()+o->o->w() > br) br = o->o->x()+o->o->w(); + if (o->o->y()+o->o->h() > bt) bt = o->o->y()+o->o->h(); + } + recalc = 0; + } + fl_color(FL_RED); + if (drag==BOX && (x1 != mx || y1 != my)) { + int x = x1; int r = mx; if (x > r) {x = mx; r = x1;} + int y = y1; int b = my; if (y > b) {y = my; b = y1;} + fl_rect(x,y,r-x,b-y); + } + if (overlays_invisible) return; + if (selected) fl_rect(0,0,o->w(),o->h()); + if (!numselected) return; + int bx,by,br,bt; + bx = o->w(); by = o->h(); br = 0; bt = 0; + for (Fl_Type *q=next; q && q->level>level; q = q->next) + if (q->selected && q->is_widget() && !q->is_menu_item()) { + Fl_Widget_Type* o = (Fl_Widget_Type*)q; + int x,y,r,t; + newposition(o,x,y,r,t); + fl_rect(x,y,r-x,t-y); + if (x < bx) bx = x; + if (y < by) by = y; + if (r > br) br = r; + if (t > bt) bt = t; + } + if (selected) return; + if (numselected>1) fl_rect(bx,by,br-bx,bt-by); + fl_rectf(bx,by,5,5); + fl_rectf(br-5,by,5,5); + fl_rectf(br-5,bt-5,5,5); + fl_rectf(bx,bt-5,5,5); +} + +// Calculate new bounding box of selected widgets: +void Fl_Window_Type::fix_overlay() { + overlays_invisible = 0; + recalc = 1; + ((Overlay_Window *)(this->o))->redraw_overlay(); +} + +// do that for every window (when selected set changes): +void redraw_overlays() { + for (Fl_Type *o=Fl_Type::first; o; o=o->next) + if (o->is_window()) ((Fl_Window_Type*)o)->fix_overlay(); +} + +void toggle_overlays(Fl_Widget *,void *) { + overlays_invisible = !overlays_invisible; + for (Fl_Type *o=Fl_Type::first; o; o=o->next) + if (o->is_window()) { + Fl_Widget_Type* w = (Fl_Widget_Type*)o; + ((Overlay_Window*)(w->o))->redraw_overlay(); + } +} + +extern void select(Fl_Type *,int); +extern void select_only(Fl_Type *); +extern void deselect(); +extern Fl_Type* in_this_only; +extern void fix_group_size(Fl_Type *t); + +extern Fl_Menu_Item Main_Menu[]; +extern Fl_Menu_Item New_Menu[]; + +int Fl_Window_Type::handle(int event) { + static Fl_Type* selection; + switch (event) { + case FL_PUSH: + x1 = mx = Fl::event_x(); + y1 = my = Fl::event_y(); + drag = 0; + // test for popup menu: + if (Fl::event_button() >= 3) { + in_this_only = this; // modifies how some menu items work. + static const Fl_Menu_Item* prev; + const Fl_Menu_Item* m = New_Menu->popup(mx,my,"New",prev); + if (m && m->callback()) {prev = m; m->do_callback(this->o);} + in_this_only = 0; + return 1; + } + // find the innermost item clicked on: + selection = this; + {for (Fl_Type* i=next; i && i->level>level; i=i->next) + if (i->is_widget() && !i->is_menu_item()) { + Fl_Widget_Type* o = (Fl_Widget_Type*)i; + for (Fl_Widget *o1 = o->o; o1; o1 = o1->parent()) + if (!o1->visible()) goto CONTINUE2; + if (Fl::event_inside(o->o)) selection = o; + CONTINUE2:; + }} + // do object-specific selection of other objects: + {Fl_Type* t = selection->click_test(mx, my); + if (t) { + //if (t == selection) return 1; // indicates mouse eaten w/o change + if (Fl::event_state(FL_SHIFT)) { + Fl::event_is_click(0); + select(t, !t->selected); + } else { + deselect(); + select(t, 1); + if (t->is_menu_item()) t->open(); + } + selection = t; + return 1; + }} + // see if user grabs edges of selected region: + if (numselected && !overlays_invisible && !(Fl::event_state(FL_SHIFT)) && + mx<=br+snap && mx>=bx-snap && my<=bt+snap && my>=by-snap) { + int snap1 = snap>5 ? snap : 5; + int w1 = (br-bx)/4; if (w1 > snap1) w1 = snap1; + if (mx>=br-w1) drag |= RIGHT; + else if (mx<bx+w1) drag |= LEFT; + w1 = (bt-by)/4; if (w1 > snap1) w1 = snap1; + if (my<=by+w1) drag |= BOTTOM; + else if (my>bt-w1) drag |= TOP; + if (!drag) drag = DRAG; + } else { + drag = BOX; // start a new selection region + } + return 1; + case FL_DRAG: + if (!drag) return 0; + mx = Fl::event_x(); + my = Fl::event_y(); + newdx(); + return 1; + case FL_RELEASE: + if (!drag) return 0; + mx = Fl::event_x(); + my = Fl::event_y(); + newdx(); + if (drag != BOX && (dx || dy || !Fl::event_is_click())) { + if (dx || dy) { + Fl_Type *i; + for (i=next; i && i->level>level;) { + if (i->selected && i->is_widget() && !i->is_menu_item()) { + Fl_Widget_Type* o = (Fl_Widget_Type*)i; + int x,y,r,t; + newposition(o,x,y,r,t); + o->o->resize(x,y,r-x,t-y); + // move all the children, whether selected or not: + Fl_Type* p; + for (p = o->next; p && p->level>o->level; p = p->next) + if (p->is_widget() && !p->is_menu_item()) { + Fl_Widget_Type* o = (Fl_Widget_Type*)p; + int x,y,r,t; + newposition(o,x,y,r,t); + o->o->resize(x,y,r-x,t-y); + } + i = p; + } else { + i = i->next; + } + } + for (i=next; i && i->level>level; i=i->next) fix_group_size(i); + this->o->redraw(); + fix_overlay(); + modflag = 1; + } + } else if ((Fl::event_clicks() || Fl::event_state(FL_CTRL))) { + Fl_Widget_Type::open(); + } else { + if (mx<x1) {int t = x1; x1 = mx; mx = t;} + if (my<y1) {int t = y1; y1 = my; my = t;} + int n = 0; + int toggle = Fl::event_state(FL_SHIFT); + // clear selection on everything: + if (!toggle) deselect(); else Fl::event_is_click(0); + // select everything in box: + for (Fl_Type*i=next; i&&i->level>level; i=i->next) + if (i->is_widget() && !i->is_menu_item()) { + Fl_Widget_Type* o = (Fl_Widget_Type*)i; + for (Fl_Widget *o1 = o->o; o1; o1 = o1->parent()) + if (!o1->visible()) goto CONTINUE; + if (Fl::event_inside(o->o)) selection = o; + if (o->o->x()>=x1 && o->o->y()>y1 && + o->o->x()+o->o->w()<mx && o->o->y()+o->o->h()<my) { + n++; + select(o, toggle ? !o->selected : 1); + } + CONTINUE:; + } + // if nothing in box, select what was clicked on: + if (!n) { + select(selection, toggle ? !selection->selected : 1); + } + } + drag = 0; + return 1; + + case FL_KEYBOARD: { + if (Fl::event_key() == FL_Escape) {((Fl_Window*)o)->hide(); return 1;} + // find current child: + Fl_Type *i = Fl_Type::current; + while (i && (!i->is_widget() || i->is_menu_item())) i = i->parent; + if (!i) return 0; + Fl_Type *p = i->parent; + while (p && p != this) p = p->parent; + if (!p || !p->is_widget()) {i=next; if (!i || i->level <= level) return 0;} + p = i; + // try to navigate to another child: + for (;;) { + switch (Fl::event_key()) { + case FL_Tab: + if (Fl::event_state(FL_SHIFT)) goto LEFT; + case FL_Right: + case FL_Down: + i = i->next; break; + case FL_Left: + case FL_Up: + LEFT: + i = i->prev; break; + default: + return 0; + } + if (!i || i->level <= level) {i = p; break;} + if (!i->is_widget() || i->is_menu_item()) continue; + switch (Fl::event_key()) { + case FL_Up: + case FL_Down: if (p->is_widget() && !p->is_menu_item()) { + Fl_Widget* w = ((Fl_Widget_Type*)i)->o; + Fl_Widget* pw = ((Fl_Widget_Type*)p)->o; + if (w->x() >= pw->x()+pw->w() || + w->x()+w->w() <= pw->x()) continue; + }} + break; + } + // select it: + deselect(); select(i,1); + } return 1; + + case FL_SHORTCUT: { + in_this_only = this; // modifies how some menu items work. + const Fl_Menu_Item* m = Main_Menu->test_shortcut(); + if (m && m->callback()) m->do_callback(this->o); + in_this_only = 0; + return (m != 0); + } + default: + return 0; + } +} + +//////////////////////////////////////////////////////////////// + +#include <stdio.h> +#include <string.h> + +void Fl_Window_Type::write_code1() { + Fl_Widget_Type::write_code1(); +} + +void Fl_Window_Type::write_code2() { + if (modal) write_c("%so->set_modal();\n", indent()); + else if (non_modal) write_c("%so->set_non_modal();\n", indent()); + if (!((Fl_Window*)o)->border()) write_c("%so->clear_border();\n", indent()); + write_c("%so->end();\n", indent()); + if (((Fl_Window*)o)->resizable() == o) + write_c("%so->resizable(o);\n", indent()); + Fl_Widget_Type::write_code2(); +} + +void Fl_Window_Type::write_properties() { + Fl_Widget_Type::write_properties(); + if (modal) write_string("modal"); + else if (non_modal) write_string("non_modal"); + if (!((Fl_Window*)o)->border()) write_string("noborder"); + if (xclass) {write_string("xclass"); write_word(xclass);} + if (o->visible()) write_string("visible"); +} + +void Fl_Window_Type::read_property(const char *c) { + if (!strcmp(c,"modal")) { + modal = 1; + } else if (!strcmp(c,"non_modal")) { + non_modal = 1; + } else if (!strcmp(c, "visible")) { + if (Fl::first_window()) open(); // only if we are using user interface + } else if (!strcmp(c,"noborder")) { + ((Fl_Window*)o)->border(0); + } else if (!strcmp(c,"xclass")) { + storestring(read_word(),xclass); + ((Fl_Window*)o)->xclass(xclass); + } else { + Fl_Widget_Type::read_property(c); + } +} + +int Fl_Window_Type::read_fdesign(const char* name, const char* value) { + int x; + o->box(FL_NO_BOX); // because fdesign always puts an Fl_Box next + if (!strcmp(name,"Width")) { + if (sscanf(value,"%d",&x) == 1) o->size(x,o->h()); + } else if (!strcmp(name,"Height")) { + if (sscanf(value,"%d",&x) == 1) o->size(o->w(),x); + } else if (!strcmp(name,"NumberofWidgets")) { + return 1; // we can figure out count from file + } else if (!strcmp(name,"border")) { + if (sscanf(value,"%d",&x) == 1) ((Fl_Window*)o)->border(x); + } else if (!strcmp(name,"title")) { + label(value); + } else { + return Fl_Widget_Type::read_fdesign(name,value); + } + return 1; +} diff --git a/fluid/Fluid_Image.cxx b/fluid/Fluid_Image.cxx new file mode 100644 index 000000000..e01022502 --- /dev/null +++ b/fluid/Fluid_Image.cxx @@ -0,0 +1,384 @@ +// Fluid_Image.C + +// For pixmap labels. + +#include <FL/Fl.H> +#include <FL/Fl_Widget.H> +#include "Fl_Type.H" +#include "Fluid_Image.H" +#include <string.h> +#include <stdio.h> +#include <errno.h> +#include <ctype.h> +#include <malloc.h> +#include <stdlib.h> // needed for DEC's Alpha cxx ? +#include <FL/filename.H> + +extern void goto_source_dir(); // in fluid.C +extern void leave_source_dir(); // in fluid.C + +//////////////////////////////////////////////////////////////// +#include <FL/Fl_Pixmap.H> + +class pixmap_image : public Fluid_Image { +protected: + Fl_Pixmap *p; + int *linelength; +public: + pixmap_image(const char *name, FILE *); + ~pixmap_image(); + virtual void label(Fl_Widget *); // set the label of this widget + virtual void write_static(); + virtual void write_code(); + static int test_file(char *buffer); +}; + +int pixmap_image::test_file(char *buffer) { + return (strstr(buffer,"/* XPM") != 0); +} + +void pixmap_image::label(Fl_Widget *o) { + if (p) p->label(o); +} + +static int pixmap_header_written; + +void pixmap_image::write_static() { + if (!p) return; + write_c("\n"); + if (pixmap_header_written != write_number) { + write_c("#include <FL/Fl_Pixmap.H>\n"); + pixmap_header_written = write_number; + } + write_c("static char *%s[] = {\n", + unique_id(this, "image", filename_name(name()), 0)); + int l; + for (l = 0; p->data[l]; l++) { + if (l) write_c(",\n"); + write_cstring(p->data[l],linelength[l]); + } + write_c("\n};\n"); + write_c("static Fl_Pixmap %s(%s);\n", + unique_id(this, "pixmap", filename_name(name()), 0), + unique_id(this, "image", filename_name(name()), 0)); +} + +void pixmap_image::write_code() { + if (!p) return; + write_c("%s%s.label(o);\n", indent(), + unique_id(this, "pixmap", filename_name(name()), 0)); +} + +static int hexdigit(int x) { + if (isdigit(x)) return x-'0'; + if (isupper(x)) return x-'A'+10; + if (islower(x)) return x-'a'+10; + return 20; +} + +#define MAXSIZE 1024 + +pixmap_image::pixmap_image(const char *name, FILE *f) : Fluid_Image(name) { + if (!f) return; // for subclasses + // read all the c-strings out of the file: + char *data[MAXSIZE+1]; + int length[MAXSIZE+1]; + char buffer[MAXSIZE+20]; + int i = 0; + while (i < MAXSIZE && fgets(buffer,MAXSIZE+20,f)) { + if (buffer[0] != '\"') continue; + char *p = buffer; + char *q = buffer+1; + while (*q != '\"') { + if (*q == '\\') switch (*++q) { + case '\n': + fgets(q,(buffer+MAXSIZE+20)-q,f); break; + case 0: + break; + case 'x': { + q++; + int n = 0; + for (int x = 0; x < 3; x++) { + int d = hexdigit(*q); + if (d > 15) break; + n = (n<<4)+d; + q++; + } + *p++ = n; + } break; + default: { + int c = *q++; + if (c>='0' && c<='7') { + c -= '0'; + for (int x=0; x<2; x++) { + int d = hexdigit(*q); + if (d>7) break; + c = (c<<3)+d; + q++; + } + } + *p++ = c; + } break; + } else { + *p++ = *q++; + } + } + *p++ = 0; + data[i] = new char[p-buffer]; + memcpy(data[i],buffer,p-buffer); + length[i] = p-buffer-1; + i++; + } + data[i++] = 0; // put a null at the end + + char** real_data = new char*[i]; + linelength = new int[i]; + while (i--) {real_data[i] = data[i]; linelength[i] = length[i];} + p = new Fl_Pixmap(real_data); +} + +pixmap_image::~pixmap_image() { + if (p && p->data) { + char** real_data = (char**)(p->data); + for (int i = 0; real_data[i]; i++) delete[] real_data[i]; + delete[] real_data; + } + delete[] linelength; + delete p; +} + +//////////////////////////////////////////////////////////////// + +class gif_image : public pixmap_image { +public: + gif_image(const char *name, FILE *); + ~gif_image(); + static int test_file(char *buffer); +}; + +int gif_image::test_file(char *buffer) { + return !strncmp(buffer,"GIF",3); +} + +// function in gif.C: +int gif2xpm( + const char *infname,// filename for error messages + FILE *GifFile, // file to read + char*** datap, // return xpm data here + int** lengthp, // return line lengths here + int inumber // which image in movie (0 = first) +); + +gif_image::gif_image(const char *name, FILE *f) : pixmap_image(name,0) { + char** datap; + if (gif2xpm(name,f,&datap,&linelength,0)) { + p = new Fl_Pixmap(datap); + } else + p = 0; +} + +gif_image::~gif_image() { + if (p && p->data) { + char** real_data = (char**)(p->data); + for (int i = 0; i < 3; i++) delete[] real_data[i]; + delete[] real_data; + p->data = 0; + } +} + +//////////////////////////////////////////////////////////////// +#include <FL/Fl_Bitmap.H> + +class bitmap_image : public Fluid_Image { + Fl_Bitmap *p; +public: + ~bitmap_image(); + bitmap_image(const char *name, FILE *); + virtual void label(Fl_Widget *); // set the label of this widget + virtual void write_static(); + virtual void write_code(); + static int test_file(char *buffer); +}; + +// bad test, always do this last! +int bitmap_image::test_file(char *buffer) { + return (strstr(buffer,"#define ") != 0); +} + +void bitmap_image::label(Fl_Widget *o) { + if (p) p->label(o); else o->labeltype(FL_NORMAL_LABEL); +} + +static int bitmap_header_written; + +void bitmap_image::write_static() { + if (!p) return; + write_c("\n"); + if (bitmap_header_written != write_number) { + write_c("#include <FL/Fl_Bitmap.H>\n"); + bitmap_header_written = write_number; + } + write_c("static char %s[] = { \n", + unique_id(this, "bits", filename_name(name()), 0)); + int n = ((p->w+7)/8)*p->h; + for (int i = 0; i < n; i++) { + if (i) write_c(", "); + write_c("%d",p->array[i]); + } + write_c("\n};\n"); + write_c("static Fl_Bitmap %s(%s, %d, %d);\n", + unique_id(this, "bitmap", filename_name(name()), 0), + unique_id(this, "bits", filename_name(name()), 0), + p->w, p->h); +} + +void bitmap_image::write_code() { + if (!p) return; + write_c("%s%s.label(o);\n", indent(), + unique_id(this, "bitmap", filename_name(name()), 0)); +} + +bitmap_image::bitmap_image(const char *name, FILE *f) : Fluid_Image(name) { + p = 0; // if any problems with parse we exit with this zero + char buffer[1024]; + char junk[1024]; + int wh[2]; // width and height + int i; + for (i = 0; i<2; i++) { + for (;;) { + if (!fgets(buffer,1024,f)) return; + int r = sscanf(buffer,"#define %s %d",junk,&wh[i]); + if (r >= 2) break; + } + } + // skip to data array: + for (;;) { + if (!fgets(buffer,1024,f)) return; + if (!strncmp(buffer,"static ",7)) break; + } + int n = ((wh[0]+7)/8)*wh[1]; + uchar *data = new uchar[n]; + // read the data: + i = 0; + for (;i<n;) { + if (!fgets(buffer,1024,f)) return; + const char *a = buffer; + while (*a && i<n) { + int t; + if (sscanf(a," 0x%x",&t)>0) data[i++] = t; + while (*a && *a++ != ','); + } + } + p = new Fl_Bitmap(data,wh[0],wh[1]); +} + +bitmap_image::~bitmap_image() { + if (p) { + delete[] (uchar*)(p->array); + delete p; + } +} + +//////////////////////////////////////////////////////////////// + +static Fluid_Image** images; // sorted list +static int numimages; +static int tablesize; + +Fluid_Image* Fluid_Image::find(const char *name) { + if (!name || !*name) return 0; + + // first search to see if it exists already: + int a = 0; + int b = numimages; + while (a < b) { + int c = (a+b)/2; + int i = strcmp(name,images[c]->name_); + if (i < 0) b = c; + else if (i > 0) a = c+1; + else return images[c]; + } + + // no, so now see if the file exists: + + goto_source_dir(); + FILE *f = fopen(name,"rb"); + if (!f) { + read_error("%s : %s",name,strerror(errno)); + leave_source_dir(); + return 0; + } + + Fluid_Image *ret; + + // now see if we can identify the type, by reading in some data + // and asking all the types we know about: + + char buffer[1025]; + fread(buffer, 1, 1024, f); + rewind(f); + buffer[1024] = 0; // null-terminate so strstr() works + + if (pixmap_image::test_file(buffer)) { + ret = new pixmap_image(name,f); + } else if (gif_image::test_file(buffer)) { + ret = new gif_image(name,f); + } else if (bitmap_image::test_file(buffer)) { + ret = new bitmap_image(name,f); + } else { + ret = 0; + read_error("%s : unrecognized image format", name); + } + fclose(f); + leave_source_dir(); + if (!ret) return 0; + + // make a new entry in the table: + numimages++; + if (numimages > tablesize) { + tablesize = tablesize ? 2*tablesize : 16; + images = (Fluid_Image**)realloc(images, tablesize*sizeof(Fluid_Image*)); + } + for (b = numimages-1; b > a; b--) images[b] = images[b-1]; + images[a] = ret; + + return ret; +} + +Fluid_Image::Fluid_Image(const char *name) { + name_ = strdup(name); + written = 0; + refcount = 0; +} + +void Fluid_Image::increment() { + ++refcount; +} + +void Fluid_Image::decrement() { + --refcount; + if (refcount > 0) return; + delete this; +} + +Fluid_Image::~Fluid_Image() { + int a; + for (a = 0;; a++) if (images[a] == this) break; + numimages--; + for (; a < numimages; a++) images[a] = images[a+1]; + free((void*)name_); +} + +//////////////////////////////////////////////////////////////// + +#include <FL/fl_file_chooser.H> + +const char *ui_find_image_name; +Fluid_Image *ui_find_image(const char *oldname) { + goto_source_dir(); + const char *name = fl_file_chooser("Image","*.{bm|xbm|xpm|gif}",oldname); + ui_find_image_name = name; + Fluid_Image *ret = (name && *name) ? Fluid_Image::find(name) : 0; + leave_source_dir(); + return ret; +} diff --git a/fluid/Fluid_Image.h b/fluid/Fluid_Image.h new file mode 100644 index 000000000..fdc7937bc --- /dev/null +++ b/fluid/Fluid_Image.h @@ -0,0 +1,28 @@ +// Fluid_Image.H + +// This class stores the image labels for widgets in fluid. This is +// not a class in fltk itself, and this will produce different types of +// code depending on what the image type is. There are private subclasses +// in Fluid_Image.C for each type of image format. Right now only xpm +// files are supported. + +class Fluid_Image { + const char *name_; + int refcount; +protected: + Fluid_Image(const char *name); // no public constructor + virtual ~Fluid_Image(); // no public destructor +public: + int written; + static Fluid_Image* find(const char *); + void decrement(); // reference counting & automatic free + void increment(); + virtual void label(Fl_Widget *) = 0; // set the label of this widget + virtual void write_static() = 0; + virtual void write_code() = 0; + const char *name() const {return name_;} +}; + +// pop up file chooser and return a legal image selected by user, +// or zero for any errors: +Fluid_Image *ui_find_image(const char *); diff --git a/fluid/Makefile b/fluid/Makefile new file mode 100644 index 000000000..876b52a09 --- /dev/null +++ b/fluid/Makefile @@ -0,0 +1,83 @@ +PROGRAM = fluid + +CPPFILES = \ + Fl_Function_Type.C \ + Fl_Menu_Type.C \ + Fl_Group_Type.C \ + Fl_Widget_Type.C \ + Fl_Type.C \ + Fl_Window_Type.C \ + Fluid_Image.C \ + code.C \ + factory.C \ + file.C \ + fluid.C \ + about_panel.C \ + widget_panel.C \ + alignment_panel.C \ + function_panel.C \ + gif.C + +################################################################ + +OBJECTS = $(CPPFILES:.C=.o) + +include ../makeinclude + +.SUFFIXES : .C .c .o .do .fl .H + +.C.o : + @echo $<: + @$(CXX) -I.. $(CXXFLAGS) -c $< +.c.o : + @echo $<: + @$(CC) -I.. $(CFLAGS) -c $< +.C : + @echo $@: + @$(CXX) -I.. $(CXXFLAGS) -o $@ $< -L../lib -lfltk $(LDLIBS) + +.fl.C .fl.H : + -fluid -c $< + +# better way to do this for gnu make: +# %.H %.C: %.fl +# fluid -c $< + +$(PROGRAM) : $(OBJECTS) ../lib/$(LIBNAME) + @echo linking $@: + @$(CXX) $(CXXFLAGS) -o $(PROGRAM) $(OBJECTS) -L../lib -lfltk $(LDLIBS) + +clean : + -@ rm -f *.o $(PROGRAM) $(CLEAN) core *~ makedepend + @touch makedepend + +depend: + $(MAKEDEPEND) -I.. $(CXXFLAGS) $(CPPFILES) $(CFILES) > makedepend +include makedepend + +install: $(PROGRAM) + strip $(PROGRAM) + cp $(PROGRAM) $(bindir)/$(PROGRAM) + @chmod a+rx,g-w,o-w $(bindir)/$(PROGRAM) + +uninstall: + -@ rm -f $(bindir)/$(PROGRAM) + +################################################################ + +PROGRAM_D = $(PROGRAM)_d + +debug: $(PROGRAM_D) + +OBJECTS_D = $(CPPFILES:.C=.do) $(CFILES:.c=.do) + +.C.do : + @echo $<: + @$(CXX) -I.. $(CXXFLAGS_D) -c -o $@ $< +.c.do : + @echo $<: + @$(CC) -I.. $(CFLAGS_D) -c -o $@ $< + +$(PROGRAM_D) : $(OBJECTS_D) ../lib/$(LIBNAME_D) + @echo linking $@: + @$(CXX) $(CXXFLAGS_D) -o $(PROGRAM_D) $(OBJECTS_D) -L../lib -lfltk_d $(LDLIBS) diff --git a/fluid/README b/fluid/README new file mode 100644 index 000000000..9fe6d6c36 --- /dev/null +++ b/fluid/README @@ -0,0 +1,214 @@ +Fluid (the FL User Interface Designer) is a graphical editor that +is used to produce FL source code. + +Fluid edits and saves it's state in ".fl" files. These files are +text, and you could (with care) edit them in a text editor, perhaps to +get some special effects. + +When asked to "compile", fluid outputs a .C source file and a .H +header file: The .C file contains one or more public functions, each +of which will create one or more FL windows and all the objects in +those windows. The .H file declares (as externs) all the functions +and named objects created by the .C file, and includes all the +necessary FL header files for those objects. + +The C file must be compiled and linked with a "main" source file(s) +that you write. This source code must include the .H output, and +should call the functions in the .C file to create windows. The main +code must do show() on the windows and run the Fl::wait() loop. + + _________ + / / + __________ +->/.C file /--------+ + / / / /________/ | + /.fl file /<==>[fluid]< #include | + /_________/ \ ___v_____ | + \ / / | + +>/.H file / | + /________/ | + ^ | + #include | + ___|_____ | __________ + / / V / / + / main.C /--->[c++,link]-->/ program / + /________/ /_________/ + + +Objects created by fluid are either "named" or "unnamed". If they +are named, the .C file will declare a global variable with that name +of type "<type>*". This pointer has a value of zero until the fluid +function is called, the fluid function will set it to the instance of +the . Unnamed objects are only accessible through +pointers from other objects. + +Windows may be named or unnamed. Named windows are only created +once even if you call the function several times (fluid outputs "if +(!name) {...}" around the code that creates the window). Unnamed +windows lets you create many instances of the same window structure, a +pointer to the unnamed window is returned from the fluid function (you +can only put one unnamed window in a function). + +Objects may either call a named callback function that you write in +another source file, or you can supply a small piece of C++ source and +fluid will write a private callback function into the .C file. + +================================================================ +Worlds shortest tutorial: +================================================================ + +Type "fluid&" + +Pick "New/Function" off the menu. + +Delete the function name in the popup window and hit OK. The text +"main()" with a triangle next to it should appear highlighted in the +main window. + +Pick "New/Window" off the menu. + +Move the window and resize it to the size you want. + +Pick "New/buttons/Button" off the menu. + +Hit the "OK" button to dismiss the panel that appears. + +In the window you created, try moving the button by dragging it +around. Notice that it "snaps" to fixed locations. If you want to +drag it smoothly, hold down Alt. You can also change the size of the +steps with Edit/Preferences. + +Try resizing the object by dragging the edges and corners. + +Type Alt+c to copy the object. + +Type Alt+v to paste a copy into the window. + +Type Alt+v several times. + +Drag the objects and resize them so they don't overlap. Notice +that you have to click an object to pick it first, then drag it. + +Try selecting several objects by dragging a box around them. Check +what happens when you move them, or when you drag an edge to resize +them. + +You can also use Shift+click to toggle objects on and off. + +You can also select objects by clicking on them in the list in the +main window, try that. + +Double-click one of the buttons. You will get a control panel. + +Try changing the "label". Try changing other items near the top of +the panel. To see any changes to the box type clearer, type "Alt+o" +to make the red overlay disappear. + +Type "#include <stdlib.h>" into the first line of "extra code:". + +Type "exit(0);" into the "callback:". + +Hit OK. + +Pick "File/Save As" off the menu. + +Type "test.fl" into the file chooser and hit return. + +Pick "File/Write Code" off the menu. + +Go back to your terminal window. Type "more test.C" and "more +test.H" and you can see the code it made. + +Type "make test" (you may have to add libaries to your Makefile). + +Type "./test" to run your program. + +Try the buttons. The one you put the code into will exit the +program. + +Type "Alt+Q" to exit fluid. + +Ok, now try to make a real program. + +================================================================ + +This code is quite a kludge and probably impossible to figure out. I +hope it will be fixed someday, but my intention was to make FL itself +clean and simple, even if the user interface designer is forced to be +more complex as a result. + +An object in fluid is represented by a subclass of "Fl_Type". + +Creating a new instance of an object is done by calling the virtual +method "make()" on Fl_Type. To allow an initial version of each type +to be created, there is a static "factory" instance of every subclass +of Fl_Type. For now, make() is only called on these. The intention +was to use make() to copy objects, but that did not happen. Instead I +write the descriptions and read them back from a file in /usr/tmp, +which is much more reliable because the read/write code is tested +every time a file is saved! + +The (non-factory) instances are linked into a list by the previous and +next pointers. The "hierarchy" is stored by a "level" number on each +object, and an "isparent" flag on the parent. To find the "brother" +of an object, code must search forward for the next object whose level +is equal to this one. A null pointer or an object with a lower level +number indicates no brother. + +If the type is a subclass of Fl_Object, the "o" pointer points at an +Fl_Object. This allows the code in FL to be used to draw the object. +The user_data() field on the Fl_Object is used as a back pointer to +the Fl_Type. The "factory" has an "o" pointer that points at the +"template object". This is an Fl_Object created the first time make() +is called and is used to figure out what the default values for the +fields are for the object. + +This "o" pointer exists in all Fl_Type objects, even the base class. +If this is not an Fl_Object item, then the "o" pointer is zero. This +avoided a lot of virtual functions, but is mostly for historical +reasons. Rather than RTTI, I use some tests to determine subclasses: + + if (o && level == 1) + this is an Fl_Window_Type + else if (o && isparent) + this is a Fl_Group_Type + else if (o) + this is a Fl_Object_Type + else if (!level) + this is a function + else + this is a menu item or something + (none of these implemented yet) + + + Fl_Type::first + | + | NULL + | ^ + V | + +---------+ +-----------+ + | Fl_Type |------ o ---> | Fl_Window | + | level=0 |<-user_data()-| | + |isparent |<-+ +-----------+ + +---------+ | | ^ + | ^ parent first | + next prev / | parent + V | / V | + +---------+ +-----------+ + | Fl_Type |------ o ---> | Fl_Object | + | level=1 | | | + | |<-user_data()-| | + | | +-----------+ + | | +---------+ + | |-factory->| Fl_Type |---- o ---->[Fl_Object] + +---------+ | | template object + | ^ +---------+ + next prev (next,prev=NULL) + V | + +---------+ + | Fl_Type | + +---------+ + | ^ + V | + NULL | + | + Fl_Type::last diff --git a/fluid/Shortcut_Button.h b/fluid/Shortcut_Button.h new file mode 100644 index 000000000..eea4ddc70 --- /dev/null +++ b/fluid/Shortcut_Button.h @@ -0,0 +1,10 @@ +#include <FL/Fl_Button.H> + +class Shortcut_Button : public Fl_Button { +public: + int svalue; + int handle(int); + void draw(); + Shortcut_Button(int x, int y, int w, int h, const char* l = 0) : + Fl_Button(x,y,w,h,l) {svalue = 0;} +}; diff --git a/fluid/about_panel.cxx b/fluid/about_panel.cxx new file mode 100644 index 000000000..a880d39dd --- /dev/null +++ b/fluid/about_panel.cxx @@ -0,0 +1,122 @@ +// generated by Fast Light User Interface Designer (fluid) version 0.99 + +#include "about_panel.H" + +Fl_Window *about_panel; + +Fl_Group *display_group; + +static void cb_1998(Fl_Button*, void*) { + display_group->hide(); +copyright_box->show(); +} + +Fl_Box *copyright_box; + +static void cb_OK(Fl_Return_Button* o, void*) { + ((Fl_Window*)(o->parent()))->hide(); +} + +Fl_Window* make_about_panel(const char *copyright) { + Fl_Window* w; + { Fl_Window* o = about_panel = w = new Fl_Window(309, 221, "about fluid"); + o->box(FL_UP_BOX); + o->color(97); + o->selection_color(47); + w->hotspot(o); + { Fl_Group* o = display_group = new Fl_Group(24, 14, 275, 186); + { Fl_Box* o = new Fl_Box(64, 14, 50, 126); + o->box(FL_ROUND_UP_BOX); + o->color(14); + o->selection_color(47); + o->labelcolor(6); + } + { Fl_Box* o = new Fl_Box(54, 14, 70, 16); + o->box(FL_FLAT_BOX); + o->color(97); + o->selection_color(47); + } + { Fl_Box* o = new Fl_Box(68, 30, 42, 50); + o->box(FL_DOWN_BOX); + o->color(6); + o->selection_color(47); + } + { Fl_Box* o = new Fl_Box(54, 20, 70, 20); + o->box(FL_ROUND_UP_BOX); + o->color(6); + o->selection_color(47); + o->labelcolor(6); + o->align(16); + } + { Fl_Box* o = new Fl_Box(24, 110, 130, 90, "fluid"); + o->box(FL_ROUND_UP_BOX); + o->color(14); + o->selection_color(47); + o->labeltype(FL_SHADOW_LABEL); + o->labelfont(1); + o->labelsize(40); + o->labelcolor(6); + } + { Fl_Box* o = new Fl_Box(67, 110, 44, 10); + o->box(FL_FLAT_BOX); + o->color(14); + o->selection_color(47); + } + { Fl_Box* o = new Fl_Box(84, 120, 15, 15, "` "); + o->box(FL_OVAL_BOX); + o->color(6); + o->selection_color(47); + o->labelsize(20); + o->labelcolor(7); + o->align(17); + } + { Fl_Box* o = new Fl_Box(75, 105, 15, 15, "` "); + o->box(FL_OVAL_BOX); + o->color(6); + o->selection_color(47); + o->labelsize(20); + o->labelcolor(7); + o->align(17); + } + { Fl_Box* o = new Fl_Box(89, 85, 15, 15, "` "); + o->box(FL_OVAL_BOX); + o->color(6); + o->selection_color(47); + o->labelsize(20); + o->labelcolor(7); + o->align(17); + } + { Fl_Box* o = new Fl_Box(159, 27, 131, 95, "Fltk User\nInterface\nDesigner\nVersion 1.00"); + o->box(FL_OVAL_BOX); + o->color(12); + o->selection_color(47); + o->labeltype(FL_SHADOW_LABEL); + o->labelfont(1); + o->labelsize(18); + o->labelcolor(7); + } + { Fl_Button* o = new Fl_Button(169, 138, 115, 30, "\xa9\x31\x39\x39\x38 Bill Spitzak\n(click here)"); + o->box(FL_THIN_UP_BOX); + o->labelsize(10); + o->labelcolor(136); + o->callback((Fl_Callback*)cb_1998); + } + o->end(); + } + { Fl_Box* o = copyright_box = new Fl_Box(5, 5, 300, 210); + o->labelsize(8); + o->labelcolor(6); + o->align(148); + o->hide(); + o->label(copyright); + } + { Fl_Return_Button* o = new Fl_Return_Button(168, 182, 116, 22, "OK"); + o->labelsize(10); + o->callback((Fl_Callback*)cb_OK); + } + o->set_non_modal(); + o->clear_border(); + o->end(); + } + return w; +} diff --git a/fluid/about_panel.fl b/fluid/about_panel.fl new file mode 100644 index 000000000..b35c59251 --- /dev/null +++ b/fluid/about_panel.fl @@ -0,0 +1,71 @@ +# data file for the Fltk User Interface Designer (fluid) +version 0.99 +gridx 2 +gridy 2 +snap 3 +Function {make_about_panel(const char *copyright)} {open +} { + Fl_Window about_panel { + label {about fluid} open + xywh {345 417 309 221} box UP_BOX color {97 47} hide hotspot non_modal noborder + } { + Fl_Group display_group {open + xywh {24 14 275 186} + } { + Fl_Box {} { + xywh {64 14 50 126} box ROUND_UP_BOX color {14 47} labelcolor 6 + } + Fl_Box {} { + xywh {54 14 70 16} box FLAT_BOX color {97 47} + } + Fl_Box {} { + xywh {68 30 42 50} box DOWN_BOX color {6 47} + } + Fl_Box {} { + xywh {54 20 70 20} box ROUND_UP_BOX color {6 47} labelcolor 6 align 16 + } + Fl_Box {} { + label fluid + xywh {24 110 130 90} box ROUND_UP_BOX color {14 47} labeltype SHADOW_LABEL labelfont 1 labelsize 40 labelcolor 6 + } + Fl_Box {} { + xywh {67 110 44 10} box FLAT_BOX color {14 47} + } + Fl_Box {} { + label {` } + xywh {84 120 15 15} box OVAL_BOX color {6 47} labelsize 20 labelcolor 7 align 17 + } + Fl_Box {} { + label {` } + xywh {75 105 15 15} box OVAL_BOX color {6 47} labelsize 20 labelcolor 7 align 17 + } + Fl_Box {} { + label {` } + xywh {89 85 15 15} box OVAL_BOX color {6 47} labelsize 20 labelcolor 7 align 17 + } + Fl_Box {} { + label {Fltk User +Interface +Designer +Version 1.00} + xywh {159 27 131 95} box OVAL_BOX color {12 47} labeltype SHADOW_LABEL labelfont 1 labelsize 18 labelcolor 7 + } + Fl_Button {} { + label {©1998 Bill Spitzak +(click here)} + callback {display_group->hide(); +copyright_box->show();} + xywh {169 138 115 30} box THIN_UP_BOX labelsize 10 labelcolor 136 + } + } + Fl_Box copyright_box {selected + xywh {5 5 300 210} labelsize 8 labelcolor 6 align 148 hide + code0 {o->label(copyright);} + } + Fl_Return_Button {} { + label OK + callback {((Fl_Window*)(o->parent()))->hide();} + xywh {168 182 116 22} labelsize 10 + } + } +} diff --git a/fluid/about_panel.h b/fluid/about_panel.h new file mode 100644 index 000000000..7113cf5cf --- /dev/null +++ b/fluid/about_panel.h @@ -0,0 +1,12 @@ +// generated by Fast Light User Interface Designer (fluid) version 0.99 + +#include <FL/Fl.H> +#include <FL/Fl_Box.H> +#include <FL/Fl_Button.H> +#include <FL/Fl_Group.H> +#include <FL/Fl_Return_Button.H> +#include <FL/Fl_Window.H> +extern Fl_Window *about_panel; +extern Fl_Group *display_group; +extern Fl_Box *copyright_box; +Fl_Window* make_about_panel(const char *copyright); diff --git a/fluid/alignment_panel.cxx b/fluid/alignment_panel.cxx new file mode 100644 index 000000000..fa8c7c089 --- /dev/null +++ b/fluid/alignment_panel.cxx @@ -0,0 +1,73 @@ +// generated by Fast Light User Interface Designer (fluid) version 0.99 + +#include "alignment_panel.H" + +Fl_Window *alignment_window; + +Fl_Input *horizontal_input; + +Fl_Input *vertical_input; + +Fl_Input *snap_input; + +static void cb_close(Fl_Button*, void*) { + alignment_window->hide(); +} + +Fl_Input *header_file_input; + +Fl_Input *code_file_input; + +Fl_Window* make_alignment_window() { + Fl_Window *w; + { Fl_Window* o = alignment_window = w = new Fl_Window(210, 282, "fluid Preferences"); + { Fl_Box* o = new Fl_Box(10, 20, 190, 100, "ALIGNMENT:"); + o->box(FL_ENGRAVED_FRAME); + o->labelsize(10); + o->align(5); + } + { Fl_Input* o = horizontal_input = new Fl_Input(90, 30, 100, 20, "horizontal:"); + o->type(2); + o->box(FL_THIN_DOWN_BOX); + o->callback((Fl_Callback*)alignment_cb, (void*)(1)); + o->when(FL_WHEN_RELEASE|FL_WHEN_ENTER_KEY); + } + { Fl_Input* o = vertical_input = new Fl_Input(90, 60, 100, 20, "vertical:"); + o->type(2); + o->box(FL_THIN_DOWN_BOX); + o->callback((Fl_Callback*)alignment_cb, (void*)(2)); + o->when(FL_WHEN_RELEASE|FL_WHEN_ENTER_KEY); + } + { Fl_Input* o = snap_input = new Fl_Input(90, 90, 100, 20, "snap:"); + o->type(2); + o->box(FL_THIN_DOWN_BOX); + o->callback((Fl_Callback*)alignment_cb, (void*)(3)); + o->when(FL_WHEN_RELEASE|FL_WHEN_ENTER_KEY); + } + { Fl_Button* o = new Fl_Button(10, 250, 190, 20, "close"); + o->callback((Fl_Callback*)cb_close); + w->hotspot(o); + } + { Fl_Box* o = new Fl_Box(10, 140, 190, 100, "OUTPUT FILE NAMES:"); + o->box(FL_ENGRAVED_FRAME); + o->labelsize(10); + o->align(5); + } + { Fl_Box* o = new Fl_Box(10, 140, 190, 40, "Use \"name.ext\" to set name, use just \".ext\" to set only extension."); + o->labelsize(10); + o->align(128); + } + { Fl_Input* o = header_file_input = new Fl_Input(90, 180, 100, 20, "header file:"); + o->box(FL_THIN_DOWN_BOX); + o->callback((Fl_Callback*)header_input_cb, (void*)(1)); + o->when(1); + } + { Fl_Input* o = code_file_input = new Fl_Input(90, 210, 100, 20, "code file:"); + o->box(FL_THIN_DOWN_BOX); + o->callback((Fl_Callback*)code_input_cb, (void*)(1)); + o->when(1); + } + o->end(); + } + return w; +} diff --git a/fluid/alignment_panel.fl b/fluid/alignment_panel.fl new file mode 100644 index 000000000..c2e7f9286 --- /dev/null +++ b/fluid/alignment_panel.fl @@ -0,0 +1,65 @@ +# data file for the Fltk User Interface Designer (fluid) +version 0.99 +header_name {.H} +code_name {.C} +gridx 10 +gridy 10 +snap 3 +Function {make_alignment_window()} {open +} { + Fl_Window alignment_window { + label {fluid Preferences} open selected + xywh {303 187 210 282} visible + } { + Fl_Box {} { + label {ALIGNMENT:} + xywh {10 20 190 100} box ENGRAVED_FRAME labelsize 10 align 5 + } + Fl_Input horizontal_input { + label {horizontal:} + user_data 1 user_data_type long + callback alignment_cb + xywh {90 30 100 20} type Int box THIN_DOWN_BOX + code0 {o->when(FL_WHEN_RELEASE|FL_WHEN_ENTER_KEY);} + } + Fl_Input vertical_input { + label {vertical:} + user_data 2 user_data_type long + callback alignment_cb + xywh {90 60 100 20} type Int box THIN_DOWN_BOX + code0 {o->when(FL_WHEN_RELEASE|FL_WHEN_ENTER_KEY);} + } + Fl_Input snap_input { + label {snap:} + user_data 3 user_data_type long + callback alignment_cb + xywh {90 90 100 20} type Int box THIN_DOWN_BOX + code0 {o->when(FL_WHEN_RELEASE|FL_WHEN_ENTER_KEY);} + } + Fl_Button {} { + label close + callback {alignment_window->hide();} + xywh {10 250 190 20} hotspot + } + Fl_Box {} { + label {OUTPUT FILE NAMES:} + xywh {10 140 190 100} box ENGRAVED_FRAME labelsize 10 align 5 + } + Fl_Box {} { + label {Use "name.ext" to set name, use just ".ext" to set only extension.} + xywh {10 140 190 40} labelsize 10 align 128 + } + Fl_Input header_file_input { + label {header file:} + user_data 1 user_data_type {void*} + callback header_input_cb + xywh {90 180 100 20} box THIN_DOWN_BOX when 1 + } + Fl_Input code_file_input { + label {code file:} + user_data 1 user_data_type {void*} + callback code_input_cb + xywh {90 210 100 20} box THIN_DOWN_BOX when 1 + } + } +} diff --git a/fluid/alignment_panel.h b/fluid/alignment_panel.h new file mode 100644 index 000000000..437d7640f --- /dev/null +++ b/fluid/alignment_panel.h @@ -0,0 +1,17 @@ +// generated by Fast Light User Interface Designer (fluid) version 0.99 + +#include <FL/Fl.H> +#include <FL/Fl_Box.H> +#include <FL/Fl_Button.H> +#include <FL/Fl_Input.H> +#include <FL/Fl_Window.H> +extern void alignment_cb(Fl_Input*, long); +extern void code_input_cb(Fl_Input*, void*); +extern void header_input_cb(Fl_Input*, void*); +extern Fl_Window *alignment_window; +extern Fl_Input *horizontal_input; +extern Fl_Input *vertical_input; +extern Fl_Input *snap_input; +extern Fl_Input *header_file_input; +extern Fl_Input *code_file_input; +Fl_Window* make_alignment_window(); diff --git a/fluid/class.C b/fluid/class.C new file mode 100644 index 000000000..e547cf2a7 --- /dev/null +++ b/fluid/class.C @@ -0,0 +1,123 @@ +// generated by Fast Light User Interface Designer (fluid) version 0.99 + +#include "class.H" + +inline void essai::cb_button_i(Fl_Button*, void*) { + printf("button\n"); +} +void essai::cb_button(Fl_Button* o, void* v) { + ((essai*)(o->parent()->user_data()))->cb_button_i(o,v); +} + +inline void essai::cb_unnamed_i(Fl_Button*, void*) { + printf("unnamed\n"); +} +void essai::cb_unnamed(Fl_Button* o, void* v) { + ((essai*)(o->parent()->user_data()))->cb_unnamed_i(o,v); +} + +inline void essai::cb_src_i(Fl_Button*, void*) { + (new essai)->win->show(); +} +void essai::cb_src(Fl_Button* o, void* v) { + ((essai*)(o->parent()->user_data()))->cb_src_i(o,v); +} + +#include <FL/Fl_Bitmap.H> +static char bits_ew_mask[] = { +0, 0, 0, 0, 0, 0, 0, 0, 24, 24, 28, 56, 254, 127, 255, 255, 255, 255, 254, 127, 28, 56, 24, 24, 0, 0, 0, 0, 0, 0, 0, 0 +}; +static Fl_Bitmap bitmap_ew_mask(bits_ew_mask, 16, 16); + +inline void essai::cb_change_i(Fl_Menu_*, void*) { + cbox->color(cbox->color()+1); +cbox->redraw(); +} +void essai::cb_change(Fl_Menu_* o, void* v) { + ((essai*)(o->parent()->user_data()))->cb_change_i(o,v); +} + +Fl_Menu_Item essai::menu_menu[] = { + {"change color", 0, (Fl_Callback*)essai::cb_change, 0, 0, 0, 3, 14, 0}, + {"radio off", 0, 0, 0, 8, 0, 3, 14, 0}, + {"radio on", 0, 0, 0, 12, 0, 3, 14, 0}, + {"toggle off", 0, 0, 0, 2, 0, 3, 14, 0}, + {"toggle on", 0, 0, 0, 6, 0, 3, 14, 0}, + {"new item 5", 0, 0, 0, 0, 0, 3, 14, 0}, + {"new item 6", 0, 0, 0, 0, 0, 3, 14, 0}, + {"new item 7", 0, 0, 0, 0, 0, 3, 14, 0}, + {"new item 8", 0, 0, 0, 0, 0, 3, 14, 0}, + {"new item 9", 0, 0, 0, 0, 0, 3, 14, 0}, + {"new item 10", 0, 0, 0, 0, 0, 3, 14, 0}, + {"new item 11", 0, 0, 0, 0, 0, 3, 14, 0}, + {"new item 12", 0, 0, 0, 0, 0, 3, 14, 0}, + {"new item 13", 0, 0, 0, 0, 0, 3, 14, 0}, + {"new item 14", 0, 0, 0, 0, 0, 3, 14, 0}, + {"new item 15", 0, 0, 0, 0, 0, 3, 14, 0}, + {"new item 16", 0, 0, 0, 0, 0, 3, 14, 0}, + {"new item 17", 0, 0, 0, 0, 0, 3, 14, 0}, + {"new item 18", 0, 0, 0, 0, 0, 3, 14, 0}, + {"new item 19", 0, 0, 0, 0, 0, 3, 14, 0}, + {"new item 20", 0, 0, 0, 0, 0, 3, 14, 0}, + {"new item 21", 0, 0, 0, 0, 0, 3, 14, 0}, + {"new item 22", 0, 0, 0, 0, 0, 3, 14, 0}, + {"new item 23", 0, 0, 0, 0, 0, 3, 14, 0}, + {"new item 24", 0, 0, 0, 0, 0, 3, 14, 0}, + {0} +}; + +inline void essai::cb_color_i(Fl_Button*, void*) { + cbox->color(cbox->color()+1); +cbox->redraw(); +} +void essai::cb_color(Fl_Button* o, void* v) { + ((essai*)(o->parent()->user_data()))->cb_color_i(o,v); +} + +inline void essai::cb_delete_i(Fl_Button*, void*) { + delete this; +} +void essai::cb_delete(Fl_Button* o, void* v) { + ((essai*)(o->parent()->user_data()))->cb_delete_i(o,v); +} + +essai::essai() { + Fl_Window *w; + { Fl_Window* o = win = w = new Fl_Window(282, 193); + o->user_data((void*)(this)); + { Fl_Button* o = new Fl_Button(10, 10, 55, 35, "button"); + o->callback((Fl_Callback*)cb_button); + } + { Fl_Button* o = new Fl_Button(10, 45, 145, 35, "unnamed"); + o->callback((Fl_Callback*)cb_unnamed); + } + { Fl_Button* o = new Fl_Button(10, 80, 145, 35); + bitmap_ew_mask.label(o); + o->callback((Fl_Callback*)cb_src); + } + { Fl_Menu_Button* o = new Fl_Menu_Button(10, 115, 145, 35, "menu"); + o->menu(menu_menu); + } + { Fl_Button* o = new Fl_Button(70, 150, 85, 35, "color"); + o->callback((Fl_Callback*)cb_color); + } + new Fl_Button(200, 10, 55, 35, "boring"); + { Fl_Box* o = cbox = new Fl_Box(165, 80, 55, 35, "color"); + o->box(FL_FLAT_BOX); + } + { Fl_Button* o = new Fl_Button(200, 125, 55, 35, "delete this"); + o->callback((Fl_Callback*)cb_delete); + } + button_variable = new Fl_Button(100, 10, 55, 35, "button"); + w->end(); + } +} + +essai::~essai() { + delete win; +} + +int main(int argc, char **argv) { + essai E; E.win->show(); + return Fl::run(); +} diff --git a/fluid/class.H b/fluid/class.H new file mode 100644 index 000000000..302ce0486 --- /dev/null +++ b/fluid/class.H @@ -0,0 +1,34 @@ +// generated by Fast Light User Interface Designer (fluid) version 0.99 + +#include <FL/Fl.H> +#include <FL/Fl_Box.H> +#include <FL/Fl_Button.H> +#include <FL/Fl_Menu_Button.H> +#include <FL/Fl_Window.H> +#include <stdio.h> + +class essai { +public: + essai(); + Fl_Window *win; +private: + inline void cb_button_i(Fl_Button*, void*); + static void cb_button(Fl_Button*, void*); + inline void cb_unnamed_i(Fl_Button*, void*); + static void cb_unnamed(Fl_Button*, void*); + inline void cb_src_i(Fl_Button*, void*); + static void cb_src(Fl_Button*, void*); + static Fl_Menu_Item menu_menu[]; + inline void cb_change_i(Fl_Menu_*, void*); + static void cb_change(Fl_Menu_*, void*); + inline void cb_color_i(Fl_Button*, void*); + static void cb_color(Fl_Button*, void*); +public: + Fl_Box *cbox; +private: + inline void cb_delete_i(Fl_Button*, void*); + static void cb_delete(Fl_Button*, void*); +public: + Fl_Button *button_variable; + ~essai(); +}; diff --git a/fluid/code.cxx b/fluid/code.cxx new file mode 100644 index 000000000..171593fff --- /dev/null +++ b/fluid/code.cxx @@ -0,0 +1,263 @@ +/* code.C + + Code to write .C files from Fluid + +*/ + +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> + +#include <FL/Fl.H> +#include "Fl_Type.H" + +static FILE *code_file; +static FILE *header_file; + +// return true if c can be in a C identifier. I needed this so +// it is not messed up by locale settings: +int is_id(char c) { + return c>='a' && c<='z' || c>='A' && c<='Z' || c>='0' && c<='9' || c=='_'; +} + +//////////////////////////////////////////////////////////////// +// Generate unique but human-readable identifiers: + +struct id { + char* text; + void* object; + id *left, *right; + id (const char* t, void* o) : text(strdup(t)), object(o) {left = right = 0;} + ~id(); +}; + +id::~id() { + delete left; + free((void *)text); + delete right; +} + +static id* id_root; + +const char* unique_id(void* o, const char* type, const char* name, const char* label) { + char buffer[128]; + char* q = buffer; + while (*type) *q++ = *type++; + *q++ = '_'; + const char* n = name; + if (!n || !*n) n = label; + if (n && *n) { + while (!is_id(*n)) n++; + while (is_id(*n)) *q++ = *n++; + } + *q = 0; + // okay, search the tree and see if the name was already used: + id** p = &id_root; + int which = 0; + while (*p) { + int i = strcmp(buffer, (*p)->text); + if (!i) { + if ((*p)->object == o) return (*p)->text; + // already used, we need to pick a new name: + sprintf(q,"%x",++which); + p = &id_root; + continue; + } + else if (i < 0) p = &((*p)->left); + else p = &((*p)->right); + } + *p = new id(buffer, o); + return (*p)->text; +} + +//////////////////////////////////////////////////////////////// +// return current indentation: + +static const char* spaces = " "; +int indentation; +const char* indent() { + int i = indentation; if (i>16) i = 16; + return spaces+16-i; +} + +//////////////////////////////////////////////////////////////// +// declarations/include files: +// These are sorted in alphabetical order and only included once each: +// Relies on '#' being less than any letter to put #include first. +// I use a binary tree to sort these out. + +struct included { + char *text; + included *left, *right; + included(const char *t) { + text = strdup(t); + left = right = 0; + } + ~included(); +}; + +included::~included() { + delete left; + fprintf(header_file,"%s\n",text); + free((void *)text); + delete right; +} +static included *included_root; + +int write_declare(const char *format, ...) { + va_list args; + char buf[1024]; + va_start(args, format); + vsprintf(buf, format, args); + va_end(args); + included **p = &included_root; + while (*p) { + int i = strcmp(buf,(*p)->text); + if (!i) return 0; + else if (i < 0) p = &((*p)->left); + else p = &((*p)->right); + } + *p = new included(buf); + return 1; +} + +//////////////////////////////////////////////////////////////// + +// silly thing to prevent declaring unused variables: +// When this symbol is on, all attempts to write code don't write +// anything, but set a variable if it looks like the varaible "o" is used: +int varused_test; +int varused; + +// write an array of C characters (adds a null): +void write_cstring(const char *w, int length) { + if (varused_test) return; + const char *e = w+length; + int linelength = 1; + putc('\"', code_file); + for (; w < e;) { + if (linelength >= 75) {fputs("\\\n",code_file); linelength = 0;} + int c = *w++; + switch (c) { + case '\b': c = 'b'; goto QUOTED; + case '\t': c = 't'; goto QUOTED; + case '\n': c = 'n'; goto QUOTED; + case '\f': c = 'f'; goto QUOTED; + case '\r': c = 'r'; goto QUOTED; + case '\"': + case '\'': + case '\\': + QUOTED: + putc('\\',code_file); + putc(c,code_file); + linelength += 2; + break; + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + if (*w < '0' || *w > '9') {c += '0'; goto QUOTED;} + // else fall through: + default: + if (c < ' ' || c >= 127) { + QUOTENEXT: + fprintf(code_file, "\\x%02x",c&255); + linelength += 4; + c = *w; + if (w < e && (c>='0'&&c<='9' || c>='a'&&c<='f' || c>='A'&&c<='F')) { + w++; goto QUOTENEXT; + } + } else { + putc(c,code_file); + linelength++; + } + break; + } + } + putc('\"', code_file); +} + +// write a C string, quoting characters if necessary: +void write_cstring(const char *w) {write_cstring(w,strlen(w));} + +void write_c(const char* format,...) { + if (varused_test) {varused = 1; return;} + va_list args; + va_start(args, format); + vfprintf(code_file, format, args); + va_end(args); +} + +void write_h(const char* format,...) { + if (varused_test) return; + va_list args; + va_start(args, format); + vfprintf(header_file, format, args); + va_end(args); +} + +#include <FL/filename.H> +int write_number; + +// recursively dump code, putting children between the two parts +// of the parent code: +static Fl_Type* write_code(Fl_Type* p) { + p->write_code1(); + Fl_Type* q; + for (q = p->next; q && q->level > p->level;) q = write_code(q); + p->write_code2(); + return q; +} + +int write_code(const char *s, const char *t) { + write_number++; + delete id_root; id_root = 0; + indentation = 0; + if (!s) code_file = stdout; + else { + FILE *f = fopen(s,"w"); + if (!f) return 0; + code_file = f; + } + if (!t) header_file = stdout; + else { + FILE *f = fopen(t,"w"); + if (!f) {fclose(code_file); return 0;} + header_file = f; + } + const char *hdr = "\ +// generated by Fast Light User Interface Designer (fluid) version %.2f\n\n"; + fprintf(header_file, hdr, FL_VERSION); + fprintf(code_file, hdr, FL_VERSION); + Fl_Type *p; + + for (p = Fl_Type::first; p; p = p->next) p->write_declare(); + delete included_root; included_root = 0; + + if (t) write_c("#include \"%s\"\n", filename_name(t)); + for (p = Fl_Type::first; p; p = p->next) p->write_static(); + for (p = Fl_Type::first; p;) p = write_code(p); + + if (!s) return 1; + int x = fclose(code_file); + code_file = 0; + int y = fclose(header_file); + header_file = 0; + return x >= 0 && y >= 0; +} + +//////////////////////////////////////////////////////////////// + +void Fl_Type::write_declare() {} +void Fl_Type::write_static() {} +void Fl_Type::write_code1() { + write_h("// Header for %s\n", title()); + write_c("// Code for %s\n", title()); +} +void Fl_Type::write_code2() {} diff --git a/fluid/factory.cxx b/fluid/factory.cxx new file mode 100644 index 000000000..5a5ff5383 --- /dev/null +++ b/fluid/factory.cxx @@ -0,0 +1,651 @@ +/* factory.C + + Type classes for most of the fltk widgets. Most of the work + is done by code in Fl_Widget_Type.C. Also a factory instance + of each of these type classes. + + This file also contains the "new" menu, which has a pointer + to a factory instance for every class (both the ones defined + here and ones in other files) +*/ + +#include <FL/Fl.H> +#include <FL/Fl_Group.H> +#include <FL/Fl_Menu_Item.H> +#include <string.h> +#include <stdio.h> + +#if defined(WIN32) || defined(__EMX__) +#define strcasecmp stricmp +#endif + +#include "Fl_Widget_Type.H" + +//////////////////////////////////////////////////////////////// + +#include <FL/Fl_Box.H> +class Fl_Box_Type : public Fl_Widget_Type { +public: + virtual const char *type_name() {return "Fl_Box";} + Fl_Widget *widget(int x,int y,int w, int h) { + return new Fl_Box(x,y,w,h,"label");} + Fl_Widget_Type *_make() {return new Fl_Box_Type();} +}; +static Fl_Box_Type Fl_Box_type; + +//////////////////////////////////////////////////////////////// + +#include <FL/Fl_Button.H> +static Fl_Menu_Item button_type_menu[] = { + {"Normal",0,0,(void*)0}, + {"Toggle",0,0,(void*)FL_TOGGLE_BUTTON}, + {"Radio",0,0,(void*)FL_RADIO_BUTTON}, + {0}}; +class Fl_Button_Type : public Fl_Widget_Type { + Fl_Menu_Item *subtypes() {return button_type_menu;} +public: + virtual const char *type_name() {return "Fl_Button";} + Fl_Widget *widget(int x,int y,int w,int h) { + return new Fl_Button(x,y,w,h,"button");} + Fl_Widget_Type *_make() {return new Fl_Button_Type();} + int is_button() const {return 1;} +}; +static Fl_Button_Type Fl_Button_type; + +//////////////////////////////////////////////////////////////// + +#include <FL/Fl_Return_Button.H> +class Fl_Return_Button_Type : public Fl_Button_Type { +public: + virtual const char *type_name() {return "Fl_Return_Button";} + Fl_Widget *widget(int x,int y,int w,int h) { + return new Fl_Return_Button(x,y,w,h,0);} + Fl_Widget_Type *_make() {return new Fl_Return_Button_Type();} +}; +static Fl_Return_Button_Type Fl_Return_Button_type; + +//////////////////////////////////////////////////////////////// + +#include <FL/Fl_Repeat_Button.H> +class Fl_Repeat_Button_Type : public Fl_Widget_Type { +public: + virtual const char *type_name() {return "Fl_Repeat_Button";} + Fl_Widget *widget(int x,int y,int w,int h) { + return new Fl_Repeat_Button(x,y,w,h,0);} + Fl_Widget_Type *_make() {return new Fl_Repeat_Button_Type();} +}; +static Fl_Repeat_Button_Type Fl_Repeat_Button_type; + +//////////////////////////////////////////////////////////////// + +#include <FL/Fl_Light_Button.H> +class Fl_Light_Button_Type : public Fl_Button_Type { +public: + virtual const char *type_name() {return "Fl_Light_Button";} + Fl_Widget *widget(int x,int y,int w,int h) { + return new Fl_Light_Button(x,y,w,h,"button");} + Fl_Widget_Type *_make() {return new Fl_Light_Button_Type();} +}; +static Fl_Light_Button_Type Fl_Light_Button_type; + +//////////////////////////////////////////////////////////////// + +#include <FL/Fl_Check_Button.H> +class Fl_Check_Button_Type : public Fl_Button_Type { +public: + virtual const char *type_name() {return "Fl_Check_Button";} + Fl_Widget *widget(int x,int y,int w,int h) { + return new Fl_Check_Button(x,y,w,h,"button");} + Fl_Widget_Type *_make() {return new Fl_Check_Button_Type();} +}; +static Fl_Check_Button_Type Fl_Check_Button_type; + +//////////////////////////////////////////////////////////////// + +#include <FL/Fl_Round_Button.H> +class Fl_Round_Button_Type : public Fl_Button_Type { +public: + virtual const char *type_name() {return "Fl_Round_Button";} + Fl_Widget *widget(int x,int y,int w,int h) { + return new Fl_Round_Button(x,y,w,h,"button");} + Fl_Widget_Type *_make() {return new Fl_Round_Button_Type();} +}; +static Fl_Round_Button_Type Fl_Round_Button_type; + +//////////////////////////////////////////////////////////////// + +#include <FL/Fl_Browser.H> +static Fl_Menu_Item browser_type_menu[] = { + {"No Select",0,0,(void*)FL_NORMAL_BROWSER}, + {"Select",0,0,(void*)FL_SELECT_BROWSER}, + {"Hold",0,0,(void*)FL_HOLD_BROWSER}, + {"Multi",0,0,(void*)FL_MULTI_BROWSER}, + {0}}; +class Fl_Browser_Type : public Fl_Widget_Type { + Fl_Menu_Item *subtypes() {return browser_type_menu;} + int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) { + Fl_Browser *o = (Fl_Browser*)(w==4 ? ((Fl_Widget_Type*)this->factory)->o : this->o); + switch (w) { + case 4: + case 0: f = o->textfont(); s = o->textsize(); c = o->textcolor(); break; + case 1: o->textfont(f); break; + case 2: o->textsize(s); break; + case 3: o->textcolor(c); break; + } + return 1; + } +public: + virtual const char *type_name() {return "Fl_Browser";} + Fl_Widget *widget(int x,int y,int w,int h) { + Fl_Browser* b = new Fl_Browser(x,y,w,h); + char buffer[20]; + for (int i = 1; i <= 20; i++) { + sprintf(buffer,"Browser Line %d",i); + b->add(buffer); + } + return b; + } + Fl_Widget_Type *_make() {return new Fl_Browser_Type();} +}; +static Fl_Browser_Type Fl_Browser_type; + +//////////////////////////////////////////////////////////////// + +#include <FL/Fl_Counter.H> +static Fl_Menu_Item counter_type_menu[] = { + {"Normal",0,0,(void*)FL_NORMAL_COUNTER}, + {"Simple",0,0,(void*)FL_SIMPLE_COUNTER}, + {0}}; +class Fl_Counter_Type : public Fl_Widget_Type { + Fl_Menu_Item *subtypes() {return counter_type_menu;} + int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) { + Fl_Counter *o = (Fl_Counter*)(w==4 ? ((Fl_Widget_Type*)this->factory)->o : this->o); + switch (w) { + case 4: + case 0: f = o->textfont(); s = o->textsize(); c = o->textcolor(); break; + case 1: o->textfont(f); break; + case 2: o->textsize(s); break; + case 3: o->textcolor(c); break; + } + return 1; + } + int is_valuator() const {return 1;} +public: + virtual const char *type_name() {return "Fl_Counter";} + Fl_Widget *widget(int x,int y,int w,int h) { + return new Fl_Counter(x,y,w,h,"counter:");} + Fl_Widget_Type *_make() {return new Fl_Counter_Type();} +}; +static Fl_Counter_Type Fl_Counter_type; + +//////////////////////////////////////////////////////////////// + +#include <FL/Fl_Input.H> +static Fl_Menu_Item input_type_menu[] = { + {"Normal",0,0,(void*)FL_NORMAL_INPUT}, + {"Multiline",0,0,(void*)FL_MULTILINE_INPUT}, + {"Secret",0,0,(void*)FL_SECRET_INPUT}, + {"Int",0,0,(void*)FL_INT_INPUT}, + {"Float",0,0,(void*)FL_FLOAT_INPUT}, + {0}}; +class Fl_Input_Type : public Fl_Widget_Type { + Fl_Menu_Item *subtypes() {return input_type_menu;} + int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) { + Fl_Input_ *o = (Fl_Input_*)(w==4 ? ((Fl_Widget_Type*)this->factory)->o : this->o); + switch (w) { + case 4: + case 0: f = o->textfont(); s = o->textsize(); c = o->textcolor(); break; + case 1: o->textfont(f); break; + case 2: o->textsize(s); break; + case 3: o->textcolor(c); break; + } + return 1; + } +public: + virtual const char *type_name() {return "Fl_Input";} + Fl_Widget *widget(int x,int y,int w,int h) { + Fl_Input *o = new Fl_Input(x,y,w,h,"input:"); + o->value("Text Input"); + return o; + } + Fl_Widget_Type *_make() {return new Fl_Input_Type();} +}; +static Fl_Input_Type Fl_Input_type; + +//////////////////////////////////////////////////////////////// + +#include <FL/Fl_Clock.H> +class Fl_Clock_Type : public Fl_Widget_Type { +public: + virtual const char *type_name() {return "Fl_Clock";} + Fl_Widget *widget(int x,int y,int w,int h) { + return new Fl_Clock(x,y,w,h);} + Fl_Widget_Type *_make() {return new Fl_Clock_Type();} +}; +static Fl_Clock_Type Fl_Clock_type; + +//////////////////////////////////////////////////////////////// + +#include <FL/Fl_Adjuster.H> +class Fl_Adjuster_Type : public Fl_Widget_Type { + int is_valuator() const {return 1;} +public: + virtual const char *type_name() {return "Fl_Adjuster";} + Fl_Widget *widget(int x,int y,int w,int h) { + return new Fl_Adjuster(x,y,w,h);} + Fl_Widget_Type *_make() {return new Fl_Adjuster_Type();} +}; +static Fl_Adjuster_Type Fl_Adjuster_type; + +//////////////////////////////////////////////////////////////// + +#include <FL/Fl_Dial.H> +static Fl_Menu_Item dial_type_menu[] = { + {"Dot",0,0,(void*)0}, + {"Line",0,0,(void*)FL_LINE_DIAL}, + {"Fill",0,0,(void*)FL_FILL_DIAL}, + {0}}; +class Fl_Dial_Type : public Fl_Widget_Type { + Fl_Menu_Item *subtypes() {return dial_type_menu;} + int is_valuator() const {return 1;} +public: + virtual const char *type_name() {return "Fl_Dial";} + Fl_Widget *widget(int x,int y,int w,int h) { + return new Fl_Dial(x,y,w,h);} + Fl_Widget_Type *_make() {return new Fl_Dial_Type();} +}; +static Fl_Dial_Type Fl_Dial_type; + +//////////////////////////////////////////////////////////////// + +#include <FL/Fl_Roller.H> +static Fl_Menu_Item roller_type_menu[] = { + {"Vertical",0,0,(void*)0}, + {"Horizontal",0,0,(void*)FL_HORIZONTAL}, + {0}}; +class Fl_Roller_Type : public Fl_Widget_Type { + Fl_Menu_Item *subtypes() {return roller_type_menu;} + int is_valuator() const {return 1;} +public: + virtual const char *type_name() {return "Fl_Roller";} + Fl_Widget *widget(int x,int y,int w,int h) { + return new Fl_Roller(x,y,w,h);} + Fl_Widget_Type *_make() {return new Fl_Roller_Type();} +}; +static Fl_Roller_Type Fl_Roller_type; + +//////////////////////////////////////////////////////////////// + +#include <FL/Fl_Scrollbar.H> +static Fl_Menu_Item slider_type_menu[] = { + {"Vertical",0,0,(void*)FL_VERT_SLIDER}, + {"Horizontal",0,0,(void*)FL_HOR_SLIDER}, + {"Vert Fill",0,0,(void*)FL_VERT_FILL_SLIDER}, + {"Horz Fill",0,0,(void*)FL_HOR_FILL_SLIDER}, + {"Vert Knob",0,0,(void*)FL_VERT_NICE_SLIDER}, + {"Horz Knob",0,0,(void*)FL_HOR_NICE_SLIDER}, + {0}}; +class Fl_Slider_Type : public Fl_Widget_Type { + Fl_Menu_Item *subtypes() {return slider_type_menu;} + int is_valuator() const {return 2;} +public: + virtual const char *type_name() {return "Fl_Slider";} + Fl_Widget *widget(int x,int y,int w,int h) { + return new Fl_Slider(x,y,w,h);} + Fl_Widget_Type *_make() {return new Fl_Slider_Type();} +}; +static Fl_Slider_Type Fl_Slider_type; + +static Fl_Menu_Item scrollbar_type_menu[] = { + {"Vertical",0,0,(void*)FL_VERT_SLIDER}, + {"Horizontal",0,0,(void*)FL_HOR_SLIDER}, + {0}}; +class Fl_Scrollbar_Type : public Fl_Slider_Type { + Fl_Menu_Item *subtypes() {return scrollbar_type_menu;} +public: + virtual const char *type_name() {return "Fl_Scrollbar";} + Fl_Widget *widget(int x,int y,int w,int h) { + return new Fl_Scrollbar(x,y,w,h);} + Fl_Widget_Type *_make() {return new Fl_Scrollbar_Type();} +}; +static Fl_Scrollbar_Type Fl_Scrollbar_type; + +//////////////////////////////////////////////////////////////// + +#include <FL/Fl_Output.H> +static Fl_Menu_Item output_type_menu[] = { + {"Normal",0,0,(void*)FL_NORMAL_INPUT}, + {"Multiline",0,0,(void*)FL_MULTILINE_INPUT}, + {0}}; +class Fl_Output_Type : public Fl_Input_Type { + Fl_Menu_Item *subtypes() {return output_type_menu;} +public: + virtual const char *type_name() {return "Fl_Output";} + Fl_Widget *widget(int x,int y,int w,int h) { + Fl_Output *o = new Fl_Output(x,y,w,h,"output:"); + o->value("Text Output"); + return o; + } + Fl_Widget_Type *_make() {return new Fl_Output_Type();} +}; +static Fl_Output_Type Fl_Output_type; + +//////////////////////////////////////////////////////////////// + +#include <FL/Fl_Value_Input.H> +class Fl_Value_Input_Type : public Fl_Widget_Type { +public: + virtual const char *type_name() {return "Fl_Value_Input";} + int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) { + Fl_Value_Input *o = (Fl_Value_Input*)(w==4 ? ((Fl_Widget_Type*)this->factory)->o : this->o); + switch (w) { + case 4: + case 0: f = o->textfont(); s = o->textsize(); c = o->textcolor(); break; + case 1: o->textfont(f); break; + case 2: o->textsize(s); break; + case 3: o->textcolor(c); break; + } + return 1; + } + int is_valuator() const {return 1;} + Fl_Widget *widget(int x,int y,int w,int h) { + Fl_Value_Input *o = new Fl_Value_Input(x,y,w,h,"value:"); + return o; + } + Fl_Widget_Type *_make() {return new Fl_Value_Input_Type();} +}; +static Fl_Value_Input_Type Fl_Value_Input_type; + +//////////////////////////////////////////////////////////////// + +#include <FL/Fl_Value_Output.H> +class Fl_Value_Output_Type : public Fl_Widget_Type { +public: + virtual const char *type_name() {return "Fl_Value_Output";} + int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) { + Fl_Value_Output *o = (Fl_Value_Output*)(w==4 ? ((Fl_Widget_Type*)this->factory)->o : this->o); + switch (w) { + case 4: + case 0: f = o->textfont(); s = o->textsize(); c = o->textcolor(); break; + case 1: o->textfont(f); break; + case 2: o->textsize(s); break; + case 3: o->textcolor(c); break; + } + return 1; + } + int is_valuator() const {return 1;} + Fl_Widget *widget(int x,int y,int w,int h) { + Fl_Value_Output *o = new Fl_Value_Output(x,y,w,h,"value:"); + return o; + } + Fl_Widget_Type *_make() {return new Fl_Value_Output_Type();} +}; +static Fl_Value_Output_Type Fl_Value_Output_type; + +//////////////////////////////////////////////////////////////// + +#include <FL/Fl_Value_Slider.H> +class Fl_Value_Slider_Type : public Fl_Slider_Type { + int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) { + Fl_Value_Slider *o = (Fl_Value_Slider*)(w==4 ? ((Fl_Widget_Type*)this->factory)->o : this->o); + switch (w) { + case 4: + case 0: f = o->textfont(); s = o->textsize(); c = o->textcolor(); break; + case 1: o->textfont(f); break; + case 2: o->textsize(s); break; + case 3: o->textcolor(c); break; + } + return 1; + } +public: + virtual const char *type_name() {return "Fl_Value_Slider";} + Fl_Widget *widget(int x,int y,int w,int h) { + return new Fl_Value_Slider(x,y,w,h);} + Fl_Widget_Type *_make() {return new Fl_Value_Slider_Type();} +}; +static Fl_Value_Slider_Type Fl_Value_Slider_type; + +//////////////////////////////////////////////////////////////// + +extern class Fl_Function_Type Fl_Function_type; +extern class Fl_Code_Type Fl_Code_type; +extern class Fl_CodeBlock_Type Fl_CodeBlock_type; +extern class Fl_Decl_Type Fl_Decl_type; +extern class Fl_DeclBlock_Type Fl_DeclBlock_type; +extern class Fl_Class_Type Fl_Class_type; +extern class Fl_Window_Type Fl_Window_type; +extern class Fl_Group_Type Fl_Group_type; +extern class Fl_Tabs_Type Fl_Tabs_type; +extern class Fl_Scroll_Type Fl_Scroll_type; +extern class Fl_Tile_Type Fl_Tile_type; +extern class Fl_Choice_Type Fl_Choice_type; +extern class Fl_Menu_Bar_Type Fl_Menu_Bar_type; +extern class Fl_Menu_Button_Type Fl_Menu_Button_type; +extern class Fl_Menu_Item_Type Fl_Menu_Item_type; +extern class Fl_Submenu_Type Fl_Submenu_type; + +extern void select(Fl_Type *,int); +extern void select_only(Fl_Type *); + +static void cb(Fl_Widget *, void *v) { + Fl_Type *t = ((Fl_Type*)v)->make(); + if (t) {select_only(t); modflag = 1; t->open();} +} + +Fl_Menu_Item New_Menu[] = { +{"code",0,0,0,FL_SUBMENU}, + {"function/method",0,cb,(void*)&Fl_Function_type}, + {"code",0,cb,(void*)&Fl_Code_type}, + {"code block",0,cb,(void*)&Fl_CodeBlock_type}, + {"declaration",0,cb,(void*)&Fl_Decl_type}, + {"declaration block",0,cb,(void*)&Fl_DeclBlock_type}, + {"class",0,cb,(void*)&Fl_Class_type}, +{0}, +{"group",0,0,0,FL_SUBMENU}, + {0,0,cb,(void*)&Fl_Window_type}, + {0,0,cb,(void*)&Fl_Group_type}, + {0,0,cb,(void*)&Fl_Tabs_type}, + {0,0,cb,(void*)&Fl_Scroll_type}, + {0,0,cb,(void*)&Fl_Tile_type}, +{0}, +{"buttons",0,0,0,FL_SUBMENU}, + {0,0,cb,(void*)&Fl_Button_type}, + {0,0,cb,(void*)&Fl_Return_Button_type}, + {0,0,cb,(void*)&Fl_Light_Button_type}, + {0,0,cb,(void*)&Fl_Check_Button_type}, + {0,0,cb,(void*)&Fl_Round_Button_type}, + {0,0,cb,(void*)&Fl_Repeat_Button_type}, +{0}, +{"valuators",0,0,0,FL_SUBMENU}, + {0,0,cb,(void*)&Fl_Slider_type}, + {0,0,cb,(void*)&Fl_Scrollbar_type}, + {0,0,cb,(void*)&Fl_Value_Slider_type}, + {0,0,cb,(void*)&Fl_Adjuster_type}, + {0,0,cb,(void*)&Fl_Counter_type}, + {0,0,cb,(void*)&Fl_Dial_type}, + {0,0,cb,(void*)&Fl_Roller_type}, + {0,0,cb,(void*)&Fl_Value_Input_type}, + {0,0,cb,(void*)&Fl_Value_Output_type}, +{0}, +{"text",0,0,0,FL_SUBMENU}, + {0,0,cb,(void*)&Fl_Input_type}, + {0,0,cb,(void*)&Fl_Output_type}, +{0}, +{"menus",0,0,0,FL_SUBMENU}, + {0,0,cb,(void*)&Fl_Menu_Bar_type}, + {0,0,cb,(void*)&Fl_Menu_Button_type}, + {0,0,cb,(void*)&Fl_Choice_type}, + {0,0,cb, (void*)&Fl_Submenu_type}, + {0,0,cb, (void*)&Fl_Menu_Item_type}, +{0}, +{"other",0,0,0,FL_SUBMENU}, + {0,0,cb,(void*)&Fl_Browser_type}, + {0,0,cb,(void*)&Fl_Box_type}, + {0,0,cb,(void*)&Fl_Clock_type}, +{0}, +{0}}; + +void fill_in_New_Menu() { + for (unsigned i = 0; i < sizeof(New_Menu)/sizeof(*New_Menu); i++) { + Fl_Menu_Item *m = New_Menu+i; + if (m->user_data() && !m->text) { + const char *n = ((Fl_Type*)(m->user_data()))->type_name(); + if (!strncmp(n,"Fl_",3)) n += 3; + m->text = n; + } + } +} + +// use keyword to pick the type, this is used to parse files: +int reading_file; +Fl_Type *Fl_Type_make(const char *tn) { + reading_file = 1; // makes labels be null + Fl_Type *r = 0; + for (unsigned i = 0; i < sizeof(New_Menu)/sizeof(*New_Menu); i++) { + Fl_Menu_Item *m = New_Menu+i; + if (!m->user_data()) continue; + Fl_Type *t = (Fl_Type*)(m->user_data()); + if (!strcasecmp(tn,t->type_name())) {r = t->make(); break;} + } + reading_file = 0; + return r; +} + +//////////////////////////////////////////////////////////////// + +// Since I have included all the .H files, do this table here: +// This table is only used to read fdesign files: + +struct symbol {const char *name; int value;}; + +static symbol table[] = { + {"BLACK", FL_BLACK}, + {"RED", FL_RED}, + {"GREEN", FL_GREEN}, + {"YELLOW", FL_YELLOW}, + {"BLUE", FL_BLUE}, + {"MAGENTA", FL_MAGENTA}, + {"CYAN", FL_CYAN}, + {"WHITE", FL_WHITE}, + + {"LCOL", FL_BLACK}, + {"COL1", FL_GRAY}, + {"MCOL", FL_LIGHT1}, + {"LEFT_BCOL", FL_LIGHT3}, + {"TOP_BCOL", FL_LIGHT2}, + {"BOTTOM_BCOL", FL_DARK2}, + {"RIGHT_BCOL", FL_DARK3}, + {"INACTIVE", FL_INACTIVE_COLOR}, + {"INACTIVE_COL", FL_INACTIVE_COLOR}, + {"FREE_COL1", FL_FREE_COLOR}, + {"FREE_COL2", FL_FREE_COLOR+1}, + {"FREE_COL3", FL_FREE_COLOR+2}, + {"FREE_COL4", FL_FREE_COLOR+3}, + {"FREE_COL5", FL_FREE_COLOR+4}, + {"FREE_COL6", FL_FREE_COLOR+5}, + {"FREE_COL7", FL_FREE_COLOR+6}, + {"FREE_COL8", FL_FREE_COLOR+7}, + {"FREE_COL9", FL_FREE_COLOR+8}, + {"FREE_COL10", FL_FREE_COLOR+9}, + {"FREE_COL11", FL_FREE_COLOR+10}, + {"FREE_COL12", FL_FREE_COLOR+11}, + {"FREE_COL13", FL_FREE_COLOR+12}, + {"FREE_COL14", FL_FREE_COLOR+13}, + {"FREE_COL15", FL_FREE_COLOR+14}, + {"FREE_COL16", FL_FREE_COLOR+15}, + {"TOMATO", 131}, + {"INDIANRED", 164}, + {"SLATEBLUE", 195}, + {"DARKGOLD", 84}, + {"PALEGREEN", 157}, + {"ORCHID", 203}, + {"DARKCYAN", 189}, + {"DARKTOMATO", 113}, + {"WHEAT", 174}, + {"ALIGN_CENTER", FL_ALIGN_CENTER}, + {"ALIGN_TOP", FL_ALIGN_TOP}, + {"ALIGN_BOTTOM", FL_ALIGN_BOTTOM}, + {"ALIGN_LEFT", FL_ALIGN_LEFT}, + {"ALIGN_RIGHT", FL_ALIGN_RIGHT}, + {"ALIGN_INSIDE", FL_ALIGN_INSIDE}, + {"ALIGN_TOP_LEFT", FL_ALIGN_TOP | FL_ALIGN_LEFT}, + {"ALIGN_TOP_RIGHT", FL_ALIGN_TOP | FL_ALIGN_RIGHT}, + {"ALIGN_BOTTOM_LEFT", FL_ALIGN_BOTTOM | FL_ALIGN_LEFT}, + {"ALIGN_BOTTOM_RIGHT", FL_ALIGN_BOTTOM | FL_ALIGN_RIGHT}, + {"ALIGN_CENTER|FL_ALIGN_INSIDE", FL_ALIGN_CENTER|FL_ALIGN_INSIDE}, + {"ALIGN_TOP|FL_ALIGN_INSIDE", FL_ALIGN_TOP|FL_ALIGN_INSIDE}, + {"ALIGN_BOTTOM|FL_ALIGN_INSIDE", FL_ALIGN_BOTTOM|FL_ALIGN_INSIDE}, + {"ALIGN_LEFT|FL_ALIGN_INSIDE", FL_ALIGN_LEFT|FL_ALIGN_INSIDE}, + {"ALIGN_RIGHT|FL_ALIGN_INSIDE", FL_ALIGN_RIGHT|FL_ALIGN_INSIDE}, + {"ALIGN_INSIDE|FL_ALIGN_INSIDE", FL_ALIGN_INSIDE|FL_ALIGN_INSIDE}, + {"ALIGN_TOP_LEFT|FL_ALIGN_INSIDE", FL_ALIGN_TOP|FL_ALIGN_LEFT|FL_ALIGN_INSIDE}, + {"ALIGN_TOP_RIGHT|FL_ALIGN_INSIDE", FL_ALIGN_TOP|FL_ALIGN_RIGHT|FL_ALIGN_INSIDE}, + {"ALIGN_BOTTOM_LEFT|FL_ALIGN_INSIDE", FL_ALIGN_BOTTOM|FL_ALIGN_LEFT|FL_ALIGN_INSIDE}, + {"ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE",FL_ALIGN_BOTTOM|FL_ALIGN_RIGHT|FL_ALIGN_INSIDE}, + + {"ALIGN_LEFT_TOP", FL_ALIGN_TOP | FL_ALIGN_LEFT}, + {"ALIGN_RIGHT_TOP", FL_ALIGN_TOP | FL_ALIGN_RIGHT}, + {"ALIGN_LEFT_BOTTOM", FL_ALIGN_BOTTOM | FL_ALIGN_LEFT}, + {"ALIGN_RIGHT_BOTTOM", FL_ALIGN_BOTTOM | FL_ALIGN_RIGHT}, + {"INVALID_STYLE", 255}, + {"NORMAL_STYLE", FL_HELVETICA}, + {"BOLD_STYLE", FL_HELVETICA|FL_BOLD}, + {"ITALIC_STYLE", FL_HELVETICA|FL_ITALIC}, + {"BOLDITALIC_STYLE", FL_HELVETICA|FL_BOLD|FL_ITALIC}, + {"FIXED_STYLE", FL_COURIER}, + {"FIXEDBOLD_STYLE", FL_COURIER|FL_BOLD}, + {"FIXEDITALIC_STYLE", FL_COURIER|FL_ITALIC}, + {"FIXEDBOLDITALIC_STYLE", FL_COURIER|FL_BOLD|FL_ITALIC}, + {"TIMES_STYLE", FL_TIMES}, + {"TIMESBOLD_STYLE", FL_TIMES|FL_BOLD}, + {"TIMESITALIC_STYLE", FL_TIMES|FL_ITALIC}, + {"TIMESBOLDITALIC_STYLE", FL_TIMES|FL_BOLD|FL_ITALIC}, + {"SHADOW_STYLE", (_FL_SHADOW_LABEL<<8)}, + {"ENGRAVED_STYLE", (_FL_ENGRAVED_LABEL<<8)}, + {"EMBOSSED_STYLE", (_FL_EMBOSSED_LABEL<<0)}, + {"TINY_SIZE", 8}, + {"SMALL_SIZE", 11}, + {"NORMAL_SIZE", FL_NORMAL_SIZE}, + {"MEDIUM_SIZE", 18}, + {"LARGE_SIZE", 24}, + {"HUGE_SIZE", 32}, + {"DEFAULT_SIZE", FL_NORMAL_SIZE}, + {"TINY_FONT", 8}, + {"SMALL_FONT", 11}, + {"NORMAL_FONT", FL_NORMAL_SIZE}, + {"MEDIUM_FONT", 18}, + {"LARGE_FONT", 24}, + {"HUGE_FONT", 32}, + {"NORMAL_FONT1", 11}, + {"NORMAL_FONT2", FL_NORMAL_SIZE}, + {"DEFAULT_FONT", 11}, + {"RETURN_END_CHANGED", 0}, + {"RETURN_CHANGED", 1}, + {"RETURN_END", 2}, + {"RETURN_ALWAYS", 3}, + {"PUSH_BUTTON", FL_TOGGLE_BUTTON}, + {"RADIO_BUTTON", FL_RADIO_BUTTON}, + {"HIDDEN_BUTTON", FL_HIDDEN_BUTTON}, + {"SELECT_BROWSER", FL_SELECT_BROWSER}, + {"HOLD_BROWSER", FL_HOLD_BROWSER}, + {"MULTI_BROWSER", FL_MULTI_BROWSER}, + {"SIMPLE_COUNTER", FL_SIMPLE_COUNTER}, + {"LINE_DIAL", FL_LINE_DIAL}, + {"FILL_DIAL", FL_FILL_DIAL}, + {"VERT_SLIDER", FL_VERT_SLIDER}, + {"HOR_SLIDER", FL_HOR_SLIDER}, + {"VERT_FILL_SLIDER", FL_VERT_FILL_SLIDER}, + {"HOR_FILL_SLIDER", FL_HOR_FILL_SLIDER}, + {"VERT_NICE_SLIDER", FL_VERT_NICE_SLIDER}, + {"HOR_NICE_SLIDER", FL_HOR_NICE_SLIDER}, +}; + +#include <stdlib.h> + +int lookup_symbol(const char *name, int &v, int numberok) { + if (name[0]=='F' && name[1]=='L' && name[2]=='_') name += 3; + for (int i=0; i < int(sizeof(table)/sizeof(*table)); i++) + if (!strcasecmp(name,table[i].name)) {v = table[i].value; return 1;} + if (numberok && ((v = atoi(name)) || !strcmp(name,"0"))) return 1; + return 0; +} diff --git a/fluid/file.cxx b/fluid/file.cxx new file mode 100644 index 000000000..69bc97d17 --- /dev/null +++ b/fluid/file.cxx @@ -0,0 +1,562 @@ +/* file.C + + Code to read and write Fluid .fl files + + You may find the basic read_* and write_* routines to + be useful for other programs. I have used them many times. + They are somewhat similar to tcl, using matching { and } + to quote strings. + +*/ + +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> + +//////////////////////////////////////////////////////////////// +// BASIC FILE WRITING: + +static FILE *fout; + +int open_write(const char *s) { + if (!s) {fout = stdout; return 1;} + FILE *f = fopen(s,"w"); + if (!f) return 0; + fout = f; + return 1; +} + +int close_write() { + if (fout != stdout) { + int x = fclose(fout); + fout = stdout; + return x >= 0; + } + return 1; +} + +static int needspace; +int is_id(char); // in code.C + +// write a string, quoting characters if necessary: +void write_word(const char *w) { + if (needspace) putc(' ', fout); + needspace = 1; + if (!w || !*w) {fprintf(fout,"{}"); return;} + const char *p; + // see if it is a single word: + for (p = w; is_id(*p); p++) ; + if (!*p) {fprintf(fout,"%s",w); return;} + // see if there are matching braces: + int n = 0; + for (p = w; *p; p++) { + if (*p == '{') n++; + else if (*p == '}') {n--; if (n<0) break;} + } + int mismatched = (n != 0); + // write out brace-quoted string: + putc('{', fout); + for (; *w; w++) { + switch (*w) { + case '{': + case '}': + if (!mismatched) break; + case '\\': + case '#': + putc('\\',fout); + break; + } + putc(*w,fout); + } + putc('}', fout); +} + +// write an arbitrary formatted word, or a comment, etc: +void write_string(const char *format, ...) { + va_list args; + va_start(args, format); + if (needspace) fputc(' ',fout); + vfprintf(fout, format, args); + va_end(args); + needspace = !isspace(format[strlen(format)-1]); +} + +// start a new line and indent it for a given nesting level: +void write_indent(int n) { + fputc('\n',fout); + while (n--) {fputc(' ',fout); fputc(' ',fout);} + needspace = 0; +} + +// write a '{' at the given indenting level: +void write_open(int) { + if (needspace) fputc(' ',fout); + fputc('{',fout); + needspace = 0; +} + +// write a '}' at the given indenting level: +void write_close(int n) { + if (needspace) write_indent(n); + fputc('}',fout); + needspace = 1; +} + +//////////////////////////////////////////////////////////////// +// BASIC FILE READING: + +static FILE *fin; +static int lineno; +static const char *fname; + +int open_read(const char *s) { + lineno = 1; + if (!s) {fin = stdin; fname = "stdin"; return 1;} + FILE *f = fopen(s,"r"); + if (!f) return 0; + fin = f; + fname = s; + return 1; +} + +int close_read() { + if (fin != stdin) { + int x = fclose(fin); + fin = 0; + return x >= 0; + } + return 1; +} + +#include <FL/fl_message.H> + +void read_error(const char *format, ...) { + va_list args; + va_start(args, format); + if (!fin) { + char buffer[1024]; + vsprintf(buffer, format, args); + fl_message(buffer); + } else { + fprintf(stderr, "%s:%d: ", fname, lineno); + vfprintf(stderr, format, args); + fprintf(stderr, "\n"); + } + va_end(args); +} + +static int hexdigit(int x) { + if (isdigit(x)) return x-'0'; + if (isupper(x)) return x-'A'+10; + if (islower(x)) return x-'a'+10; + return 20; +} + + +static int read_quoted() { // read whatever character is after a \ . + int c,d,x; + switch(c = fgetc(fin)) { + case '\n': lineno++; return -1; + case 'a' : return('\a'); + case 'b' : return('\b'); + case 'f' : return('\f'); + case 'n' : return('\n'); + case 'r' : return('\r'); + case 't' : return('\t'); + case 'v' : return('\v'); + case 'x' : /* read hex */ + for (c=x=0; x<3; x++) { + int ch = fgetc(fin); + d = hexdigit(ch); + if (d > 15) {ungetc(ch,fin); break;} + c = (c<<4)+d; + } + break; + default: /* read octal */ + if (c<'0' || c>'7') break; + c -= '0'; + for (x=0; x<2; x++) { + int ch = fgetc(fin); + d = hexdigit(ch); + if (d>7) {ungetc(ch,fin); break;} + c = (c<<3)+d; + } + break; + } + return(c); +} + +// return a word read from the file, or NULL at the EOF: +// This will skip all comments (# to end of line), and evaluate +// all \xxx sequences and use \ at the end of line to remove the newline. +// A word is any one of: +// a continuous string of non-space chars except { and } and # +// everything between matching {...} (unless wantbrace != 0) +// the characters '{' and '}' + +static char *buffer; +static int buflen; +static void expand_buffer(int length) { + if (length >= buflen) { + if (!buflen) { + buflen = length+1; + buffer = (char*)malloc(buflen); + } else { + buflen = 2*buflen; + if (length >= buflen) buflen = length+1; + buffer = (char *)realloc((void *)buffer,buflen); + } + } +} + +const char *read_word(int wantbrace) { + int x; + + // skip all the whitespace before it: + for (;;) { + x = getc(fin); + if (x < 0) { // eof + return 0; + } else if (x == '#') { // comment + do x = getc(fin); while (x >= 0 && x != '\n'); + lineno++; + continue; + } else if (x == '\n') { + lineno++; + } else if (!isspace(x)) { + break; + } + } + + expand_buffer(100); + + if (x == '{' && !wantbrace) { + + // read in whatever is between braces + int length = 0; + int nesting = 0; + for (;;) { + x = getc(fin); + if (x<0) {read_error("Missing '}'"); break;} + else if (x == '#') { // embedded comment + do x = getc(fin); while (x >= 0 && x != '\n'); + lineno++; + continue; + } else if (x == '\n') lineno++; + else if (x == '\\') {x = read_quoted(); if (x<0) continue;} + else if (x == '{') nesting++; + else if (x == '}') {if (!nesting--) break;} + buffer[length++] = x; + expand_buffer(length); + } + buffer[length] = 0; + return buffer; + + } else if (x == '{' || x == '}') { + // all the punctuation is a word: + buffer[0] = x; + buffer[1] = 0; + return buffer; + + } else { + + // read in an unquoted word: + int length = 0; + for (;;) { + if (x == '\\') {x = read_quoted(); if (x<0) continue;} + else if (x<0 || isspace(x) || x=='{' || x=='}' || x=='#') break; + buffer[length++] = x; + expand_buffer(length); + x = getc(fin); + } + ungetc(x, fin); + buffer[length] = 0; + return buffer; + + } +} + +//////////////////////////////////////////////////////////////// + +#include <FL/Fl.H> +#include "Fl_Widget_Type.H" + +// global int variables: +extern int gridx, gridy, snap; +static struct {const char* name; int* value;} inttable[] = { + {"gridx", &gridx}, + {"gridy", &gridy}, + {"snap", &snap} +}; + +extern const char* header_file_name; +extern const char* code_file_name; + +int write_file(const char *filename, int selected_only) { + if (!open_write(filename)) return 0; + write_string("# data file for the Fltk User Interface Designer (fluid)\n" + "version %.2f",FL_VERSION); + if (!selected_only) { + write_string("\nheader_name"); write_word(header_file_name); + write_string("\ncode_name"); write_word(code_file_name); + for (unsigned int i=0; i<sizeof(inttable)/sizeof(*inttable); i++) + write_string("\n%s %d",inttable[i].name, *inttable[i].value); + } + for (Fl_Type *p = Fl_Type::first; p;) { + if (!selected_only || p->selected) { + p->write(); + write_string("\n"); + int q = p->level; + for (p = p->next; p && p->level > q; p = p->next); + } else { + p = p->next; + } + } + return close_write(); +} + +//////////////////////////////////////////////////////////////// +// read all the objects out of the input file: + +void read_fdesign(); + +double read_version; + +extern Fl_Type *Fl_Type_make(const char *tn); + +static void read_children(Fl_Type *p, int paste) { + Fl_Type::current = p; + for (;;) { + unsigned int i; + const char *c = read_word(); + REUSE_C: + if (!c) { + if (p && !paste) read_error("Missing '}'"); + break; + } + + if (!strcmp(c,"}")) { + if (!p) read_error("Unexpected '}'"); + break; + } + + // this is the first word in a .fd file: + if (!strcmp(c,"Magic:")) { + read_fdesign(); + return; + } + + if (!strcmp(c,"version")) { + c = read_word(); + read_version = strtod(c,0); + if (read_version<=0 || read_version>FL_VERSION) + read_error("unknown version '%s'",c); + continue; + } + + // back compatability with Vincent Penne's original class code: + if (!p && !strcmp(c,"define_in_struct")) { + Fl_Type *t = Fl_Type_make("class"); + t->name(read_word()); + Fl_Type::current = p = t; + paste = 1; // stops "missing }" error + continue; + } + + if (!strcmp(c,"header_name")) { + header_file_name = strdup(read_word()); + goto CONTINUE; + } + + if (!strcmp(c,"code_name")) { + code_file_name = strdup(read_word()); + goto CONTINUE; + } + + for (i=0; i<sizeof(inttable)/sizeof(*inttable); i++) { + if (!strcmp(c,inttable[i].name)) { + c = read_word(); + *inttable[i].value = atoi(c); + goto CONTINUE; + } + } + + {Fl_Type *t = Fl_Type_make(c); + if (!t) { + read_error("Unknown word \"%s\"", c); + continue; + } + t->name(read_word()); + + c = read_word(1); + if (strcmp(c,"{")) { + read_error("Missing property list for %s\n",t->title()); + goto REUSE_C; + } + + t->open_ = 0; + for (;;) { + const char *c = read_word(); + if (!c || !strcmp(c,"}")) break; + t->read_property(c); + } + + if (!t->is_parent()) continue; + c = read_word(1); + if (strcmp(c,"{")) { + read_error("Missing child list for %s\n",t->title()); + goto REUSE_C; + } + read_children(t, 0);} + Fl_Type::current = p; + CONTINUE:; + } +} + +extern void deselect(); + +int read_file(const char *filename, int merge) { + read_version = 0.0; + if (!open_read(filename)) return 0; + if (merge) deselect(); else delete_all(); + read_children(Fl_Type::current, merge); + Fl_Type::current = 0; + for (Fl_Type *o = Fl_Type::first; o; o = o->next) + if (o->selected) {Fl_Type::current = o; break;} + return close_read(); +} + +//////////////////////////////////////////////////////////////// +// Read Forms and XForms fdesign files: + +int read_fdesign_line(const char*& name, const char*& value) { + + int length = 0; + int x; + // find a colon: + for (;;) { + x = getc(fin); + if (x < 0) return 0; + if (x == '\n') {length = 0; continue;} // no colon this line... + if (!isspace(x)) { + buffer[length++] = x; + expand_buffer(length); + } + if (x == ':') break; + } + int valueoffset = length; + buffer[length-1] = 0; + + // skip to start of value: + for (;;) { + x = getc(fin); + if (x < 0 || x == '\n' || !isspace(x)) break; + } + + // read the value: + for (;;) { + if (x == '\\') {x = read_quoted(); if (x<0) continue;} + else if (x == '\n') break; + buffer[length++] = x; + expand_buffer(length); + x = getc(fin); + } + buffer[length] = 0; + name = buffer; + value = buffer+valueoffset; + return 1; +} + +int fdesign_flip; +int fdesign_magic; +#include <FL/Fl_Group.H> + +static const char *class_matcher[] = { +"FL_CHECKBUTTON", "Fl_Check_Button", +"FL_ROUNDBUTTON", "Fl_Round_Button", +"FL_ROUND3DBUTTON", "Fl_Round_Button", +"FL_LIGHTBUTTON", "Fl_Light_Button", +"FL_FRAME", "Fl_Box", +"FL_LABELFRAME", "Fl_Box", +"FL_TEXT", "Fl_Box", +"FL_VALSLIDER", "Fl_Value_Slider", +"FL_MENU", "Fl_Menu_Button", +"3", "FL_BITMAP", +"1", "FL_BOX", +"71","FL_BROWSER", +"11","FL_BUTTON", +"4", "FL_CHART", +"42","FL_CHOICE", +"61","FL_CLOCK", +"25","FL_COUNTER", +"22","FL_DIAL", +"101","FL_FREE", +"31","FL_INPUT", +"12","Fl_Light_Button", +"41","FL_MENU", +"23","FL_POSITIONER", +"13","Fl_Round_Button", +"21","FL_SLIDER", +"2", "FL_BOX", // was FL_TEXT +"62","FL_TIMER", +"24","Fl_Value_Slider", +0}; + +void read_fdesign() { + fdesign_magic = atoi(read_word()); + fdesign_flip = (fdesign_magic < 13000); + Fl_Widget_Type *window = 0; + Fl_Widget_Type *group = 0; + Fl_Widget_Type *widget = 0; + if (!Fl_Type::current) { + Fl_Type *t = Fl_Type_make("Function"); + t->name("create_the_forms()"); + Fl_Type::current = t; + } + for (;;) { + const char *name; + const char *value; + if (!read_fdesign_line(name, value)) break; + + if (!strcmp(name,"Name")) { + + window = (Fl_Widget_Type*)Fl_Type_make("Fl_Window"); + window->name(value); + window->label(value); + Fl_Type::current = widget = window; + + } else if (!strcmp(name,"class")) { + + if (!strcmp(value,"FL_BEGIN_GROUP")) { + group = widget = (Fl_Widget_Type*)Fl_Type_make("Fl_Group"); + Fl_Type::current = group; + } else if (!strcmp(value,"FL_END_GROUP")) { + if (group) { + Fl_Group* g = (Fl_Group*)(group->o); + g->begin(); + g->forms_end(); + Fl_Group::current(0); + } + group = widget = 0; + Fl_Type::current = window; + } else { + for (int i = 0; class_matcher[i]; i += 2) + if (!strcmp(value,class_matcher[i])) { + value = class_matcher[i+1]; break;} + widget = (Fl_Widget_Type*)Fl_Type_make(value); + if (!widget) { + printf("class %s not found, using Fl_Button\n", value); + widget = (Fl_Widget_Type*)Fl_Type_make("Fl_Button"); + } + } + + } else if (widget) { + if (!widget->read_fdesign(name, value)) + printf("Ignoring \"%s: %s\"\n", name, value); + } + } +} + + diff --git a/fluid/fluid.cxx b/fluid/fluid.cxx new file mode 100644 index 000000000..384eb5104 --- /dev/null +++ b/fluid/fluid.cxx @@ -0,0 +1,387 @@ +// fluid.C + +// Please see README for some information about the construction of this +// rather nasty piece of code. + +const char *copyright = +"The FLTK user interface designer version 0.99\n" +"Copyright \xa9 1998 Bill Spitzak\n" +"\n" +"This library is free software; you can redistribute it and/or " +"modify it under the terms of the GNU Library General Public " +"License as published by the Free Software Foundation; either " +"version 2 of the License, or (at your option) any later version.\n" +"\n" +"This library is distributed in the hope that it will be useful, " +"but WITHOUT ANY WARRANTY; without even the implied warranty of " +"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. " +"See the GNU Library General Public License for more details.\n" +"\n" +"You should have received a copy of the GNU Library General Public " +"License along with this library; if not, write to the Free Software " +"Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 " +"USA.\n" +"\n" +"Written by Bill Spitzak spitzak@d2.com\n"; + +#include <FL/Fl.H> +#include <FL/Fl_Double_Window.H> +#include <FL/Fl_Box.H> +#include <FL/Fl_Button.H> +#include <FL/Fl_Hold_Browser.H> +#include <FL/Fl_Menu_Bar.H> +#include <FL/Fl_Input.H> +#include <FL/fl_ask.H> +#include <FL/fl_draw.H> +#include <FL/fl_file_chooser.H> +#include <FL/fl_message.H> +#include <FL/filename.H> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <errno.h> + +#if defined(WIN32) && !defined(CYGNUS) +# include <direct.h> +#else +# include <unistd.h> +#endif + +#include "about_panel.H" + +#include "Fl_Type.H" + +//////////////////////////////////////////////////////////////// + +void nyi(Fl_Widget *,void *) { + fl_message("That's not yet implemented, sorry"); +} + +static const char *filename; +void set_filename(const char *c); +int modflag; + +static char* pwd; +static char in_source_dir; +void goto_source_dir() { + if (in_source_dir) return; + if (!filename || !*filename) return; + const char *p = filename_name(filename); + if (p <= filename) return; // it is in the current directory + char buffer[1024]; + strcpy(buffer,filename); + int n = p-filename; if (n>1) n--; buffer[n] = 0; + if (!pwd) { + pwd = getcwd(0,1024); + if (!pwd) {fprintf(stderr,"getwd : %s\n",strerror(errno)); return;} + } + if (chdir(buffer)<0) {fprintf(stderr, "Can't chdir to %s : %s\n", + buffer, strerror(errno)); return;} + in_source_dir = 1; +} + +void leave_source_dir() { + if (!in_source_dir) return; + if (chdir(pwd)<0) {fprintf(stderr, "Can't chdir to %s : %s\n", + pwd, strerror(errno));} + in_source_dir = 0; +} + +Fl_Window *main_window; + +void exit_cb(Fl_Widget *,void *) { + if (!modflag || fl_ask("Exit without saving changes?")) exit(0); +} + +void save_cb(Fl_Widget *, void *v) { + const char *c = filename; + if (v || !c || !*c) { + if (!(c=fl_file_chooser("Save to:", "*.f[ld]", c))) return; + set_filename(c); + } + if (!write_file(c)) { + fl_show_message("Error writing", c, strerror(errno)); + return; + } + modflag = 0; +} + +void open_cb(Fl_Widget *, void *v) { + if (!v && modflag && !fl_ask("Discard changes?")) return; + const char *c; + if (!(c = fl_file_chooser("Open:", "*.f[ld]", filename))) return; + if (!read_file(c, v!=0)) { + fl_show_message("Can't read", c, strerror(errno)); + return; + } + if (!v) {set_filename(c); modflag = 0;} + else modflag = 1; +} + +void new_cb(Fl_Widget *, void *v) { + if (!v && modflag && !fl_ask("Discard changes?")) return; + const char *c; + if (!(c = fl_file_chooser("New:", "*.f[ld]", 0))) return; + delete_all(); + set_filename(c); + modflag = 0; +} + +static int compile_only; + +const char* header_file_name = ".H"; +const char* code_file_name = ".C"; + +void write_cb(Fl_Widget *, void *) { + if (!filename) { + save_cb(0,0); + if (!filename) return; + } + char cname[1024]; + char hname[1024]; + if (*code_file_name == '.') { + strcpy(cname,filename_name(filename)); + filename_setext(cname, code_file_name); + } else { + strcpy(cname, code_file_name); + } + if (*header_file_name == '.') { + strcpy(hname,filename_name(filename)); + filename_setext(hname, header_file_name); + } else { + strcpy(hname, header_file_name); + } + int x = write_code(cname,hname); + strcat(cname, "/"); strcat(cname,header_file_name); + if (compile_only) { + if (!x) {fprintf(stderr,"%s : %s\n",cname,strerror(errno)); exit(1);} + } else { + if (!x) { + fl_show_message("Can't write", cname, strerror(errno)); + } else { + fl_show_message("Wrote", cname, 0); + } + } +} + +void openwidget_cb(Fl_Widget *, void *) { + if (!Fl_Type::current) { + fl_message("Please select a widget"); + return; + } + Fl_Type::current->open(); +} + +void toggle_overlays(Fl_Widget *,void *); + +void select_all_cb(Fl_Widget *,void *); + +void group_cb(Fl_Widget *, void *); + +void ungroup_cb(Fl_Widget *, void *); + +extern int pasteoffset; +static int ipasteoffset; + +static char* cutfname() { +#ifdef WIN32 + return ".fluid_cut_buffer"; +#else + static char name[256] = "~/.fluid_cut_buffer"; + static char beenhere; + if (!beenhere) {beenhere = 1; filename_expand(name,name);} + return name; +#endif +} + +void copy_cb(Fl_Widget*, void*) { + if (!Fl_Type::current) return; + ipasteoffset = 10; + if (!write_file(cutfname(),1)) { + fl_show_message("Can't write", cutfname(), strerror(errno)); + return; + } +} + +extern void select_only(Fl_Type *); +void cut_cb(Fl_Widget *, void *) { + if (!Fl_Type::current) return; + ipasteoffset = 0; + Fl_Type *p = Fl_Type::current->parent; + while (p && p->selected) p = p->parent; + if (!write_file(cutfname(),1)) { + fl_show_message("Can't write", cutfname(), strerror(errno)); + return; + } + delete_all(1); + if (p) select_only(p); +} + +extern int force_parent, gridx, gridy; + +void paste_cb(Fl_Widget*, void*) { + if (ipasteoffset) force_parent = 1; + pasteoffset = ipasteoffset; + if (gridx>1) pasteoffset = ((pasteoffset-1)/gridx+1)*gridx; + if (gridy>1) pasteoffset = ((pasteoffset-1)/gridy+1)*gridy; + if (!read_file(cutfname(), 1)) { + fl_show_message("Can't read", cutfname(), strerror(errno)); + } + pasteoffset = 0; + ipasteoffset += 10; + force_parent = 0; +} + +void earlier_cb(Fl_Widget*,void*); + +void later_cb(Fl_Widget*,void*); + +Fl_Type *sort(Fl_Type *parent); + +static void sort_cb(Fl_Widget *,void *) { + sort((Fl_Type*)0); +} + +void show_alignment_cb(Fl_Widget *, void *); + +void about_cb(Fl_Widget *, void *) { + if (!about_panel) make_about_panel(copyright); + copyright_box->hide(); + display_group->show(); + about_panel->show(); +} + +//////////////////////////////////////////////////////////////// + +extern Fl_Menu_Item New_Menu[]; + +Fl_Menu_Item Main_Menu[] = { +{"File",0,0,0,FL_SUBMENU}, + {"New", FL_ALT+'N', new_cb, 0}, + {"Open...", FL_ALT+'O', open_cb, 0}, + {"Save", FL_ALT+'s', save_cb, 0}, + {"Save As...", FL_ALT+'S', save_cb, (void*)1}, + {"Merge...", FL_ALT+'i', open_cb, (void*)1, FL_MENU_DIVIDER}, + {"Write code", FL_ALT+'C', write_cb, 0}, + {"Quit", FL_ALT+'q', exit_cb}, + {0}, +{"Edit",0,0,0,FL_SUBMENU}, + {"Undo", FL_ALT+'z', nyi}, + {"Cut", FL_ALT+'x', cut_cb}, + {"Copy", FL_ALT+'c', copy_cb}, + {"Paste", FL_ALT+'v', paste_cb}, + {"Select All", FL_ALT+'a', select_all_cb, 0, FL_MENU_DIVIDER}, + {"Open...", FL_F+1, openwidget_cb}, + {"Sort",0,sort_cb}, + {"Earlier", FL_F+2, earlier_cb}, + {"Later", FL_F+3, later_cb}, +//{"Show", FL_F+5, show_cb}, +//{"Hide", FL_F+6, hide_cb}, + {"Group", FL_F+7, group_cb}, + {"Ungroup", FL_F+8, ungroup_cb,0, FL_MENU_DIVIDER}, +//{"Deactivate", 0, nyi}, +//{"Activate", 0, nyi, 0, FL_MENU_DIVIDER}, + {"Overlays on/off",FL_ALT+'o',toggle_overlays}, + {"Preferences",FL_ALT+'p',show_alignment_cb}, + {0}, +{"New", 0, 0, (void *)New_Menu, FL_SUBMENU_POINTER}, +{"Help",0,0,0,FL_SUBMENU}, + {"About fluid",0,about_cb}, + {"Manual",0,nyi}, + {0}, +{0}}; + +#define BROWSERWIDTH 300 +#define BROWSERHEIGHT 500 +#define WINWIDTH 300 +#define MENUHEIGHT 30 +#define WINHEIGHT (BROWSERHEIGHT+MENUHEIGHT) + +extern void fill_in_New_Menu(); + +void make_main_window() { + if (!main_window) { + Fl_Widget *o; + main_window = new Fl_Double_Window(WINWIDTH,WINHEIGHT,"fluid"); + main_window->box(FL_NO_BOX); + o = make_widget_browser(0,MENUHEIGHT,BROWSERWIDTH,BROWSERHEIGHT); + o->box(FL_FLAT_BOX); + main_window->resizable(o); + Fl_Menu_Bar *m = new Fl_Menu_Bar(0,0,BROWSERWIDTH,MENUHEIGHT); + m->menu(Main_Menu); + m->global(); + fill_in_New_Menu(); + main_window->end(); + } +} + +void set_filename(const char *c) { + if (filename) free((void *)filename); + filename = strdup(c); + if (main_window) main_window->label(filename); +} + +//////////////////////////////////////////////////////////////// + +static int arg(int argc, char** argv, int& i) { + if (argv[i][1] == 'c' && !argv[i][2]) {compile_only = 1; i++; return 1;} + if (argv[i][1] == 'o' && !argv[i][2] && i+1 < argc) { + code_file_name = argv[i+1]; i += 2; return 2;} + if (argv[i][1] == 'h' && !argv[i][2]) { + header_file_name = argv[i+1]; i += 2; return 2;} + return 0; +} + +#ifndef WIN32 + +#include <signal.h> +#ifdef _sigargs +#define SIGARG _sigargs +#else +#ifdef __sigargs +#define SIGARG __sigargs +#else +#define SIGARG int // you may need to fix this for older systems +#endif +#endif + +static void sigint(SIGARG) { + signal(SIGINT,sigint); + exit_cb(0,0); +} + +#endif + +int main(int argc,char **argv) { + int i = 1; + if (!Fl::args(argc,argv,i,arg) || i < argc-1) { + fprintf(stderr,"usage: %s <switches> name.fl\n" +" -c : write .C and .H and exit\n" +" -o <name> : .C output filename, or extension if <name> starts with '.'\n" +" -h <name> : .H output filename, or extension if <name> starts with '.'\n" +"%s\n", argv[0], Fl::help); + return 1; + } + const char *c = argv[i]; + make_main_window(); + if (c) set_filename(c); + if (!compile_only) { + Fl::visual((Fl_Mode)(FL_DOUBLE|FL_INDEX)); + main_window->callback(exit_cb); + main_window->show(argc,argv); + } + if (c && !read_file(c,0)) { + if (compile_only) { + fprintf(stderr,"%s : %s\n", c, strerror(errno)); + exit(1); + } + fl_show_message("Can't read", c, strerror(errno)); + } + if (compile_only) {write_cb(0,0); exit(0);} + modflag = 0; +#ifndef WIN32 + signal(SIGINT,sigint); +#endif + return Fl::run(); +} diff --git a/fluid/function_panel.cxx b/fluid/function_panel.cxx new file mode 100644 index 000000000..0b6bccd61 --- /dev/null +++ b/fluid/function_panel.cxx @@ -0,0 +1,262 @@ +// generated by Fast Light User Interface Designer (fluid) version 0.99 + +#include "function_panel.H" + +Fl_Window *function_panel; + +Fl_Light_Button *f_public_button; + +Fl_Input *f_name_input; + +Fl_Input *f_return_type_input; + +Fl_Return_Button *f_panel_ok; + +Fl_Button *f_panel_cancel; + +Fl_Window *code_panel; + +Fl_Input *code_input; + +Fl_Return_Button *code_panel_ok; + +Fl_Button *code_panel_cancel; + +Fl_Window *codeblock_panel; + +Fl_Input *code_before_input; + +Fl_Input *code_after_input; + +Fl_Return_Button *codeblock_panel_ok; + +Fl_Button *codeblock_panel_cancel; + +Fl_Window *declblock_panel; + +Fl_Input *decl_before_input; + +Fl_Input *decl_after_input; + +Fl_Return_Button *declblock_panel_ok; + +Fl_Button *declblock_panel_cancel; + +Fl_Window *decl_panel; + +Fl_Light_Button *decl_public_button; + +Fl_Input *decl_input; + +Fl_Return_Button *decl_panel_ok; + +Fl_Button *decl_panel_cancel; + +Fl_Window *class_panel; + +Fl_Light_Button *c_public_button; + +Fl_Input *c_name_input; + +Fl_Input *c_subclass_input; + +Fl_Return_Button *c_panel_ok; + +Fl_Button *c_panel_cancel; + +Fl_Window* make_function_panel() { + Fl_Window *w; + { Fl_Window* o = new Fl_Window(287, 173, "function/method"); + w = function_panel = o; + w->set_modal(); + { Fl_Light_Button* o = new Fl_Light_Button(10, 15, 65, 25, "public"); + f_public_button = o; + o->labelsize(10); + o->when(0); + } + { Fl_Input* o = new Fl_Input(10, 60, 270, 25, "name(args): (blank for main())"); + f_name_input = o; + o->labelsize(12); + o->align(5); + o->when(0); + Fl_Group::current()->resizable(o); + } + { Fl_Input* o = new Fl_Input(10, 105, 270, 25, "return type: (blank to return outermost widget)"); + f_return_type_input = o; + o->labelsize(12); + o->align(5); + o->when(0); + } + { Fl_Return_Button* o = new Fl_Return_Button(110, 140, 80, 25, "OK"); + f_panel_ok = o; + w->hotspot(o); + } + { Fl_Button* o = new Fl_Button(200, 140, 80, 25, "cancel"); + f_panel_cancel = o; + o->shortcut(0xff1b); + } + w->end(); + } + return w; +} + +Fl_Window* make_code_panel() { + Fl_Window *w; + { Fl_Window* o = new Fl_Window(291, 178, "code"); + w = code_panel = o; + w->set_modal(); + { Fl_Input* o = new Fl_Input(6, 5, 280, 135); + code_input = o; + o->type(4); + o->labelsize(12); + o->align(0); + o->when(0); + Fl_Group::current()->resizable(o); + } + { Fl_Return_Button* o = new Fl_Return_Button(115, 145, 80, 25, "OK"); + code_panel_ok = o; + w->hotspot(o); + } + { Fl_Button* o = new Fl_Button(205, 145, 80, 25, "cancel"); + code_panel_cancel = o; + o->shortcut(0xff1b); + } + w->end(); + } + return w; +} + +Fl_Window* make_codeblock_panel() { + Fl_Window *w; + { Fl_Window* o = new Fl_Window(293, 134, "codeblock"); + w = codeblock_panel = o; + w->set_modal(); + { Fl_Input* o = new Fl_Input(10, 5, 275, 25); + code_before_input = o; + o->labelsize(12); + o->align(5); + o->when(0); + Fl_Group::current()->resizable(o); + } + { Fl_Box* o = new Fl_Box(10, 35, 270, 25, "\"{...child code...}\" is inserted here"); + o->align(20); + } + { Fl_Input* o = new Fl_Input(10, 65, 275, 25); + code_after_input = o; + o->labelsize(12); + o->align(5); + o->when(0); + } + { Fl_Return_Button* o = new Fl_Return_Button(115, 100, 80, 25, "OK"); + codeblock_panel_ok = o; + w->hotspot(o); + } + { Fl_Button* o = new Fl_Button(205, 100, 80, 25, "cancel"); + codeblock_panel_cancel = o; + o->shortcut(0xff1b); + } + w->end(); + } + return w; +} + +Fl_Window* make_declblock_panel() { + Fl_Window *w; + { Fl_Window* o = new Fl_Window(293, 134, "declaration block"); + w = declblock_panel = o; + w->set_modal(); + { Fl_Input* o = new Fl_Input(15, 10, 275, 25); + decl_before_input = o; + o->labelsize(12); + o->align(5); + o->when(0); + Fl_Group::current()->resizable(o); + } + { Fl_Box* o = new Fl_Box(15, 40, 270, 25, "\"\\n...child code...\\n\" is inserted here"); + o->align(20); + } + { Fl_Input* o = new Fl_Input(15, 70, 275, 25); + decl_after_input = o; + o->labelsize(12); + o->align(5); + o->when(0); + } + { Fl_Return_Button* o = new Fl_Return_Button(120, 105, 80, 25, "OK"); + declblock_panel_ok = o; + w->hotspot(o); + } + { Fl_Button* o = new Fl_Button(210, 105, 80, 25, "cancel"); + declblock_panel_cancel = o; + o->shortcut(0xff1b); + } + w->end(); + } + return w; +} + +Fl_Window* make_decl_panel() { + Fl_Window *w; + { Fl_Window* o = new Fl_Window(290, 176, "declaration"); + w = decl_panel = o; + { Fl_Light_Button* o = new Fl_Light_Button(10, 15, 65, 25, "public"); + decl_public_button = o; + o->labelsize(10); + o->when(0); + } + { Fl_Input* o = new Fl_Input(10, 50, 270, 25, "can be any declartion, like \"int x;\",\nan external symbol like \"extern \ +int foo();\",\na #directive like \"#include <foo.h>\",\nor a comment like \"\ +//foo\" or \"/*foo*/\""); + decl_input = o; + o->labelsize(12); + o->align(6); + o->when(0); + Fl_Group::current()->resizable(o); + } + { Fl_Return_Button* o = new Fl_Return_Button(115, 145, 80, 25, "OK"); + decl_panel_ok = o; + w->hotspot(o); + } + { Fl_Button* o = new Fl_Button(205, 145, 80, 25, "cancel"); + decl_panel_cancel = o; + o->shortcut(0xff1b); + } + w->end(); + } + return w; +} + +Fl_Window* make_class_panel() { + Fl_Window *w; + { Fl_Window* o = new Fl_Window(287, 173, "class"); + w = class_panel = o; + w->set_modal(); + { Fl_Light_Button* o = new Fl_Light_Button(10, 10, 65, 25, "public"); + c_public_button = o; + o->labelsize(10); + o->when(0); + } + { Fl_Input* o = new Fl_Input(10, 55, 270, 25, "name:"); + c_name_input = o; + o->labelsize(12); + o->align(5); + o->when(0); + Fl_Group::current()->resizable(o); + } + { Fl_Input* o = new Fl_Input(10, 100, 270, 25, "subclass of (text between : and {)"); + c_subclass_input = o; + o->labelsize(12); + o->align(5); + o->when(0); + } + { Fl_Return_Button* o = new Fl_Return_Button(110, 135, 80, 25, "OK"); + c_panel_ok = o; + w->hotspot(o); + } + { Fl_Button* o = new Fl_Button(200, 135, 80, 25, "cancel"); + c_panel_cancel = o; + o->shortcut(0xff1b); + } + w->end(); + } + return w; +} diff --git a/fluid/function_panel.fl b/fluid/function_panel.fl new file mode 100644 index 000000000..e4ad307f1 --- /dev/null +++ b/fluid/function_panel.fl @@ -0,0 +1,164 @@ +# data file for the Fltk User Interface Designer (fluid) +version 0.99 +gridx 10 +gridy 5 +snap 3 +Function {make_function_panel()} {open +} { + Fl_Window function_panel { + label {function/method} open + xywh {281 608 287 173} modal visible + } { + Fl_Light_Button f_public_button { + label public + xywh {10 15 65 25} labelsize 10 when 0 + } + Fl_Input f_name_input { + label {name(args): (blank for main())} + xywh {10 60 270 25} labelsize 12 align 5 when 0 resizable + } + Fl_Input f_return_type_input { + label {return type: (blank to return outermost widget)} + xywh {10 105 270 25} labelsize 12 align 5 when 0 + } + Fl_Return_Button f_panel_ok { + label OK + xywh {110 140 80 25} hotspot + } + Fl_Button f_panel_cancel { + label cancel + xywh {200 140 80 25} shortcut 0xff1b + } + } +} + +Function {make_code_panel()} {open +} { + Fl_Window code_panel { + label code open + xywh {256 219 291 178} modal visible + } { + Fl_Input code_input { + xywh {6 5 280 135} type Multiline labelsize 12 align 0 when 0 resizable + } + Fl_Return_Button code_panel_ok { + label OK + xywh {115 145 80 25} hotspot + } + Fl_Button code_panel_cancel { + label cancel + xywh {205 145 80 25} shortcut 0xff1b + } + } +} + +Function {make_codeblock_panel()} {open +} { + Fl_Window codeblock_panel { + label codeblock open + xywh {285 439 293 134} modal visible + } { + Fl_Input code_before_input { + xywh {10 5 275 25} labelsize 12 align 5 when 0 resizable + } + Fl_Box {} { + label {"{...child code...}" is inserted here} + xywh {10 35 270 25} align 20 + } + Fl_Input code_after_input { + xywh {10 65 275 25} labelsize 12 align 5 when 0 + } + Fl_Return_Button codeblock_panel_ok { + label OK + xywh {115 100 80 25} hotspot + } + Fl_Button codeblock_panel_cancel { + label cancel + xywh {205 100 80 25} shortcut 0xff1b + } + } +} + +Function {make_declblock_panel()} {open +} { + Fl_Window declblock_panel { + label {declaration block} open + xywh {296 118 293 134} modal visible + } { + Fl_Input decl_before_input { + xywh {15 10 275 25} labelsize 12 align 5 when 0 resizable + } + Fl_Box {} { + label {"\\n...child code...\\n" is inserted here} + xywh {15 40 270 25} align 20 + } + Fl_Input decl_after_input { + xywh {15 70 275 25} labelsize 12 align 5 when 0 + } + Fl_Return_Button declblock_panel_ok { + label OK + xywh {120 105 80 25} hotspot + } + Fl_Button declblock_panel_cancel { + label cancel + xywh {210 105 80 25} shortcut 0xff1b + } + } +} + +Function {make_decl_panel()} {open +} { + Fl_Window decl_panel { + label declaration open + xywh {278 800 290 176} visible + } { + Fl_Light_Button decl_public_button { + label public + xywh {10 15 65 25} labelsize 10 when 0 + } + Fl_Input decl_input { + label {can be any declartion, like "int x;", +an external symbol like "extern int foo();", +a \#directive like "\#include <foo.h>", +or a comment like "//foo" or "/*foo*/"} + xywh {10 50 270 25} labelsize 12 align 6 when 0 resizable + } + Fl_Return_Button decl_panel_ok { + label OK + xywh {115 145 80 25} hotspot + } + Fl_Button decl_panel_cancel { + label cancel + xywh {205 145 80 25} shortcut 0xff1b + } + } +} + +Function {make_class_panel()} {open +} { + Fl_Window class_panel { + label class open selected + xywh {291 618 287 173} modal visible + } { + Fl_Light_Button c_public_button { + label public + xywh {10 10 65 25} labelsize 10 when 0 + } + Fl_Input c_name_input { + label {name:} + xywh {10 55 270 25} labelsize 12 align 5 when 0 resizable + } + Fl_Input c_subclass_input { + label {subclass of (text between : and \{)} + xywh {10 100 270 25} labelsize 12 align 5 when 0 + } + Fl_Return_Button c_panel_ok { + label OK + xywh {110 135 80 25} hotspot + } + Fl_Button c_panel_cancel { + label cancel + xywh {200 135 80 25} shortcut 0xff1b + } + } +} diff --git a/fluid/function_panel.h b/fluid/function_panel.h new file mode 100644 index 000000000..f0a9d2506 --- /dev/null +++ b/fluid/function_panel.h @@ -0,0 +1,46 @@ +// generated by Fast Light User Interface Designer (fluid) version 0.99 + +#include <FL/Fl.H> +#include <FL/Fl_Box.H> +#include <FL/Fl_Button.H> +#include <FL/Fl_Input.H> +#include <FL/Fl_Light_Button.H> +#include <FL/Fl_Return_Button.H> +#include <FL/Fl_Window.H> +extern Fl_Window *function_panel; +extern Fl_Light_Button *f_public_button; +extern Fl_Input *f_name_input; +extern Fl_Input *f_return_type_input; +extern Fl_Return_Button *f_panel_ok; +extern Fl_Button *f_panel_cancel; +extern Fl_Window *code_panel; +extern Fl_Input *code_input; +extern Fl_Return_Button *code_panel_ok; +extern Fl_Button *code_panel_cancel; +extern Fl_Window *codeblock_panel; +extern Fl_Input *code_before_input; +extern Fl_Input *code_after_input; +extern Fl_Return_Button *codeblock_panel_ok; +extern Fl_Button *codeblock_panel_cancel; +extern Fl_Window *declblock_panel; +extern Fl_Input *decl_before_input; +extern Fl_Input *decl_after_input; +extern Fl_Return_Button *declblock_panel_ok; +extern Fl_Button *declblock_panel_cancel; +extern Fl_Window *decl_panel; +extern Fl_Light_Button *decl_public_button; +extern Fl_Input *decl_input; +extern Fl_Return_Button *decl_panel_ok; +extern Fl_Button *decl_panel_cancel; +extern Fl_Window *class_panel; +extern Fl_Light_Button *c_public_button; +extern Fl_Input *c_name_input; +extern Fl_Input *c_subclass_input; +extern Fl_Return_Button *c_panel_ok; +extern Fl_Button *c_panel_cancel; +Fl_Window* make_function_panel(); +Fl_Window* make_code_panel(); +Fl_Window* make_codeblock_panel(); +Fl_Window* make_declblock_panel(); +Fl_Window* make_decl_panel(); +Fl_Window* make_class_panel(); diff --git a/fluid/gif.cxx b/fluid/gif.cxx new file mode 100644 index 000000000..1af6556a7 --- /dev/null +++ b/fluid/gif.cxx @@ -0,0 +1,336 @@ +// gif.C + +// Read a .gif file and convert it to a "xpm" format (actually my +// modified one with compressed colormaps). + +// Extensively modified from original code for gif2ras by +// Patrick J. Naughton of Sun Microsystems. The original +// copyright notice follows: + +/* gif2ras.c - Converts from a Compuserve GIF (tm) image to a Sun Raster image. + * + * Copyright (c) 1988 by Patrick J. Naughton + * + * Author: Patrick J. Naughton + * naughton@wind.sun.com + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * Comments and additions should be sent to the author: + * + * Patrick J. Naughton + * Sun Microsystems, Inc. + * 2550 Garcia Ave, MS 14-40 + * Mountain View, CA 94043 + * (415) 336-1080 + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +typedef unsigned char uchar; + +#define NEXTBYTE getc(GifFile) +#define GETSHORT(var) var = NEXTBYTE; var += NEXTBYTE << 8 + +int gif2xpm( + const char *infname,// filename for error messages + FILE *GifFile, // file to read + char*** datap, // return xpm data here + int** lengthp, // return line lengths here + int inumber // which image in movie (0 = first) +) { + + {char b[6]; + if (fread(b,1,6,GifFile)<6) return 0; /* quit on eof */ + if (b[0]!='G' || b[1]!='I' || b[2] != 'F') { + fprintf(stderr,"%s is not a GIF file.\n", infname); return 0;} + if (b[3]!='8' || b[4]>'9' || b[5]!= 'a') + fprintf(stderr,"%s is version %c%c%c.\n",infname,b[3],b[4],b[5]); + } + + int Width; GETSHORT(Width); + int Height; GETSHORT(Height); + + uchar ch = NEXTBYTE; + char HasColormap = ((ch & 0x80) != 0); + int BitsPerPixel = (ch & 7) + 1; + int ColorMapSize = 1 << BitsPerPixel; + // int OriginalResolution = ((ch>>4)&7)+1; + // int SortedTable = (ch&8)!=0; + NEXTBYTE; // Background Color index + NEXTBYTE; // Aspect ratio is N/64 + + // Read in global colormap: + uchar transparent_pixel = 0; + char has_transparent = 0; + uchar Red[256], Green[256], Blue[256]; /* color map */ + if (HasColormap) { + for (int i=0; i < ColorMapSize; i++) { + Red[i] = NEXTBYTE; + Green[i] = NEXTBYTE; + Blue[i] = NEXTBYTE; + } + } else { + fprintf(stderr,"%s does not have a colormap.\n", infname); + for (int i = 0; i < ColorMapSize; i++) + Red[i] = Green[i] = Blue[i] = (i*256+ColorMapSize-1)/ColorMapSize; + } + + int CodeSize; /* Code size, init from GIF header, increases... */ + char Interlace; + + for (;;) { + + int i = NEXTBYTE; + if (i<0) {fprintf(stderr,"%s: unexpected EOF\n",infname); return 0;} + int blocklen; + + // if (i == 0x3B) return 0; eof code + + if (i == 0x21) { // a "gif extension" + + ch = NEXTBYTE; + blocklen = NEXTBYTE; + + if (ch==0xF9 && blocklen==4) { // Netscape animation extension + + char bits; + bits = NEXTBYTE; + NEXTBYTE; NEXTBYTE; // GETSHORT(delay); + transparent_pixel = NEXTBYTE; + if (bits & 1) has_transparent = 1; + blocklen = NEXTBYTE; + + } else if (ch == 0xFF) { // Netscape repeat count + ; + + } else if (ch == 0xFE) { //Gif Comment +#if 0 + if(blocklen>0) { + char *comment=new char[blocklen+1]; + int l; + for(l=0;blocklen;l++,blocklen--) + comment[l]=NEXTBYTE; + comment[l]=0; + fprintf(stderr,"%s: Gif Comment: '%s'\n", infname, comment); + delete comment; + NEXTBYTE; //End marker + } +#endif + } else { + fprintf(stderr,"%s: unknown gif extension 0x%02x\n", infname, ch); + + } + + } else if (i == 0x2c) { // an image + + NEXTBYTE; NEXTBYTE; // GETSHORT(x_position); + NEXTBYTE; NEXTBYTE; // GETSHORT(y_position); + GETSHORT(Width); + GETSHORT(Height); + ch = NEXTBYTE; + Interlace = ((ch & 0x40) != 0); + if (ch&0x80) { + // read local color map + int n = 1<<((ch&7)+1); // does this replace ColorMapSize ?? + for (i=0; i < n; i++) { + Red[i] = NEXTBYTE; + Green[i] = NEXTBYTE; + Blue[i] = NEXTBYTE; + } + } + CodeSize = NEXTBYTE+1; + + if (!inumber--) break; // okay, this is the image we want + blocklen = NEXTBYTE; + + } else { + fprintf(stderr,"%s: unknown gif code 0x%02x\n", infname, i); + blocklen = 0; + } + + // skip the data: + while (blocklen>0) {while (blocklen--) {NEXTBYTE;} blocklen=NEXTBYTE;} + } + + uchar *Image = new uchar[Width*Height]; + if (!Image) { + fprintf (stderr, "Insufficient memory\n"); + exit (2); + } + int YC = 0, Pass = 0; /* Used to de-interlace the picture */ + uchar *p = Image; + uchar *eol = p+Width; + + int InitCodeSize = CodeSize; + int ClearCode = (1 << (CodeSize-1)); + int EOFCode = ClearCode + 1; + int FirstFree = ClearCode + 2; + int FinChar = 0; + int ReadMask = (1<<CodeSize) - 1; + int FreeCode = FirstFree; + int OldCode = ClearCode; + + // tables used by LZW decompresser: + short int Prefix[4096]; + uchar Suffix[4096]; + + int blocklen = NEXTBYTE; + uchar thisbyte = NEXTBYTE; blocklen--; + int frombit = 0; + + for (;;) { + +/* Fetch the next code from the raster data stream. The codes can be + * any length from 3 to 12 bits, packed into 8-bit bytes, so we have to + * maintain our location as a pointer and a bit offset. + * In addition, gif adds totally useless and annoying block counts + * that must be correctly skipped over. */ + int CurCode = thisbyte; + if (frombit+CodeSize > 7) { + if (blocklen <= 0) { + blocklen = NEXTBYTE; + if (blocklen <= 0) break; + } + thisbyte = NEXTBYTE; blocklen--; + CurCode |= thisbyte<<8; + } + if (frombit+CodeSize > 15) { + if (blocklen <= 0) { + blocklen = NEXTBYTE; + if (blocklen <= 0) break; + } + thisbyte = NEXTBYTE; blocklen--; + CurCode |= thisbyte<<16; + } + CurCode = (CurCode>>frombit)&ReadMask; + frombit = (frombit+CodeSize)%8; + + if (CurCode == ClearCode) { + CodeSize = InitCodeSize; + ReadMask = (1<<CodeSize) - 1; + FreeCode = FirstFree; + OldCode = ClearCode; + continue; + } + + if (CurCode == EOFCode) break; + + uchar OutCode[1025]; // temporary array for reversing codes + uchar *tp = OutCode; + int i; + if (CurCode < FreeCode) i = CurCode; + else if (CurCode == FreeCode) {*tp++ = FinChar; i = OldCode;} + else {fprintf(stderr,"%s : LZW Barf!\n",infname); break;} + + while (i >= ColorMapSize) {*tp++ = Suffix[i]; i = Prefix[i];} + *tp++ = FinChar = i; + while (tp > OutCode) { + *p++ = *--tp; + if (p >= eol) { + if (!Interlace) YC++; + else switch (Pass) { + case 0: YC += 8; if (YC >= Height) {Pass++; YC = 4;} break; + case 1: YC += 8; if (YC >= Height) {Pass++; YC = 2;} break; + case 2: YC += 4; if (YC >= Height) {Pass++; YC = 1;} break; + case 3: YC += 2; break; + } + if (YC>=Height) YC=0; /* cheap bug fix when excess data */ + p = Image + YC*Width; + eol = p+Width; + } + } + + if (OldCode != ClearCode) { + Prefix[FreeCode] = OldCode; + Suffix[FreeCode] = FinChar; + FreeCode++; + if (FreeCode > ReadMask) { + if (CodeSize < 12) { + CodeSize++; + ReadMask = (1 << CodeSize) - 1; + } + else FreeCode--; + } + } + OldCode = CurCode; + } + + // We are done reading the file, now convert to xpm: + + // allocate line pointer arrays: + char** data = new char*[Height+3]; + *datap = data; + int* length = new int[Height+2]; + *lengthp = length; + + // transparent pixel must be zero, swap if it isn't: + if (has_transparent && transparent_pixel != 0) { + // swap transparent pixel with zero + p = Image+Width*Height; + while (p-- > Image) { + if (*p==transparent_pixel) *p = 0; + else if (!*p) *p = transparent_pixel; + } + uchar t; + t = Red[0]; Red[0] = Red[transparent_pixel]; Red[transparent_pixel] = t; + t =Green[0];Green[0]=Green[transparent_pixel];Green[transparent_pixel]=t; + t =Blue[0];Blue[0] =Blue[transparent_pixel];Blue[transparent_pixel] = t; + } + + // find out what colors are actually used: + uchar used[256]; uchar remap[256]; + int i; + for (i = 0; i < ColorMapSize; i++) used[i] = 0; + p = Image+Width*Height; + while (p-- > Image) used[*p] = 1; + + // remap them to start with printing characters: + int base = has_transparent && used[0] ? ' ' : ' '+1; + int numcolors = 0; + for (i = 0; i < ColorMapSize; i++) if (used[i]) { + remap[i] = base++; + numcolors++; + } + + // write the first line of xpm data (use suffix as temp array): + length[0] = sprintf((char*)(Suffix), + "%d %d %d %d",Width,Height,-numcolors,1); + data[0] = new char[length[0]+1]; + strcpy(data[0], (char*)Suffix); + + // write the colormap + length[1] = 4*numcolors; + data[1] = (char*)(p = new uchar[4*numcolors]); + for (i = 0; i < ColorMapSize; i++) if (used[i]) { + *p++ = remap[i]; + *p++ = Red[i]; + *p++ = Green[i]; + *p++ = Blue[i]; + } + + // remap the image data: + p = Image+Width*Height; + while (p-- > Image) *p = remap[*p]; + + // split the image data into lines: + for (i=0; i<Height; i++) { + data[i+2] = (char*)(Image + i*Width); + length[i+2] = Width; + } + + data[Height+2] = 0; // null to end string array + return 1; +} diff --git a/fluid/keyboard_ui.cxx b/fluid/keyboard_ui.cxx new file mode 100644 index 000000000..7c7b65ae6 --- /dev/null +++ b/fluid/keyboard_ui.cxx @@ -0,0 +1,536 @@ +// generated by Fast Light User Interface Designer (fluid) version 0.99 +#include "keyboard_ui.H" + +Fl_Window *make_window() { + Fl_Window *w; + {Fl_Window* o = new Fl_Window(494, 193); + w = o; + } + {Fl_Button* o = new Fl_Button(15, 50, 20, 20, "Esc"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb, (void*)(FL_Escape)); + } + {Fl_Button* o = new Fl_Button(50, 50, 20, 20, "F1"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb, (void*)(FL_F+1)); + } + {Fl_Button* o = new Fl_Button(70, 50, 20, 20, "F2"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb, (void*)(FL_F+2)); + } + {Fl_Button* o = new Fl_Button(90, 50, 20, 20, "F3"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb, (void*)(FL_F+3)); + } + {Fl_Button* o = new Fl_Button(110, 50, 20, 20, "F4"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb, (void*)(FL_F+4)); + } + {Fl_Button* o = new Fl_Button(140, 50, 20, 20, "F5"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb, (void*)(FL_F+5)); + } + {Fl_Button* o = new Fl_Button(160, 50, 20, 20, "F6"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb, (void*)(FL_F+6)); + } + {Fl_Button* o = new Fl_Button(180, 50, 20, 20, "F7"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb, (void*)(FL_F+7)); + } + {Fl_Button* o = new Fl_Button(200, 50, 20, 20, "F8"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb, (void*)(FL_F+8)); + } + {Fl_Button* o = new Fl_Button(230, 50, 20, 20, "F9"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb, (void*)(FL_F+9)); + } + {Fl_Button* o = new Fl_Button(250, 50, 20, 20, "F10"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb, (void*)(FL_F+10)); + } + {Fl_Button* o = new Fl_Button(270, 50, 20, 20, "F11"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb, (void*)(FL_F+11)); + } + {Fl_Button* o = new Fl_Button(290, 50, 20, 20, "F12"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb, (void*)(FL_F+12)); + } + {Fl_Button* o = new Fl_Button(325, 50, 20, 20, "Print"); + o->labelsize(8); + o->callback((Fl_Callback*)key_cb, (void*)(FL_Print)); + } + {Fl_Button* o = new Fl_Button(345, 50, 20, 20, "Sclk"); + o->labelsize(8); + o->callback((Fl_Callback*)key_cb, (void*)(FL_Scroll_Lock)); + } + {Fl_Button* o = new Fl_Button(365, 50, 20, 20, "Paus"); + o->labelsize(8); + o->callback((Fl_Callback*)key_cb, (void*)(FL_Pause)); + } + {Fl_Button* o = new Fl_Button(15, 80, 20, 20, "`"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb); + } + {Fl_Button* o = new Fl_Button(35, 80, 20, 20, "1"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb); + } + {Fl_Button* o = new Fl_Button(55, 80, 20, 20, "2"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb); + } + {Fl_Button* o = new Fl_Button(75, 80, 20, 20, "3"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb); + } + {Fl_Button* o = new Fl_Button(95, 80, 20, 20, "4"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb); + } + {Fl_Button* o = new Fl_Button(115, 80, 20, 20, "5"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb); + } + {Fl_Button* o = new Fl_Button(135, 80, 20, 20, "6"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb); + } + {Fl_Button* o = new Fl_Button(155, 80, 20, 20, "7"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb); + } + {Fl_Button* o = new Fl_Button(175, 80, 20, 20, "8"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb); + } + {Fl_Button* o = new Fl_Button(195, 80, 20, 20, "9"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb); + } + {Fl_Button* o = new Fl_Button(215, 80, 20, 20, "0"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb); + } + {Fl_Button* o = new Fl_Button(235, 80, 20, 20, "-"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb); + } + {Fl_Button* o = new Fl_Button(255, 80, 20, 20, "="); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb); + } + {Fl_Button* o = new Fl_Button(275, 80, 35, 20, "Bksp"); + o->labeltype(FL_SYMBOL_LABEL); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb, (void*)(FL_BackSpace)); + } + {Fl_Button* o = new Fl_Button(325, 80, 20, 20, "Ins"); + o->labelsize(8); + o->callback((Fl_Callback*)key_cb, (void*)(FL_Insert)); + } + {Fl_Button* o = new Fl_Button(345, 80, 20, 20, "Home"); + o->labelsize(8); + o->callback((Fl_Callback*)key_cb, (void*)(FL_Home)); + } + {Fl_Button* o = new Fl_Button(365, 80, 20, 20, "pgup"); + o->labelsize(8); + o->callback((Fl_Callback*)key_cb, (void*)(FL_Page_Up)); + } + {Fl_Button* o = new Fl_Button(400, 80, 20, 20, "Num"); + o->labelsize(8); + o->callback((Fl_Callback*)key_cb, (void*)(FL_Num_Lock)); + } + {Fl_Button* o = new Fl_Button(420, 80, 20, 20, "/"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'/')); + } + {Fl_Button* o = new Fl_Button(440, 80, 20, 20, "*"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'*')); + } + {Fl_Button* o = new Fl_Button(460, 80, 20, 20, "-"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'-')); + } + {Fl_Button* o = new Fl_Button(15, 100, 27, 20, "Tab"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb, (void*)(FL_Tab)); + } + {Fl_Button* o = new Fl_Button(42, 100, 20, 20, "Q"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb); + } + {Fl_Button* o = new Fl_Button(62, 100, 20, 20, "W"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb); + } + {Fl_Button* o = new Fl_Button(82, 100, 20, 20, "E"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb); + } + {Fl_Button* o = new Fl_Button(102, 100, 20, 20, "R"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb); + } + {Fl_Button* o = new Fl_Button(122, 100, 20, 20, "T"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb); + } + {Fl_Button* o = new Fl_Button(142, 100, 20, 20, "Y"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb); + } + {Fl_Button* o = new Fl_Button(162, 100, 20, 20, "U"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb); + } + {Fl_Button* o = new Fl_Button(182, 100, 20, 20, "I"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb); + } + {Fl_Button* o = new Fl_Button(202, 100, 20, 20, "O"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb); + } + {Fl_Button* o = new Fl_Button(222, 100, 20, 20, "P"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb); + } + {Fl_Button* o = new Fl_Button(242, 100, 20, 20, "["); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb); + } + {Fl_Button* o = new Fl_Button(262, 100, 20, 20, "]"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb); + } + {Fl_Button* o = new Fl_Button(282, 100, 28, 20, "\\"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb, (void*)('|')); + o->align(20); + } + {Fl_Button* o = new Fl_Button(325, 100, 20, 20, "Del"); + o->labelsize(8); + o->callback((Fl_Callback*)key_cb, (void*)(FL_Delete)); + } + {Fl_Button* o = new Fl_Button(345, 100, 20, 20, "End"); + o->labelsize(8); + o->callback((Fl_Callback*)key_cb, (void*)(FL_End)); + } + {Fl_Button* o = new Fl_Button(365, 100, 20, 20, "pgdn"); + o->labelsize(8); + o->callback((Fl_Callback*)key_cb, (void*)(FL_Page_Down)); + } + {Fl_Button* o = new Fl_Button(400, 100, 20, 20, "7"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'7')); + } + {Fl_Button* o = new Fl_Button(420, 100, 20, 20, "8"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'8')); + } + {Fl_Button* o = new Fl_Button(440, 100, 20, 20, "9"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'9')); + } + {Fl_Button* o = new Fl_Button(460, 100, 20, 40, "+"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'+')); + o->align(17); + } + {Fl_Button* o = new Fl_Button(15, 120, 36, 20, "Lock"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb, (void*)(FL_Caps_Lock)); + } + {Fl_Button* o = new Fl_Button(51, 120, 20, 20, "A"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb); + } + {Fl_Button* o = new Fl_Button(71, 120, 20, 20, "S"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb); + } + {Fl_Button* o = new Fl_Button(91, 120, 20, 20, "D"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb); + } + {Fl_Button* o = new Fl_Button(111, 120, 20, 20, "F"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb); + } + {Fl_Button* o = new Fl_Button(131, 120, 20, 20, "G"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb); + } + {Fl_Button* o = new Fl_Button(151, 120, 20, 20, "H"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb); + } + {Fl_Button* o = new Fl_Button(171, 120, 20, 20, "J"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb); + } + {Fl_Button* o = new Fl_Button(191, 120, 20, 20, "K"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb); + } + {Fl_Button* o = new Fl_Button(211, 120, 20, 20, "L"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb); + } + {Fl_Button* o = new Fl_Button(231, 120, 20, 20, ";"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb); + } + {Fl_Button* o = new Fl_Button(251, 120, 20, 20, "\'"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb); + } + {Fl_Button* o = new Fl_Button(271, 120, 39, 20, "Enter"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb, (void*)(FL_Enter)); + } + {Fl_Button* o = new Fl_Button(400, 120, 20, 20, "4"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'4')); + } + {Fl_Button* o = new Fl_Button(420, 120, 20, 20, "5"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'5')); + } + {Fl_Button* o = new Fl_Button(440, 120, 20, 20, "6"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'6')); + } + {Fl_Button* o = new Fl_Button(15, 140, 45, 20, "Shift"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb, (void*)(FL_Shift_L)); + } + {Fl_Button* o = new Fl_Button(60, 140, 20, 20, "Z"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb); + } + {Fl_Button* o = new Fl_Button(80, 140, 20, 20, "X"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb); + } + {Fl_Button* o = new Fl_Button(100, 140, 20, 20, "C"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb); + } + {Fl_Button* o = new Fl_Button(120, 140, 20, 20, "V"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb); + } + {Fl_Button* o = new Fl_Button(140, 140, 20, 20, "B"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb); + } + {Fl_Button* o = new Fl_Button(160, 140, 20, 20, "N"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb); + } + {Fl_Button* o = new Fl_Button(180, 140, 20, 20, "M"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb); + } + {Fl_Button* o = new Fl_Button(200, 140, 20, 20, ","); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb); + } + {Fl_Button* o = new Fl_Button(220, 140, 20, 20, "."); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb); + } + {Fl_Button* o = new Fl_Button(240, 140, 20, 20, "/"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb); + } + {Fl_Button* o = new Fl_Button(260, 140, 50, 20, "Shift"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb, (void*)(FL_Shift_R)); + } + {Fl_Button* o = new Fl_Button(345, 140, 20, 20, "@8->"); + o->labeltype(FL_SYMBOL_LABEL); + o->labelsize(10); + o->labelcolor(47); + o->callback((Fl_Callback*)key_cb, (void*)(FL_Up)); + } + {Fl_Button* o = new Fl_Button(400, 140, 20, 20, "1"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'1')); + } + {Fl_Button* o = new Fl_Button(420, 140, 20, 20, "2"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'2')); + } + {Fl_Button* o = new Fl_Button(440, 140, 20, 20, "3"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'3')); + } + {Fl_Button* o = new Fl_Button(460, 140, 20, 40); + o->callback((Fl_Callback*)key_cb, (void*)(FL_KP_Enter)); + } + {Fl_Button* o = new Fl_Button(15, 160, 30, 20, "Ctrl"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb, (void*)(FL_Control_L)); + } + {Fl_Button* o = new Fl_Button(45, 160, 30, 20, "Meta"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb, (void*)(FL_Meta_L)); + } + {Fl_Button* o = new Fl_Button(75, 160, 30, 20, "Alt"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb, (void*)(FL_Alt_L)); + } + {Fl_Button* o = new Fl_Button(105, 160, 85, 20); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb, (void*)(' ')); + } + {Fl_Button* o = new Fl_Button(190, 160, 30, 20, "Alt"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb, (void*)(FL_Alt_R)); + } + {Fl_Button* o = new Fl_Button(220, 160, 30, 20, "Meta"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb, (void*)(FL_Meta_R)); + } + {Fl_Button* o = new Fl_Button(250, 160, 30, 20, "Menu"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb, (void*)(FL_Menu)); + } + {Fl_Button* o = new Fl_Button(280, 160, 30, 20, "Ctrl"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb, (void*)(FL_Control_R)); + } + {Fl_Button* o = new Fl_Button(325, 160, 20, 20, "@4->"); + o->labeltype(FL_SYMBOL_LABEL); + o->labelsize(10); + o->labelcolor(47); + o->callback((Fl_Callback*)key_cb, (void*)(FL_Left)); + } + {Fl_Button* o = new Fl_Button(345, 160, 20, 20, "@2->"); + o->labeltype(FL_SYMBOL_LABEL); + o->labelsize(10); + o->labelcolor(47); + o->callback((Fl_Callback*)key_cb, (void*)(FL_Down)); + } + {Fl_Button* o = new Fl_Button(365, 160, 20, 20, "@6->"); + o->labeltype(FL_SYMBOL_LABEL); + o->labelsize(10); + o->labelcolor(47); + o->callback((Fl_Callback*)key_cb, (void*)(FL_Right)); + } + {Fl_Button* o = new Fl_Button(400, 160, 40, 20, "0"); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'0')); + o->align(20); + } + {Fl_Button* o = new Fl_Button(440, 160, 20, 20, "."); + o->labelsize(10); + o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'.')); + } + {Fl_Input* o = new Fl_Input(15, 10, 370, 30); + } + {Fl_Button* o = new Fl_Button(400, 5, 20, 10, "shift"); + o->box(FL_THIN_UP_BOX); + o->color2(3); + o->labelsize(8); + o->callback((Fl_Callback*)shift_cb, (void*)(FL_SHIFT)); + } + {Fl_Button* o = new Fl_Button(420, 5, 20, 10, "lock"); + o->box(FL_THIN_UP_BOX); + o->color2(3); + o->labelsize(8); + o->callback((Fl_Callback*)shift_cb, (void*)(FL_CAPS_LOCK)); + } + {Fl_Button* o = new Fl_Button(440, 5, 20, 10, "ctrl"); + o->box(FL_THIN_UP_BOX); + o->color2(3); + o->labelsize(8); + o->callback((Fl_Callback*)shift_cb, (void*)(FL_CTRL)); + } + {Fl_Button* o = new Fl_Button(460, 5, 20, 10, "alt"); + o->box(FL_THIN_UP_BOX); + o->color2(3); + o->labelsize(8); + o->callback((Fl_Callback*)shift_cb, (void*)(FL_ALT)); + } + {Fl_Button* o = new Fl_Button(440, 15, 20, 10, "meta"); + o->box(FL_THIN_UP_BOX); + o->color2(3); + o->labelsize(8); + o->callback((Fl_Callback*)shift_cb, (void*)(FL_META)); + } + {Fl_Button* o = new Fl_Button(420, 15, 20, 10, "?"); + o->box(FL_THIN_UP_BOX); + o->color2(3); + o->labelsize(8); + o->callback((Fl_Callback*)shift_cb, (void*)(0x20)); + } + {Fl_Button* o = new Fl_Button(400, 15, 20, 10, "num"); + o->box(FL_THIN_UP_BOX); + o->color2(3); + o->labelsize(8); + o->callback((Fl_Callback*)shift_cb, (void*)(FL_NUM_LOCK)); + } + {Fl_Button* o = new Fl_Button(400, 25, 20, 10, "b1"); + o->box(FL_THIN_UP_BOX); + o->color2(3); + o->labelsize(8); + o->callback((Fl_Callback*)shift_cb, (void*)(FL_BUTTON1)); + } + {Fl_Button* o = new Fl_Button(420, 25, 20, 10, "b2"); + o->box(FL_THIN_UP_BOX); + o->color2(3); + o->labelsize(8); + o->callback((Fl_Callback*)shift_cb, (void*)(FL_BUTTON2)); + } + {Fl_Button* o = new Fl_Button(440, 25, 20, 10, "b3"); + o->box(FL_THIN_UP_BOX); + o->color2(3); + o->labelsize(8); + o->callback((Fl_Callback*)shift_cb, (void*)(FL_BUTTON3)); + } + {Fl_Button* o = new Fl_Button(460, 15, 20, 10, "sclk"); + o->box(FL_THIN_UP_BOX); + o->color2(3); + o->labelsize(8); + o->callback((Fl_Callback*)shift_cb, (void*)(FL_SCROLL_LOCK)); + } + {Fl_Button* o = new Fl_Button(460, 25, 20, 10, "?"); + o->box(FL_THIN_UP_BOX); + o->color2(3); + o->labelsize(8); + o->callback((Fl_Callback*)shift_cb, (void*)(0x800)); + } + {Fl_Button* o = new Fl_Button(400, 35, 20, 10, "?"); + o->box(FL_THIN_UP_BOX); + o->color2(3); + o->labelsize(8); + o->callback((Fl_Callback*)shift_cb, (void*)(0x1000)); + } + {Fl_Button* o = new Fl_Button(420, 35, 20, 10, "?"); + o->box(FL_THIN_UP_BOX); + o->color2(3); + o->labelsize(8); + o->callback((Fl_Callback*)shift_cb, (void*)(0x2000)); + } + {Fl_Button* o = new Fl_Button(440, 35, 20, 10, "?"); + o->box(FL_THIN_UP_BOX); + o->color2(3); + o->labelsize(8); + o->callback((Fl_Callback*)shift_cb, (void*)(0x4000)); + } + {Fl_Button* o = new Fl_Button(460, 35, 20, 10, "?"); + o->box(FL_THIN_UP_BOX); + o->color2(3); + o->labelsize(8); + o->callback((Fl_Callback*)shift_cb, (void*)(0x8000)); + } + w->end(); + return w; +} diff --git a/fluid/keyboard_ui.h b/fluid/keyboard_ui.h new file mode 100644 index 000000000..ec1ba7722 --- /dev/null +++ b/fluid/keyboard_ui.h @@ -0,0 +1,8 @@ +// generated by Fast Light User Interface Designer (fluid) version 0.99 +#include <FL/Fl.H> +#include <FL/Fl_Button.H> +#include <FL/Fl_Input.H> +#include <FL/Fl_Window.H> +extern void key_cb(Fl_Button*, void*); +extern void shift_cb(Fl_Button*, void*); +Fl_Window *make_window(); diff --git a/fluid/penne.C b/fluid/penne.C new file mode 100644 index 000000000..cc1db0937 --- /dev/null +++ b/fluid/penne.C @@ -0,0 +1,85 @@ +// generated by Fast Light User Interface Designer (fluid) version 0.99 + +#include "penne.H" + +inline void UserInterface::cb_New_i(Fl_Button*, void*) { + new UserInterface; +} +void UserInterface::cb_New(Fl_Button* o, void* v) { + ((UserInterface*)(o->parent()->user_data()))->cb_New_i(o,v); +} + +inline void UserInterface::cb_Delete_i(Fl_Button*, void*) { + delete this; +} +void UserInterface::cb_Delete(Fl_Button* o, void* v) { + ((UserInterface*)(o->parent()->user_data()))->cb_Delete_i(o,v); +} + +inline void UserInterface::cb_button1_i(Fl_Light_Button* o, void*) { + Button->value(o->value()); +} +void UserInterface::cb_button1(Fl_Light_Button* o, void* v) { + ((UserInterface*)(o->parent()->user_data()))->cb_button1_i(o,v); +} + +inline void UserInterface::cb_When_i(Fl_Menu_* o, void*) { + Button->value(o->value()); +} +void UserInterface::cb_When(Fl_Menu_* o, void* v) { + ((UserInterface*)(o->parent()->user_data()))->cb_When_i(o,v); +} + +Fl_Menu_Item UserInterface::menu_[] = { + {"coucou", 0, 0, 0, 64, 0, 3, 14, 0}, + {"When you press this, it should crash !", 0, (Fl_Callback*)UserInterface::cb_When, 0, 2, 0, 3, 14, 0}, + {0}, + {0} +}; + +UserInterface::UserInterface() { + Fl_Window *w; + { Fl_Window* o = new Fl_Window(375, 199); + w = Win = o; + o->user_data((void*)(this)); + { Fl_Button* o = new Fl_Button(35, 145, 120, 35, "New window"); + o->callback((Fl_Callback*)cb_New); + } + { Fl_Button* o = new Fl_Button(215, 145, 120, 35, "Delete window"); + o->callback((Fl_Callback*)cb_Delete); + } + { Fl_Light_Button* o = new Fl_Light_Button(45, 25, 95, 25, "button1"); + o->callback((Fl_Callback*)cb_button1); + } + { Fl_Check_Button* o = new Fl_Check_Button(220, 25, 95, 25, "button2"); + Button = o; + o->down_box(FL_DIAMOND_DOWN_BOX); + } + { Fl_Tile* o = new Fl_Tile(110, 55, 165, 80); + { Fl_Box* o = new Fl_Box(110, 55, 165, 50, "label"); + o->box(FL_DOWN_BOX); + } + { Fl_Box* o = new Fl_Box(110, 105, 80, 30, "label"); + o->box(FL_DOWN_BOX); + } + { Fl_Box* o = new Fl_Box(190, 105, 85, 30, "label"); + o->box(FL_DOWN_BOX); + } + o->end(); + } + { Fl_Menu_Bar* o = new Fl_Menu_Bar(0, 0, 375, 25); + o->menu(menu_); + } + w->end(); + } + Win->show(); +} + +UserInterface::~UserInterface() { + delete Win; +} + +int main() { + new UserInterface; +return Fl::run(); +} diff --git a/fluid/penne.H b/fluid/penne.H new file mode 100644 index 000000000..ebabab473 --- /dev/null +++ b/fluid/penne.H @@ -0,0 +1,32 @@ +// generated by Fast Light User Interface Designer (fluid) version 0.99 + +#include <FL/Fl.H> +#include <FL/Fl_Box.H> +#include <FL/Fl_Button.H> +#include <FL/Fl_Check_Button.H> +#include <FL/Fl_Light_Button.H> +#include <FL/Fl_Menu_Bar.H> +#include <FL/Fl_Tile.H> +#include <FL/Fl_Window.H> + +class UserInterface { +public: + UserInterface(); + Fl_Window *Win; +private: + inline void cb_New_i(Fl_Button*, void*); + static void cb_New(Fl_Button*, void*); + inline void cb_Delete_i(Fl_Button*, void*); + static void cb_Delete(Fl_Button*, void*); + inline void cb_button1_i(Fl_Light_Button*, void*); + static void cb_button1(Fl_Light_Button*, void*); +public: + Fl_Check_Button *Button; + static Fl_Menu_Item menu_[]; +private: + inline void cb_When_i(Fl_Menu_*, void*); + static void cb_When(Fl_Menu_*, void*); +public: + ~UserInterface(); +}; +int main(); diff --git a/fluid/primes.fl b/fluid/primes.fl new file mode 100644 index 000000000..e221b739a --- /dev/null +++ b/fluid/primes.fl @@ -0,0 +1,22 @@ +# data file for the Fltk User Interface Designer (fluid) +version 0.99 +gridx 10 +gridy 10 +snap 3 +decl {// This is a demo of fluid used to write a normal C program} {} + +decl {\#include <stdio.h>} {} + +Function {main()} {open selected +} { + code {printf("%d ", 2);} {} + codeblock {for (int x=3; x < 10000; x += 2)} {open + } { + code {for (int y=3; x%y; y += 2)} {} + codeblock {if (y*y > x)} {open + } { + code {printf("%d ", x); +break;} {} + } + } +} diff --git a/fluid/widget_panel.cxx b/fluid/widget_panel.cxx new file mode 100644 index 000000000..23ee01e19 --- /dev/null +++ b/fluid/widget_panel.cxx @@ -0,0 +1,316 @@ +// generated by Fast Light User Interface Designer (fluid) version 0.99 + +#include "widget_panel.H" + +Fl_Input *v_input[4]; + +Fl_Window* make_widget_panel() { + Fl_Window *w; + { Fl_Window* o = w = new Fl_Window(370, 480); + w->hotspot(o); + { Fl_Input* o = new Fl_Input(90, 10, 210, 20, "name:"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)name_cb); + o->when(0); + } + { Fl_Light_Button* o = new Fl_Light_Button(300, 10, 60, 20, "public"); + o->box(FL_THIN_UP_BOX); + o->selection_color(1); + o->labelsize(10); + o->callback((Fl_Callback*)name_public_cb); + o->when(1); + } + { Fl_Input* o = new Fl_Input(90, 35, 170, 20, "class:"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)subclass_cb, (void*)(4)); + o->when(0); + } + { Fl_Choice* o = new Fl_Choice(260, 35, 100, 20); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)subtype_cb); + } + { Fl_Input* o = new Fl_Input(90, 60, 270, 20, "label:"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)label_cb); + o->when(1); + } + { Fl_Choice* o = new Fl_Choice(90, 80, 150, 20, "labeltype:"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)labeltype_cb); + o->menu(labeltypemenu); + } + { Fl_Button* o = new Fl_Button(240, 80, 20, 20, "@-1<-"); + o->type(1); + o->box(FL_THIN_UP_BOX); + o->labeltype(FL_SYMBOL_LABEL); + o->labelcolor(8); + o->callback((Fl_Callback*)align_cb, (void*)(FL_ALIGN_LEFT)); + } + { Fl_Button* o = new Fl_Button(260, 80, 20, 20, "@-1->"); + o->type(1); + o->box(FL_THIN_UP_BOX); + o->labeltype(FL_SYMBOL_LABEL); + o->labelcolor(8); + o->callback((Fl_Callback*)align_cb, (void*)(FL_ALIGN_RIGHT)); + } + { Fl_Button* o = new Fl_Button(280, 80, 20, 20, "@-18"); + o->type(1); + o->box(FL_THIN_UP_BOX); + o->labeltype(FL_SYMBOL_LABEL); + o->labelcolor(8); + o->callback((Fl_Callback*)align_cb, (void*)(FL_ALIGN_TOP)); + } + { Fl_Button* o = new Fl_Button(300, 80, 20, 20, "@-12"); + o->type(1); + o->box(FL_THIN_UP_BOX); + o->labeltype(FL_SYMBOL_LABEL); + o->labelcolor(8); + o->callback((Fl_Callback*)align_cb, (void*)(FL_ALIGN_BOTTOM)); + } + { Fl_Button* o = new Fl_Button(320, 80, 20, 20, "@-3square"); + o->type(1); + o->box(FL_THIN_UP_BOX); + o->labeltype(FL_SYMBOL_LABEL); + o->labelcolor(8); + o->callback((Fl_Callback*)align_cb, (void*)(FL_ALIGN_INSIDE)); + } + { Fl_Button* o = new Fl_Button(340, 80, 20, 10, "wrap"); + o->type(1); + o->box(FL_THIN_UP_BOX); + o->labelsize(8); + o->callback((Fl_Callback*)align_cb, (void*)(FL_ALIGN_WRAP)); + } + { Fl_Button* o = new Fl_Button(340, 90, 20, 10, "clip"); + o->type(1); + o->box(FL_THIN_UP_BOX); + o->labelsize(8); + o->callback((Fl_Callback*)align_cb, (void*)(FL_ALIGN_CLIP)); + } + { Fl_Choice* o = new Fl_Choice(90, 100, 170, 20, "labelfont:"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)labelfont_cb); + o->menu(fontmenu); + } + { Fl_Value_Input* o = new Fl_Value_Input(260, 100, 50, 20); + o->box(FL_THIN_UP_BOX); + o->maximum(100); + o->step(1); + o->value(14); + o->callback((Fl_Callback*)labelsize_cb); + } + { Fl_Button* o = new Fl_Button(310, 100, 50, 20, "labelcolor"); + o->box(FL_THIN_UP_BOX); + o->labelsize(8); + o->callback((Fl_Callback*)labelcolor_cb); + } + { Fl_Choice* o = new Fl_Choice(90, 125, 220, 20, "box:"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)box_cb); + o->menu(boxmenu); + } + { Fl_Button* o = new Fl_Button(310, 125, 50, 20, "color"); + o->box(FL_THIN_UP_BOX); + o->labelsize(8); + o->callback((Fl_Callback*)color_cb); + } + { Fl_Choice* o = new Fl_Choice(90, 145, 220, 20, "down_box:"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)down_box_cb); + o->menu(boxmenu); + } + { Fl_Button* o = new Fl_Button(310, 145, 50, 20, "select color"); + o->box(FL_THIN_UP_BOX); + o->labelsize(8); + o->callback((Fl_Callback*)color2_cb); + } + { Fl_Choice* o = new Fl_Choice(90, 170, 170, 20, "textfont:"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)textfont_cb); + o->hide(); + o->menu(fontmenu); + } + { Fl_Input* o = new Fl_Input(90, 170, 170, 20, "xclass:"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)xclass_cb); + o->when(0); + } + { Shortcut_Button* o = new Shortcut_Button(90, 170, 270, 20, "shortcut:"); + o->box(FL_THIN_UP_BOX); + o->color(7); + o->selection_color(7); + o->callback((Fl_Callback*)shortcut_in_cb); + o->align(4); + } + { Fl_Value_Input* o = new Fl_Value_Input(260, 170, 50, 20); + o->box(FL_THIN_UP_BOX); + o->maximum(100); + o->step(1); + o->value(14); + o->callback((Fl_Callback*)textsize_cb); + o->hide(); + } + { Fl_Button* o = new Fl_Button(310, 170, 50, 20, "textcolor"); + o->box(FL_THIN_UP_BOX); + o->labelsize(8); + o->callback((Fl_Callback*)textcolor_cb); + o->hide(); + } + { Fl_Value_Input* o = new Fl_Value_Input(20, 205, 60, 20, "size:"); + o->box(FL_THIN_UP_BOX); + o->labelsize(10); + o->step(0.010101); + o->callback((Fl_Callback*)slider_size_cb); + o->align(5); + } + { Fl_Value_Input* o = new Fl_Value_Input(90, 205, 60, 20, "minimum:"); + o->box(FL_THIN_UP_BOX); + o->labelsize(10); + o->callback((Fl_Callback*)min_cb); + o->align(5); + } + { Fl_Value_Input* o = new Fl_Value_Input(160, 205, 60, 20, "maximum:"); + o->box(FL_THIN_UP_BOX); + o->labelsize(10); + o->value(1); + o->callback((Fl_Callback*)max_cb); + o->align(5); + } + { Fl_Value_Input* o = new Fl_Value_Input(230, 205, 60, 20, "step:"); + o->box(FL_THIN_UP_BOX); + o->labelsize(10); + o->callback((Fl_Callback*)step_cb); + o->align(5); + } + { Fl_Value_Input* o = new Fl_Value_Input(300, 205, 60, 20, "value:"); + o->box(FL_THIN_UP_BOX); + o->labelsize(10); + o->callback((Fl_Callback*)value_cb); + o->align(5); + } + { Fl_Group* o = new Fl_Group(20, 230, 340, 20); + o->callback((Fl_Callback*)propagate_load); + o->align(5); + { Fl_Light_Button* o = new Fl_Light_Button(20, 230, 70, 20, "non_modal"); + o->box(FL_THIN_UP_BOX); + o->selection_color(1); + o->labelsize(9); + o->callback((Fl_Callback*)non_modal_cb); + o->align(148); + } + { Fl_Light_Button* o = new Fl_Light_Button(90, 230, 60, 20, "visible"); + o->box(FL_THIN_UP_BOX); + o->selection_color(1); + o->labelsize(10); + o->callback((Fl_Callback*)visible_cb); + } + { Fl_Light_Button* o = new Fl_Light_Button(90, 230, 60, 20, "modal"); + o->box(FL_THIN_UP_BOX); + o->selection_color(1); + o->labelsize(10); + o->callback((Fl_Callback*)modal_cb); + } + { Fl_Light_Button* o = new Fl_Light_Button(160, 230, 60, 20, "active"); + o->box(FL_THIN_UP_BOX); + o->selection_color(1); + o->labelsize(10); + o->callback((Fl_Callback*)active_cb); + } + { Fl_Light_Button* o = new Fl_Light_Button(160, 230, 60, 20, "border"); + o->box(FL_THIN_UP_BOX); + o->selection_color(1); + o->labelsize(10); + o->callback((Fl_Callback*)border_cb); + } + { Fl_Light_Button* o = new Fl_Light_Button(230, 230, 60, 20, "resizable"); + o->box(FL_THIN_UP_BOX); + o->selection_color(1); + o->labelsize(10); + o->callback((Fl_Callback*)resizable_cb); + o->when(1); + } + { Fl_Light_Button* o = new Fl_Light_Button(300, 230, 60, 20, "hotspot"); + o->box(FL_THIN_UP_BOX); + o->selection_color(1); + o->labelsize(10); + o->callback((Fl_Callback*)hotspot_cb); + o->when(1); + } + o->end(); + } + { Fl_Input* o = v_input[0] = new Fl_Input(90, 260, 270, 20, "extra code:"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)v_input_cb, (void*)(0)); + o->when(0); + } + { Fl_Input* o = v_input[1] = new Fl_Input(90, 280, 270, 20); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)v_input_cb, (void*)(1)); + o->when(0); + } + { Fl_Input* o = v_input[2] = new Fl_Input(90, 300, 270, 20); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)v_input_cb, (void*)(2)); + o->when(0); + } + { Fl_Input* o = v_input[3] = new Fl_Input(90, 320, 270, 20); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)v_input_cb, (void*)(3)); + o->when(0); + } + { Fl_Box* o = new Fl_Box(0, 350, 90, 20, "callback:"); + o->align(24); + } + { Fl_Input* o = new Fl_Input(90, 350, 270, 50); + o->type(4); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)callback_cb); + o->when(0); + } + { Fl_Box* o = new Fl_Box(90, 370, 100, 30, "label"); + o->hide(); + o->deactivate(); + Fl_Group::current()->resizable(o); + } + { Fl_Input* o = new Fl_Input(90, 400, 170, 20, "user_data:"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)user_data_cb); + o->when(0); + } + { Fl_Input* o = new Fl_Input(300, 400, 60, 20, "type:"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)user_data_type_cb); + o->when(0); + } + { Fl_Choice* o = new Fl_Choice(90, 420, 100, 20, "when:"); + o->box(FL_THIN_UP_BOX); + o->callback((Fl_Callback*)when_cb); + o->when(0); + o->menu(whenmenu); + } + { Fl_Light_Button* o = new Fl_Light_Button(190, 420, 70, 20, "no change"); + o->box(FL_THIN_UP_BOX); + o->selection_color(1); + o->labelsize(10); + o->callback((Fl_Callback*)when_button_cb); + o->when(0); + } + { Fl_Group* o = new Fl_Group(10, 450, 350, 20); + { Fl_Button* o = new Fl_Button(10, 450, 80, 20, "no &overlay"); + o->labelcolor(1); + o->callback((Fl_Callback*)overlay_cb); + } + { Fl_Button* o = new Fl_Button(100, 450, 80, 20, "Revert"); + o->callback((Fl_Callback*)revert_cb); + } + { Fl_Button* o = new Fl_Button(190, 450, 80, 20, "Cancel"); + o->callback((Fl_Callback*)cancel_cb); + } + { Fl_Return_Button* o = new Fl_Return_Button(280, 450, 80, 20, "OK"); + o->callback((Fl_Callback*)ok_cb); + } + o->end(); + } + o->end(); + } + return w; +} diff --git a/fluid/widget_panel.fl b/fluid/widget_panel.fl new file mode 100644 index 000000000..0fb973c51 --- /dev/null +++ b/fluid/widget_panel.fl @@ -0,0 +1,300 @@ +# data file for the Fltk User Interface Designer (fluid) +version 0.99 +header_name {.H} +code_name {.C} +gridx 10 +gridy 5 +snap 3 +Function {make_widget_panel()} {open +} { + Fl_Window {} {open + xywh {189 164 370 480} hotspot visible + } { + Fl_Input {} { + label {name:} + callback name_cb + xywh {90 10 210 20} box THIN_UP_BOX when 0 + } + Fl_Light_Button {} { + label public + callback name_public_cb + xywh {300 10 60 20} box THIN_UP_BOX color {49 1} labelsize 10 when 1 + } + Fl_Input {} { + label {class:} + user_data 4 + callback subclass_cb + xywh {90 35 170 20} box THIN_UP_BOX when 0 + } + Fl_Choice {} { + callback subtype_cb + xywh {260 35 100 20} box THIN_UP_BOX + } {} + Fl_Input {} { + label {label:} + callback label_cb + xywh {90 60 270 20} box THIN_UP_BOX when 1 + } + Fl_Choice {} { + label {labeltype:} + callback labeltype_cb + xywh {90 80 150 20} box THIN_UP_BOX + code0 {extern Fl_Menu_Item labeltypemenu[];} + code1 {o->menu(labeltypemenu);} + } {} + Fl_Button {} { + label {@-1<-} + user_data FL_ALIGN_LEFT + callback align_cb + xywh {240 80 20 20} type Toggle box THIN_UP_BOX labeltype SYMBOL_LABEL labelcolor 8 + } + Fl_Button {} { + label {@-1->} + user_data FL_ALIGN_RIGHT + callback align_cb + xywh {260 80 20 20} type Toggle box THIN_UP_BOX labeltype SYMBOL_LABEL labelcolor 8 + } + Fl_Button {} { + label {@-18} + user_data FL_ALIGN_TOP + callback align_cb + xywh {280 80 20 20} type Toggle box THIN_UP_BOX labeltype SYMBOL_LABEL labelcolor 8 + } + Fl_Button {} { + label {@-12} + user_data FL_ALIGN_BOTTOM + callback align_cb + xywh {300 80 20 20} type Toggle box THIN_UP_BOX labeltype SYMBOL_LABEL labelcolor 8 + } + Fl_Button {} { + label {@-3square} + user_data FL_ALIGN_INSIDE + callback align_cb + xywh {320 80 20 20} type Toggle box THIN_UP_BOX labeltype SYMBOL_LABEL labelcolor 8 + } + Fl_Button {} { + label wrap + user_data FL_ALIGN_WRAP + callback align_cb + xywh {340 80 20 10} type Toggle box THIN_UP_BOX labelsize 8 + } + Fl_Button {} { + label clip + user_data FL_ALIGN_CLIP + callback align_cb + xywh {340 90 20 10} type Toggle box THIN_UP_BOX labelsize 8 + } + Fl_Choice {} { + label {labelfont:} + callback labelfont_cb + xywh {90 100 170 20} box THIN_UP_BOX + code0 {extern Fl_Menu_Item fontmenu[];} + code1 {o->menu(fontmenu);} + } {} + Fl_Value_Input {} { + callback labelsize_cb + xywh {260 100 50 20} box THIN_UP_BOX maximum 100 step 1 value 14 + } + Fl_Button {} { + label labelcolor + callback labelcolor_cb + xywh {310 100 50 20} box THIN_UP_BOX labelsize 8 + } + Fl_Choice {} { + label {box:} + callback box_cb + xywh {90 125 220 20} box THIN_UP_BOX + code0 {extern Fl_Menu_Item boxmenu[];} + code1 {o->menu(boxmenu);} + } {} + Fl_Button {} { + label color + callback color_cb + xywh {310 125 50 20} box THIN_UP_BOX labelsize 8 + } + Fl_Choice {} { + label {down_box:} + callback down_box_cb + xywh {90 145 220 20} box THIN_UP_BOX + code0 {extern Fl_Menu_Item boxmenu[];} + code1 {o->menu(boxmenu);} + } {} + Fl_Button {} { + label {select color} + callback color2_cb + xywh {310 145 50 20} box THIN_UP_BOX labelsize 8 + } + Fl_Choice {} { + label {textfont:} + callback textfont_cb selected + xywh {90 170 170 20} box THIN_UP_BOX hide + code0 {extern Fl_Menu_Item fontmenu[];} + code1 {o->menu(fontmenu);} + } {} + Fl_Input {} { + label {xclass:} + callback xclass_cb + xywh {90 170 170 20} box THIN_UP_BOX when 0 + } + Fl_Button {} { + label {shortcut:} + callback shortcut_in_cb + xywh {90 170 270 20} box THIN_UP_BOX color {7 7} align 4 + code0 {\#include "Shortcut_Button.H"} + class Shortcut_Button + } + Fl_Value_Input {} { + callback textsize_cb + xywh {260 170 50 20} box THIN_UP_BOX maximum 100 step 1 value 14 hide + } + Fl_Button {} { + label textcolor + callback textcolor_cb + xywh {310 170 50 20} box THIN_UP_BOX labelsize 8 hide + } + Fl_Value_Input {} { + label {size:} + callback slider_size_cb + xywh {20 205 60 20} box THIN_UP_BOX labelsize 10 align 5 step 0.010101 + } + Fl_Value_Input {} { + label {minimum:} + callback min_cb + xywh {90 205 60 20} box THIN_UP_BOX labelsize 10 align 5 + } + Fl_Value_Input {} { + label {maximum:} + callback max_cb + xywh {160 205 60 20} box THIN_UP_BOX labelsize 10 align 5 value 1 + } + Fl_Value_Input {} { + label {step:} + callback step_cb + xywh {230 205 60 20} box THIN_UP_BOX labelsize 10 align 5 + } + Fl_Value_Input {} { + label {value:} + callback value_cb + xywh {300 205 60 20} box THIN_UP_BOX labelsize 10 align 5 + } + Fl_Group {} { + callback propagate_load open + xywh {20 230 340 20} align 5 + } { + Fl_Light_Button {} { + label non_modal + callback non_modal_cb + xywh {20 230 70 20} box THIN_UP_BOX color {49 1} labelsize 9 align 148 + } + Fl_Light_Button {} { + label visible + callback visible_cb + xywh {90 230 60 20} box THIN_UP_BOX color {49 1} labelsize 10 + } + Fl_Light_Button {} { + label modal + callback modal_cb + xywh {90 230 60 20} box THIN_UP_BOX color {49 1} labelsize 10 + } + Fl_Light_Button {} { + label active + callback active_cb + xywh {160 230 60 20} box THIN_UP_BOX color {49 1} labelsize 10 + } + Fl_Light_Button {} { + label border + callback border_cb + xywh {160 230 60 20} box THIN_UP_BOX color {49 1} labelsize 10 + } + Fl_Light_Button {} { + label resizable + callback resizable_cb + xywh {230 230 60 20} box THIN_UP_BOX color {49 1} labelsize 10 when 1 + } + Fl_Light_Button {} { + label hotspot + callback hotspot_cb + xywh {300 230 60 20} box THIN_UP_BOX color {49 1} labelsize 10 when 1 + } + } + Fl_Input {v_input[0]} { + label {extra code:} + user_data 0 + callback v_input_cb + xywh {90 260 270 20} box THIN_UP_BOX when 0 + } + Fl_Input {v_input[1]} { + user_data 1 + callback v_input_cb + xywh {90 280 270 20} box THIN_UP_BOX when 0 + } + Fl_Input {v_input[2]} { + user_data 2 + callback v_input_cb + xywh {90 300 270 20} box THIN_UP_BOX when 0 + } + Fl_Input {v_input[3]} { + user_data 3 + callback v_input_cb + xywh {90 320 270 20} box THIN_UP_BOX when 0 + } + Fl_Box {} { + label {callback:} + xywh {0 350 90 20} align 24 + } + Fl_Input {} { + callback callback_cb + xywh {90 350 270 50} type Multiline box THIN_UP_BOX when 0 + } + Fl_Box {} { + label label + xywh {90 370 100 30} hide deactivate resizable + } + Fl_Input {} { + label {user_data:} + callback user_data_cb + xywh {90 400 170 20} box THIN_UP_BOX when 0 + } + Fl_Input {} { + label {type:} + callback user_data_type_cb + xywh {300 400 60 20} box THIN_UP_BOX when 0 + } + Fl_Choice {} { + label {when:} + callback when_cb + xywh {90 420 100 20} box THIN_UP_BOX when 0 + code0 {extern Fl_Menu_Item whenmenu[];} + code1 {o->menu(whenmenu);} + } {} + Fl_Light_Button {} { + label {no change} + callback when_button_cb + xywh {190 420 70 20} box THIN_UP_BOX color {49 1} labelsize 10 when 0 + } + Fl_Group {} {open + xywh {10 450 350 20} + } { + Fl_Button {} { + label {no &overlay} + callback overlay_cb + xywh {10 450 80 20} labelcolor 1 + } + Fl_Button {} { + label Revert + callback revert_cb + xywh {100 450 80 20} + } + Fl_Button {} { + label Cancel + callback cancel_cb + xywh {190 450 80 20} + } + Fl_Return_Button {} { + label OK + callback ok_cb + xywh {280 450 80 20} + } + } + } +} diff --git a/fluid/widget_panel.h b/fluid/widget_panel.h new file mode 100644 index 000000000..9e304d16a --- /dev/null +++ b/fluid/widget_panel.h @@ -0,0 +1,61 @@ +// generated by Fast Light User Interface Designer (fluid) version 0.99 + +#include "Shortcut_Button.H" +#include <FL/Fl.H> +#include <FL/Fl_Box.H> +#include <FL/Fl_Button.H> +#include <FL/Fl_Choice.H> +#include <FL/Fl_Group.H> +#include <FL/Fl_Input.H> +#include <FL/Fl_Light_Button.H> +#include <FL/Fl_Return_Button.H> +#include <FL/Fl_Value_Input.H> +#include <FL/Fl_Window.H> +extern Fl_Menu_Item boxmenu[]; +extern Fl_Menu_Item fontmenu[]; +extern Fl_Menu_Item labeltypemenu[]; +extern Fl_Menu_Item whenmenu[]; +extern void active_cb(Fl_Light_Button*, void*); +extern void align_cb(Fl_Button*, void*); +extern void border_cb(Fl_Light_Button*, void*); +extern void box_cb(Fl_Choice*, void*); +extern void callback_cb(Fl_Input*, void*); +extern void cancel_cb(Fl_Button*, void*); +extern void color2_cb(Fl_Button*, void*); +extern void color_cb(Fl_Button*, void*); +extern void down_box_cb(Fl_Choice*, void*); +extern void hotspot_cb(Fl_Light_Button*, void*); +extern void label_cb(Fl_Input*, void*); +extern void labelcolor_cb(Fl_Button*, void*); +extern void labelfont_cb(Fl_Choice*, void*); +extern void labelsize_cb(Fl_Value_Input*, void*); +extern void labeltype_cb(Fl_Choice*, void*); +extern void max_cb(Fl_Value_Input*, void*); +extern void min_cb(Fl_Value_Input*, void*); +extern void modal_cb(Fl_Light_Button*, void*); +extern void name_cb(Fl_Input*, void*); +extern void name_public_cb(Fl_Light_Button*, void*); +extern void non_modal_cb(Fl_Light_Button*, void*); +extern void ok_cb(Fl_Return_Button*, void*); +extern void overlay_cb(Fl_Button*, void*); +extern void propagate_load(Fl_Group*, void*); +extern void resizable_cb(Fl_Light_Button*, void*); +extern void revert_cb(Fl_Button*, void*); +extern void shortcut_in_cb(Shortcut_Button*, void*); +extern void slider_size_cb(Fl_Value_Input*, void*); +extern void step_cb(Fl_Value_Input*, void*); +extern void subclass_cb(Fl_Input*, void*); +extern void subtype_cb(Fl_Choice*, void*); +extern void textcolor_cb(Fl_Button*, void*); +extern void textfont_cb(Fl_Choice*, void*); +extern void textsize_cb(Fl_Value_Input*, void*); +extern void user_data_cb(Fl_Input*, void*); +extern void user_data_type_cb(Fl_Input*, void*); +extern void v_input_cb(Fl_Input*, void*); +extern void value_cb(Fl_Value_Input*, void*); +extern void visible_cb(Fl_Light_Button*, void*); +extern void when_button_cb(Fl_Light_Button*, void*); +extern void when_cb(Fl_Choice*, void*); +extern void xclass_cb(Fl_Input*, void*); +extern Fl_Input *v_input[4]; +Fl_Window* make_widget_panel(); |
