From 160832ce04f932fbb3df199aa01d1c93148bb292 Mon Sep 17 00:00:00 2001 From: Matthias Melcher Date: Sat, 11 Dec 2021 19:43:00 +0100 Subject: [PATCH] STR 3442: copy/paste now inserts widget as expected. Fluid would add pasted widgets as the last child of the current group, even if they were cut at the beginning of the group. This patch adds a 'startegy' to adding widgets to allow merging closer to the 'current' widget. Also added d'n'd for the widget bin and some other UI improvements. STR 3442: some preparation, variable renaming STR 3442: unifying functions to add widgets. Adding widgets interactively is merged into one function, making undo/redo work as expected and removing unexpected differences between adding by menu or bin. STR 3442: adding drag'n'drop for windows from bin. Just drag the window symbol out of the tree and drop it anywhere on the desktop. Visual representation of dragged Window. STR 3442: insert individual nodes after 'current' STR 3442: adding new widget at expected positions. The widget bin can finally do drag'n'drop. Widgets appear in the tree close to the last selection. Duplicating now ads right below. Cut and paste inserts after last selection. Fluid: replaced #define with strict enum type. --- fluid/CMakeLists.txt | 1 + fluid/Fl_Function_Type.cxx | 52 ++-- fluid/Fl_Function_Type.h | 16 +- fluid/Fl_Group_Type.cxx | 13 +- fluid/Fl_Group_Type.h | 2 +- fluid/Fl_Menu_Type.cxx | 78 ++--- fluid/Fl_Menu_Type.h | 8 +- fluid/Fl_Type.cxx | 110 ++++++- fluid/Fl_Type.h | 22 +- fluid/Fl_Widget_Type.cxx | 14 +- fluid/Fl_Widget_Type.h | 2 +- fluid/Fl_Window_Type.cxx | 73 ++++- fluid/Fl_Window_Type.h | 4 +- fluid/Makefile | 1 + fluid/Shortcut_Button.cxx | 192 +++++++++++++ fluid/Shortcut_Button.h | 14 + fluid/factory.cxx | 231 ++++++++++++--- fluid/factory.h | 9 +- fluid/file.cxx | 40 +-- fluid/file.h | 4 +- fluid/fluid.cxx | 17 +- fluid/function_panel.cxx | 568 ++++++++++++++++++++++++++++++------- fluid/function_panel.fl | 69 ++++- fluid/undo.cxx | 9 + 24 files changed, 1256 insertions(+), 293 deletions(-) create mode 100644 fluid/Shortcut_Button.cxx diff --git a/fluid/CMakeLists.txt b/fluid/CMakeLists.txt index d45b7b1b7..a9b3af1a7 100644 --- a/fluid/CMakeLists.txt +++ b/fluid/CMakeLists.txt @@ -24,6 +24,7 @@ set (CPPFILES Fl_Widget_Type.cxx Fl_Window_Type.cxx Fluid_Image.cxx + Shortcut_Button.cxx about_panel.cxx align_widget.cxx alignment_panel.cxx diff --git a/fluid/Fl_Function_Type.cxx b/fluid/Fl_Function_Type.cxx index 2f9a18075..ac367c7b9 100644 --- a/fluid/Fl_Function_Type.cxx +++ b/fluid/Fl_Function_Type.cxx @@ -187,15 +187,16 @@ Fl_Function_Type::~Fl_Function_Type() { /** Create a new function for the widget tree. + \param[in] strategy new function add after current or as last child \return the new node */ -Fl_Type *Fl_Function_Type::make() { +Fl_Type *Fl_Function_Type::make(Strategy strategy) { 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->add(p, strategy); o->factory = this; o->public_ = 1; o->cdecl_ = 0; @@ -556,8 +557,10 @@ Fl_Code_Type::Fl_Code_Type() : Make a new code node. If the parent node is not a function, a message box will pop up and the request will be ignored. + \param[in] strategy add code after current or as last child + \return new Code node */ -Fl_Type *Fl_Code_Type::make() { +Fl_Type *Fl_Code_Type::make(Strategy strategy) { Fl_Type *p = Fl_Type::current; while (p && !p->is_code_block()) p = p->parent; if (!p) { @@ -566,7 +569,7 @@ Fl_Type *Fl_Code_Type::make() { } Fl_Code_Type *o = new Fl_Code_Type(); o->name("printf(\"Hello, World!\\n\");"); - o->add(p); + o->add(p, strategy); o->factory = this; return o; } @@ -726,8 +729,10 @@ Fl_CodeBlock_Type::~Fl_CodeBlock_Type() { Make a new code block. If the parent node is not a function or another codeblock, a message box will pop up and the request will be ignored. + \param[in] strategy add after current or as last child + \return new CodeBlock */ -Fl_Type *Fl_CodeBlock_Type::make() { +Fl_Type *Fl_CodeBlock_Type::make(Strategy strategy) { Fl_Type *p = Fl_Type::current; while (p && !p->is_code_block()) p = p->parent; if (!p) { @@ -737,7 +742,7 @@ Fl_Type *Fl_CodeBlock_Type::make() { Fl_CodeBlock_Type *o = new Fl_CodeBlock_Type(); o->name("if (test())"); o->after = 0; - o->add(p); + o->add(p, strategy); o->factory = this; return o; } @@ -851,15 +856,17 @@ int Fl_Decl_Type::is_public() const /** Make a new declaration. + \param[in] strategy add after current or as last child + \return new Declaration node */ -Fl_Type *Fl_Decl_Type::make() { +Fl_Type *Fl_Decl_Type::make(Strategy strategy) { 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->static_ = 1; o->name("int x;"); - o->add(p); + o->add(p, strategy); o->factory = this; return o; } @@ -966,7 +973,7 @@ BREAK2: /** Write the code to the source and header files. \todo There are a lot of side effect in this node depending on the given text - and the parent node which should really be documented. + and the parent node. They need to be understood and documented. */ void Fl_Decl_Type::write_code1() { const char* c = name(); @@ -1063,8 +1070,10 @@ Fl_Data_Type::~Fl_Data_Type() { /** Create an empty inline data node. + \param[in] strategy add after current or as last child + \return new inline data node */ -Fl_Type *Fl_Data_Type::make() { +Fl_Type *Fl_Data_Type::make(Strategy strategy) { Fl_Type *p = Fl_Type::current; while (p && !p->is_decl_block()) p = p->parent; Fl_Data_Type *o = new Fl_Data_Type(); @@ -1073,7 +1082,7 @@ Fl_Type *Fl_Data_Type::make() { o->filename_ = 0; o->text_mode_ = 0; o->name("myInlineData"); - o->add(p); + o->add(p, strategy); o->factory = this; return o; } @@ -1352,15 +1361,17 @@ int Fl_DeclBlock_Type::is_public() const {return public_;} /** Create a new declaration block. + \param[in] strategy add after current or as last child + \return new Declaration Blocknode */ -Fl_Type *Fl_DeclBlock_Type::make() { +Fl_Type *Fl_DeclBlock_Type::make(Strategy strategy) { 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->public_ = 0; o->after = fl_strdup("#endif"); - o->add(p); + o->add(p, strategy); o->factory = this; return o; } @@ -1479,8 +1490,10 @@ Fl_Comment_Type::Fl_Comment_Type() : /** Make a new comment node. + \param[in] strategy add after current or as last child + \return new Comment node */ -Fl_Type *Fl_Comment_Type::make() { +Fl_Type *Fl_Comment_Type::make(Strategy strategy) { Fl_Type *p = Fl_Type::current; while (p && !p->is_code_block()) p = p->parent; Fl_Comment_Type *o = new Fl_Comment_Type(); @@ -1488,7 +1501,7 @@ Fl_Type *Fl_Comment_Type::make() { o->in_h_ = 1; o->style_ = 0; o->name("my comment"); - o->add(p); + o->add(p, strategy); o->factory = this; o->title_buf[0] = 0; return o; @@ -1735,9 +1748,6 @@ void Fl_Comment_Type::write_code1() { /** \class Fl_Class_Type Manage a class declaration and implementation. - - \todo This is pretty complex and needs to be revisited to give - a good description. */ /// Prototype for a class node to be used by the factory. @@ -1780,8 +1790,10 @@ void Fl_Class_Type::prefix(const char*p) { /** Make a new class node. + \param[in] strategy add after current or as last child + \return new Class node */ -Fl_Type *Fl_Class_Type::make() { +Fl_Type *Fl_Class_Type::make(Strategy strategy) { Fl_Type *p = Fl_Type::current; while (p && !p->is_decl_block()) p = p->parent; Fl_Class_Type *o = new Fl_Class_Type(); @@ -1789,7 +1801,7 @@ Fl_Type *Fl_Class_Type::make() { o->class_prefix = NULL; o->subclass_of = NULL; o->public_ = 1; - o->add(p); + o->add(p, strategy); o->factory = this; return o; } diff --git a/fluid/Fl_Function_Type.h b/fluid/Fl_Function_Type.h index 7a6ac818e..2f0892047 100644 --- a/fluid/Fl_Function_Type.h +++ b/fluid/Fl_Function_Type.h @@ -49,7 +49,7 @@ class Fl_Function_Type : public Fl_Type { public: Fl_Function_Type(); ~Fl_Function_Type(); - Fl_Type *make(); + Fl_Type *make(Strategy strategy); void write_code1(); void write_code2(); void open(); @@ -77,7 +77,7 @@ class Fl_Code_Type : public Fl_Type { public: Fl_Code_Type(); - Fl_Type *make(); + Fl_Type *make(Strategy strategy); void write(); void write_code1(); void write_code2() { } @@ -100,7 +100,7 @@ class Fl_CodeBlock_Type : public Fl_Type { public: Fl_CodeBlock_Type(); ~Fl_CodeBlock_Type(); - Fl_Type *make(); + Fl_Type *make(Strategy strategy); void write_code1(); void write_code2(); void open(); @@ -123,7 +123,7 @@ protected: public: Fl_Decl_Type(); - Fl_Type *make(); + Fl_Type *make(Strategy strategy); void write_code1(); void write_code2() { } void open(); @@ -143,7 +143,7 @@ class Fl_Data_Type : public Fl_Decl_Type { public: Fl_Data_Type(); ~Fl_Data_Type(); - Fl_Type *make(); + Fl_Type *make(Strategy strategy); void write_code1(); void write_code2() {} void open(); @@ -162,7 +162,7 @@ class Fl_DeclBlock_Type : public Fl_Type { public: Fl_DeclBlock_Type(); ~Fl_DeclBlock_Type(); - Fl_Type *make(); + Fl_Type *make(Strategy strategy); void write_code1(); void write_code2(); void open(); @@ -183,7 +183,7 @@ class Fl_Comment_Type : public Fl_Type { public: Fl_Comment_Type(); - Fl_Type *make(); + Fl_Type *make(Strategy strategy); void write_code1(); void write_code2() { } void open(); @@ -210,7 +210,7 @@ public: char write_public_state; // true when public: has been printed Fl_Class_Type* parent_class; // save class if nested // - Fl_Type *make(); + Fl_Type *make(Strategy strategy); void write_code1(); void write_code2(); void open(); diff --git a/fluid/Fl_Group_Type.cxx b/fluid/Fl_Group_Type.cxx index a2a45a541..d5a832b17 100644 --- a/fluid/Fl_Group_Type.cxx +++ b/fluid/Fl_Group_Type.cxx @@ -42,8 +42,13 @@ void igroup::resize(int X, int Y, int W, int H) { Fl_Group_Type Fl_Group_type; // the "factory" -Fl_Type *Fl_Group_Type::make() { - return Fl_Widget_Type::make(); +/** + Create and add a new Group node. + \param[in] strategy add after current or as last child + \return new Group node + */ +Fl_Type *Fl_Group_Type::make(Strategy strategy) { + return Fl_Widget_Type::make(strategy); } void fix_group_size(Fl_Type *tt) { @@ -74,14 +79,14 @@ void group_cb(Fl_Widget *, void *) { } Fl_Widget_Type* q = (Fl_Widget_Type*)qq; force_parent = 1; - Fl_Group_Type *n = (Fl_Group_Type*)(Fl_Group_type.make()); + Fl_Group_Type *n = (Fl_Group_Type*)(Fl_Group_type.make(kAddAsLastChild)); 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->add(n, kAddAsLastChild); t = nxt; } fix_group_size(n); diff --git a/fluid/Fl_Group_Type.h b/fluid/Fl_Group_Type.h index a55e0dfd2..581f9ce3a 100644 --- a/fluid/Fl_Group_Type.h +++ b/fluid/Fl_Group_Type.h @@ -54,7 +54,7 @@ public: 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(); + Fl_Type *make(Strategy strategy); void write_code1(); void write_code2(); void add_child(Fl_Type*, Fl_Type*); diff --git a/fluid/Fl_Menu_Type.cxx b/fluid/Fl_Menu_Type.cxx index e3d6fec44..7bd55ce15 100644 --- a/fluid/Fl_Menu_Type.cxx +++ b/fluid/Fl_Menu_Type.cxx @@ -100,8 +100,12 @@ void Fl_Input_Choice_Type::build_menu() { o->redraw(); } - -Fl_Type *Fl_Menu_Item_Type::make() { +/** + Create and add a new Menu Item node. + \param[in] strategy add after current or as last child + \return new Menu Item node + */ +Fl_Type *Fl_Menu_Item_Type::make(Strategy strategy) { // Find the current menu item: Fl_Type* q = Fl_Type::current; Fl_Type* p = q; @@ -122,28 +126,43 @@ Fl_Type *Fl_Menu_Item_Type::make() { t->o = new Fl_Button(0,0,100,20); t->o->type(menuitemtype); t->factory = this; - t->add(p); + t->add(p, strategy); if (!reading_file) t->label(submenuflag ? "submenu" : "item"); return t; } -Fl_Type *Fl_Checkbox_Menu_Item_Type::make() { +/** + Create and add a new Checkbox Menu Item node. + \param[in] strategy add after current or as last child + \return new node + */ +Fl_Type *Fl_Checkbox_Menu_Item_Type::make(Strategy strategy) { menuitemtype = FL_MENU_TOGGLE; - Fl_Type* t = Fl_Menu_Item_Type::make(); + Fl_Type* t = Fl_Menu_Item_Type::make(strategy); menuitemtype = 0; return t; } -Fl_Type *Fl_Radio_Menu_Item_Type::make() { +/** + Create and add a new Radio ButtonMenu Item node. + \param[in] strategy add after current or as last child + \return new node + */ +Fl_Type *Fl_Radio_Menu_Item_Type::make(Strategy strategy) { menuitemtype = FL_MENU_RADIO; - Fl_Type* t = Fl_Menu_Item_Type::make(); + Fl_Type* t = Fl_Menu_Item_Type::make(strategy); menuitemtype = 0; return t; } -Fl_Type *Fl_Submenu_Type::make() { +/** + Create and add a new Submenu Item node. + \param[in] strategy add after current or as last child + \return new node + */ +Fl_Type *Fl_Submenu_Type::make(Strategy strategy) { submenuflag = 1; - Fl_Type* t = Fl_Menu_Item_Type::make(); + Fl_Type* t = Fl_Menu_Item_Type::make(strategy); submenuflag = 0; return t; } @@ -584,47 +603,6 @@ Fl_Menu_Bar_Type Fl_Menu_Bar_type; //////////////////////////////////////////////////////////////// // Shortcut entry item in panel: -void Shortcut_Button::draw() { - if (value()) draw_box(FL_DOWN_BOX, (Fl_Color)9); - else draw_box(FL_UP_BOX, FL_WHITE); - fl_font(FL_HELVETICA,14); fl_color(FL_FOREGROUND_COLOR); - if (use_FL_COMMAND && (svalue & (FL_CTRL|FL_META))) { - char buf[1024]; - fl_snprintf(buf, 1023, "Command+%s", fl_shortcut_label(svalue&~(FL_CTRL|FL_META))); - fl_draw(buf,x()+6,y(),w(),h(),FL_ALIGN_LEFT); - } else { - 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) ) { - if (isupper(v)) { - v = tolower(v); - v |= FL_SHIFT; - } - 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(); do_callback(); } - 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) { diff --git a/fluid/Fl_Menu_Type.h b/fluid/Fl_Menu_Type.h index b42798d61..ddd58efae 100644 --- a/fluid/Fl_Menu_Type.h +++ b/fluid/Fl_Menu_Type.h @@ -36,7 +36,7 @@ public: Fl_Menu_Item* subtypes() {return menu_item_type_menu;} const char* type_name() {return "MenuItem";} const char* alt_type_name() {return "fltk::Item";} - Fl_Type* make(); + Fl_Type* make(Strategy strategy); 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;} @@ -53,14 +53,14 @@ public: class Fl_Radio_Menu_Item_Type : public Fl_Menu_Item_Type { public: const char* type_name() {return "RadioMenuItem";} - Fl_Type* make(); + Fl_Type* make(Strategy strategy); int pixmapID() { return 55; } }; class Fl_Checkbox_Menu_Item_Type : public Fl_Menu_Item_Type { public: const char* type_name() {return "CheckMenuItem";} - Fl_Type* make(); + Fl_Type* make(Strategy strategy); int pixmapID() { return 54; } }; @@ -71,7 +71,7 @@ public: const char* alt_type_name() {return "fltk::ItemGroup";} int is_parent() const {return 1;} int is_button() const {return 0;} // disable shortcut - Fl_Type* make(); + Fl_Type* make(Strategy strategy); // 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);} diff --git a/fluid/Fl_Type.cxx b/fluid/Fl_Type.cxx index ff6a48cf6..5608969ea 100644 --- a/fluid/Fl_Type.cxx +++ b/fluid/Fl_Type.cxx @@ -14,6 +14,9 @@ // https://www.fltk.org/bugs.php // +/// \defgroup fl_type Basic Node for all Widgets and Functions +/// \{ + /** \class Fl_Type Each object described by Fluid is one of these objects. They are all stored in a double-linked list. @@ -34,6 +37,7 @@ copied or otherwise examined. #include "Fl_Function_Type.h" #include "Fl_Widget_Type.h" #include "Fl_Window_Type.h" +#include "Fl_Group_Type.h" #include "widget_browser.h" #include "file.h" #include "code.h" @@ -53,6 +57,8 @@ copied or otherwise examined. Fl_Type *Fl_Type::first = NULL; Fl_Type *Fl_Type::last = NULL; +Fl_Type *Fl_Type::current = NULL; +Fl_Type *Fl_Type::current_dnd = NULL; Fl_Type *in_this_only; // set if menu popped-up in window @@ -217,6 +223,31 @@ void fixvisible(Fl_Type *p) { // ---- implemenation of Fl_Type +/** \var Fl_Type *Fl_Type::parent + Link to the parent node in the tree structure. + Used for simulating a tree structure via a doubly linked list. + */ +/** \var Fl_Type *Fl_Type::level + Zero based depth of the node within the tree structure. + Level is used to emulate a tree structure: the first node with a lower + level in the prev list would be the parent of this node. If the next member + has a higher level value, it is this nodes first child. At the same level, + it would be the first sibling. + */ +/** \var Fl_Type *Fl_Type::next + Points to the next node in the doubly linked list. + If this is NULL, we are at the end of the list. + Used for simulating a tree structure via a doubly linked list. + */ +/** \var Fl_Type *Fl_Type::prev + Link to the next node in the tree structure. + If this is NULL, we are at the beginning of the list. + Used for simulating a tree structure via a doubly linked list. + */ + +/** + Constructor and base for any node in the widget tree. + */ Fl_Type::Fl_Type() { factory = 0; parent = 0; @@ -235,11 +266,20 @@ Fl_Type::Fl_Type() { code_position_end = header_position_end = -1; } +/** + Destructor for any node in the tree. + + The destructor removes itself from the doubly linked list. This is dangerous, + because the node does not know if it is part of the widget tree, or if it is + in a seperate tree. We try to take care of that as well as possible. + */ Fl_Type::~Fl_Type() { // 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 (Fl_Type::last==this) Fl_Type::last = prev; + if (Fl_Type::first==this) Fl_Type::first = next; if (current == this) current = 0; if (parent) parent->remove_child(this); if (name_) free((void*)name_); @@ -259,26 +299,54 @@ const char* Fl_Type::title() { } /** - Add this list/tree of widgets as a new child of p. + Return the window that contains this widget. + \return NULL if this is not a widget. + */ +Fl_Window_Type *Fl_Type::window() { + if (!is_widget()) + return NULL; + for (Fl_Type *t = this; t; t=t->parent) + if (t->is_window()) + return (Fl_Window_Type*)t; + return NULL; +} - \c this is not part of the widget browser. \c p should be in the +/** + Return the group that contains this widget. + \return NULL if this is not a widget. + */ +Fl_Group_Type *Fl_Type::group() { + if (!is_widget()) + return NULL; + for (Fl_Type *t = this; t; t=t->parent) + if (t->is_group()) + return (Fl_Group_Type*)t; + return NULL; +} + +/** + Add this list/tree of widgets as a new last child of p. + + \c this must not be part of the widget browser. \c p however must be in the widget_browser, so \c Fl_Type::first and \c Fl_Type::last are valid for \c p. This methods updates the widget_browser. \param[in] p insert \c this tree as a child of \c p + \param[in] strategy is kAddAsLastChild or kAddAfterCurrent */ -void Fl_Type::add(Fl_Type *p) { +void Fl_Type::add(Fl_Type *p, Strategy strategy) { if (p && parent == p) return; undo_checkpoint(); parent = p; - // p is not in the Widget_Browser, so we must run the linked list to find the last entry + // 'this' is not in the Widget_Browser, so we must run the linked list to find the last entry Fl_Type *end = this; while (end->next) end = end->next; // run the list again to set the future node levels - Fl_Type *q; + Fl_Type *q; // insert 'this' before q int newlevel; if (p) { + // find the last node that is a child or grandchild of p for (q = p->next; q && q->level > p->level; q = q->next) {/*empty*/} newlevel = p->level+1; } else { @@ -287,7 +355,7 @@ void Fl_Type::add(Fl_Type *p) { } for (Fl_Type *t = this->next; t; t = t->next) t->level += (newlevel-level); level = newlevel; - // now link this tree after p + // now link 'this' and its children before 'q', or last, if 'q' is NULL if (q) { prev = q->prev; prev->next = this; @@ -308,6 +376,22 @@ void Fl_Type::add(Fl_Type *p) { open_ = 1; fixvisible(this); set_modflag(1); + + if (strategy==kAddAfterCurrent && current) { + // we have current, t is the new node, p is the parent + // find the next child of the parent after current + //t->add(p); // add as a last child + Fl_Type *cc = current; + for (cc = current->next; cc; cc=cc->next) { + if (cc->level<=this->level) + break; + } + if (cc && cc->level==this->level && cc!=this) { + this->move_before(cc); + } + select(this, 1); + } + // run the p tree a last time to make sure the widget_browser updates correctly Fl_Type *a = p; for (Fl_Type *t = this; t && a != end; a = t, t = t->next) @@ -316,20 +400,20 @@ void Fl_Type::add(Fl_Type *p) { } /** - Add this list/tree of widgets as a new sibling before p. + Add `this` list/tree of widgets as a new sibling before `g`. - \c this is not part of the widget browser. \c g should be in the - widget_browser, so \c Fl_Type::first and \c Fl_Type::last are valid for \c p. + `This` is not part of the widget browser. `g` must be in the + widget_browser, so `Fl_Type::first` and `Fl_Type::last` are valid for `g . This methods updates the widget_browser. - \param[in] g insert \c this tree as a child of \c p + \param[in] g pointer to a node within the tree */ void Fl_Type::insert(Fl_Type *g) { - // p is not in the Widget_Browser, so we must run the linked list to find the last entry + // 'this' is not in the Widget_Browser, so we must run the linked list to find the last entry Fl_Type *end = this; while (end->next) end = end->next; - // this wil get the sam parent as g + // 'this' will get the same parent as 'g' parent = g->parent; // run the list again to set the future node levels int newlevel = g->level; @@ -734,3 +818,5 @@ void Fl_Type::write_code1() { void Fl_Type::write_code2() { } +/// \} + diff --git a/fluid/Fl_Type.h b/fluid/Fl_Type.h index 9027b4fc5..fa3a81ce9 100644 --- a/fluid/Fl_Type.h +++ b/fluid/Fl_Type.h @@ -21,6 +21,13 @@ #include class Fl_Type; +class Fl_Group_Type; +class Fl_Window_Type; + +typedef enum { + kAddAsLastChild = 0, + kAddAfterCurrent +} Strategy; void fixvisible(Fl_Type *p); void delete_all(int selected_only=0); @@ -52,15 +59,15 @@ protected: public: // things that should not be public: - Fl_Type *parent; // parent, which is previous in list + Fl_Type *parent; 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 + static Fl_Type *first, *last; + Fl_Type *next, *prev; Fl_Type *factory; const char *callback_name(); @@ -74,9 +81,12 @@ protected: public: virtual ~Fl_Type(); - virtual Fl_Type *make() = 0; + virtual Fl_Type *make(Strategy strategy) = 0; - void add(Fl_Type *parent); // add as new child + Fl_Window_Type *window(); + Fl_Group_Type *group(); + + void add(Fl_Type *parent, Strategy strategy); 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 @@ -104,6 +114,8 @@ public: virtual void remove_child(Fl_Type*) { } static Fl_Type *current; // most recently picked object + static Fl_Type *current_dnd; + virtual void open(); // what happens when you double-click // read and write data to a saved file: diff --git a/fluid/Fl_Widget_Type.cxx b/fluid/Fl_Widget_Type.cxx index d43832232..9f0d702fa 100644 --- a/fluid/Fl_Widget_Type.cxx +++ b/fluid/Fl_Widget_Type.cxx @@ -92,7 +92,12 @@ Fl_Widget_Type::ideal_spacing(int &x, int &y) { x = y = 10; } -Fl_Type *Fl_Widget_Type::make() { +/** + Make a new Widget node. + \param[in] strategy is kAddAsLastChild or kAddAfterCurrent + \return new node + */ +Fl_Type *Fl_Widget_Type::make(Strategy strategy) { // 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; @@ -162,7 +167,7 @@ Fl_Type *Fl_Widget_Type::make() { // Put it in the parent: // ((Fl_Group *)(p->o))->add(t->o); (done by Fl_Type::add()) // add to browser: - t->add(p); + t->add(p, strategy); t->redraw(); return t; } @@ -1913,8 +1918,6 @@ void Fl_Widget_Type::open() { if (numselected) the_panel->show(); } -Fl_Type *Fl_Type::current; - extern void redraw_overlays(); extern void check_redraw_corresponding_parent(Fl_Type*); extern void redraw_browser(); @@ -2373,9 +2376,6 @@ void Fl_Widget_Type::write_widget_code() { if (i & FL_ALIGN_INSIDE) write_c("|FL_ALIGN_INSIDE"); write_c("));\n"); } - // avoid the unsupported combination of flegs when user sets - // "when" to "FL_WHEN_NEVER", but keeps the "no change" set. - // FIXME: This could be reflected in the GUI by graying out the button. Fl_When ww = o->when(); if (ww==FL_WHEN_NOT_CHANGED) ww = FL_WHEN_NEVER; diff --git a/fluid/Fl_Widget_Type.h b/fluid/Fl_Widget_Type.h index 6d39fb9f4..8325dcc56 100644 --- a/fluid/Fl_Widget_Type.h +++ b/fluid/Fl_Widget_Type.h @@ -73,7 +73,7 @@ public: void setinactive(Fluid_Image *); Fl_Widget_Type(); - Fl_Type *make(); + Fl_Type *make(Strategy strategy); void open(); const char *extra_code(int n) const {return extra_code_[n];} diff --git a/fluid/Fl_Window_Type.cxx b/fluid/Fl_Window_Type.cxx index 8f718ff05..21eefe868 100644 --- a/fluid/Fl_Window_Type.cxx +++ b/fluid/Fl_Window_Type.cxx @@ -27,6 +27,7 @@ #include "file.h" #include "code.h" #include "widget_panel.h" +#include "factory.h" #include #include @@ -349,7 +350,12 @@ int Overlay_Window::handle(int e) { return ret; } -Fl_Type *Fl_Window_Type::make() { +/** + Make and add a new WIndow node. + \param[in] strategy is kAddAsLastChild or kAddAfterCurrent + \return new node + */ +Fl_Type *Fl_Window_Type::make(Strategy strategy) { Fl_Type *p = Fl_Type::current; while (p && !p->is_code_block()) p = p->parent; if (!p) { @@ -372,7 +378,7 @@ Fl_Type *Fl_Window_Type::make() { Overlay_Window *w = new Overlay_Window(100,100); w->window = myo; myo->o = w; - myo->add(p); + myo->add(p, strategy); myo->modal = 0; myo->non_modal = 0; return myo; @@ -1181,8 +1187,60 @@ int Fl_Window_Type::popupx = 0x7FFFFFFF; // mark as invalid (MAXINT) int Fl_Window_Type::popupy = 0x7FFFFFFF; int Fl_Window_Type::handle(int event) { - static Fl_Type* selection; + static Fl_Type* selection = NULL; switch (event) { + case FL_DND_ENTER: + Fl::belowmouse(o); + case FL_DND_DRAG: + { + // find the innermost item clicked on: + selection = this; + for (Fl_Type* i=next; i && i->level>level; i=i->next) + if (i->is_group()) { + Fl_Widget_Type* myo = (Fl_Widget_Type*)i; + for (Fl_Widget *o1 = myo->o; o1; o1 = o1->parent()) + if (!o1->visible()) goto CONTINUE_DND; + if (Fl::event_inside(myo->o)) { + selection = myo; + if (Fl::event_clicks()==1) + reveal_in_browser(myo); + } + } + CONTINUE_DND: + if (selection && !selection->selected) { + select_only(selection); + ((Overlay_Window *)o)->redraw_overlay(); + } + } + case FL_DND_RELEASE: + return 1; + case FL_PASTE: + { Fl_Type *prototype = typename_to_prototype(Fl::event_text()); + if (prototype==NULL) + return 0; + + in_this_only = this; + popupx = Fl::event_x(); + popupy = Fl::event_y(); + // If the selected widget at dnd start and the drop target are the same, + // or in the same group, add after selection. Otherwise, just add + // at the end of the selected group. + if ( Fl_Type::current_dnd->group() + && selection->group() + && Fl_Type::current_dnd->group()==selection->group()) + { + Fl_Type *cc = Fl_Type::current; + Fl_Type::current = Fl_Type::current_dnd; + add_new_widget_from_user(prototype, kAddAfterCurrent); + Fl_Type::current = cc; + } else { + add_new_widget_from_user(prototype, kAddAsLastChild); + } + popupx = 0x7FFFFFFF; + popupy = 0x7FFFFFFF; // mark as invalid (MAXINT) + in_this_only = NULL; + return 1; + } case FL_PUSH: x1 = mx = Fl::event_x(); y1 = my = Fl::event_y(); @@ -1439,7 +1497,12 @@ int Fl_Window_Type::read_fdesign(const char* propname, const char* value) { Fl_Widget_Class_Type Fl_Widget_Class_type; Fl_Widget_Class_Type *current_widget_class = 0; -Fl_Type *Fl_Widget_Class_Type::make() { +/** + Create and add a new Widget Class node. + \param[in] strategy add after current or as last child + \return new node + */ +Fl_Type *Fl_Widget_Class_Type::make(Strategy strategy) { Fl_Type *p = Fl_Type::current; while (p && (!p->is_decl_block() || (p->is_widget() && p->is_class()))) p = p->parent; Fl_Widget_Class_Type *myo = new Fl_Widget_Class_Type(); @@ -1460,7 +1523,7 @@ Fl_Type *Fl_Widget_Class_Type::make() { Overlay_Window *w = new Overlay_Window(100,100); w->window = myo; myo->o = w; - myo->add(p); + myo->add(p, strategy); myo->modal = 0; myo->non_modal = 0; myo->wc_relative = 0; diff --git a/fluid/Fl_Window_Type.h b/fluid/Fl_Window_Type.h index 5868e2576..97d5779aa 100644 --- a/fluid/Fl_Window_Type.h +++ b/fluid/Fl_Window_Type.h @@ -68,7 +68,7 @@ public: Fl_Window_Type() { drag = dx = dy = 0; sr_min_w = sr_min_h = sr_max_w = sr_max_h = 0; } uchar modal, non_modal; - Fl_Type *make(); + Fl_Type *make(Strategy strategy); virtual const char *type_name() {return "Fl_Window";} virtual const char *alt_type_name() {return "fltk::Window";} @@ -116,7 +116,7 @@ public: void write_code1(); void write_code2(); - Fl_Type *make(); + Fl_Type *make(Strategy strategy); virtual const char *type_name() {return "widget_class";} int pixmapID() { return 48; } int is_parent() const {return 1;} diff --git a/fluid/Makefile b/fluid/Makefile index c87c05719..8fd23d3bf 100644 --- a/fluid/Makefile +++ b/fluid/Makefile @@ -26,6 +26,7 @@ CPPFILES = \ Fl_Widget_Type.cxx \ Fl_Window_Type.cxx \ Fluid_Image.cxx \ + Shortcut_Button.cxx \ about_panel.cxx \ align_widget.cxx \ alignment_panel.cxx \ diff --git a/fluid/Shortcut_Button.cxx b/fluid/Shortcut_Button.cxx new file mode 100644 index 000000000..bc65fe8e9 --- /dev/null +++ b/fluid/Shortcut_Button.cxx @@ -0,0 +1,192 @@ +// +// Widget type code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2021 by Bill Spitzak and others. +// +// This library is free software. Distribution and use rights are outlined in +// the file "COPYING" which should have been included with this file. If this +// file is missing or damaged, see the license at: +// +// https://www.fltk.org/COPYING.php +// +// Please see the following page on how to report bugs and issues: +// +// https://www.fltk.org/bugs.php +// + +/// \defgroup fl_type Basic Node for all Widgets and Functions +/// \{ + +/** \class Fl_Type +Each object described by Fluid is one of these objects. They +are all stored in a double-linked list. + +The "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 "Shortcut_Button.h" + +#include "fluid.h" +#include "Fl_Window_Type.h" +#include "factory.h" +#include "widget_panel.h" + +#include +#include +#include +#include +#include +#include "../src/flstring.h" + +/** \class Shortcut_Button + A button that allows the user to type a key combination to create shortcuts. + After clicked once, the button catches the following keyboard events and + records the pressed keys and all modifiers. It draws a text representation of + the shortcut. The backspace key deletes the current shortcut. + */ + +/** + Draw the textual representation of the shortcut. + */ +void Shortcut_Button::draw() { + if (value()) draw_box(FL_DOWN_BOX, (Fl_Color)9); + else draw_box(FL_UP_BOX, FL_WHITE); + fl_font(FL_HELVETICA,14); fl_color(FL_FOREGROUND_COLOR); + if (use_FL_COMMAND && (svalue & (FL_CTRL|FL_META))) { + char buf[1024]; + fl_snprintf(buf, 1023, "Command+%s", fl_shortcut_label(svalue&~(FL_CTRL|FL_META))); + fl_draw(buf,x()+6,y(),w(),h(),FL_ALIGN_LEFT); + } else { + fl_draw(fl_shortcut_label(svalue),x()+6,y(),w(),h(),FL_ALIGN_LEFT); + } +} + +/** + Handle keystrokes to catch the user's shortcut. + */ +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) ) { + if (isupper(v)) { + v = tolower(v); + v |= FL_SHIFT; + } + 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(); do_callback(); } + 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; + } +} + +/** \class Widget_Bin_Button + A button for the widget bin that allows the user to drag widgets into a window. + Dragging and dropping a new widget makes it easy for the user to position + a widget inside a window or group. + */ + +/** + Convert mouse dragging into a drag and drop event. + */ +int Widget_Bin_Button::handle(int inEvent) +{ + int ret = 0; + switch (inEvent) { + case FL_PUSH: + Fl_Button::handle(inEvent); + return 1; // make sure that we get drag events + case FL_DRAG: + ret = Fl_Button::handle(inEvent); + if (!user_data()) + return ret; + if (!Fl::event_is_click()) { // make it a dnd event + // fake a drag outside of the widget + Fl::e_x = x()-1; + Fl_Button::handle(inEvent); + // fake a buttton release + Fl_Button::handle(FL_RELEASE); + // make it into a dnd event + const char *type_name = (const char*)user_data(); + Fl_Type::current_dnd = Fl_Type::current; + Fl::copy(type_name, strlen(type_name)+1, 0); + Fl::dnd(); + return 1; + } + return ret; + } + return Fl_Button::handle(inEvent); +} + +/** \class Widget_Bin_Window_Button + This button is used by the widget bin to create new windows by drag'n'drop. + The new window will be created wherever the user drops it on the desktop. + */ + +/** + Convert mouse dragging into a drag and drop event. + */ +int Widget_Bin_Window_Button::handle(int inEvent) +{ + static Fl_Window *drag_win = NULL; + int ret = 0; + switch (inEvent) { + case FL_PUSH: + Fl_Button::handle(inEvent); + return 1; // make sure that we get drag events + case FL_DRAG: + ret = Fl_Button::handle(inEvent); + if (!user_data()) + return ret; + if (!Fl::event_is_click()) { + if (!drag_win) { + drag_win = new Fl_Window(0, 0, 100, 100); + drag_win->border(0); + drag_win->set_non_modal(); + } + if (drag_win) { + drag_win->position(Fl::event_x_root()+1, Fl::event_y_root()+1); + drag_win->show(); + } + // Does not work outside window: fl_cursor(FL_CURSOR_HAND); + } + return ret; + case FL_RELEASE: + if (drag_win) { + Fl::delete_widget(drag_win); + drag_win = NULL; + // create a new window here + Fl_Type *prototype = typename_to_prototype((char*)user_data()); + if (prototype) { + Fl_Type *new_type = add_new_widget_from_user(prototype, kAddAfterCurrent); + if (new_type && new_type->is_window()) { + Fl_Window_Type *new_window = (Fl_Window_Type*)new_type; + Fl_Window *w = (Fl_Window *)new_window->o; + w->position(Fl::event_x_root(), Fl::event_y_root()); + } + } + } + return Fl_Button::handle(inEvent); + } + return Fl_Button::handle(inEvent); +} diff --git a/fluid/Shortcut_Button.h b/fluid/Shortcut_Button.h index 790415158..1c46b8afc 100644 --- a/fluid/Shortcut_Button.h +++ b/fluid/Shortcut_Button.h @@ -28,5 +28,19 @@ public: Fl_Button(X,Y,W,H,l) {svalue = 0;} }; +class Widget_Bin_Button : public Fl_Button { +public: + int handle(int); + Widget_Bin_Button(int X,int Y,int W,int H, const char* l = 0) : + Fl_Button(X,Y,W,H,l) { } +}; + +class Widget_Bin_Window_Button : public Fl_Button { +public: + int handle(int); + Widget_Bin_Window_Button(int X,int Y,int W,int H, const char* l = 0) : + Fl_Button(X,Y,W,H,l) { } +}; + #endif diff --git a/fluid/factory.cxx b/fluid/factory.cxx index d1b1b664d..dfc75d930 100644 --- a/fluid/factory.cxx +++ b/fluid/factory.cxx @@ -26,9 +26,11 @@ #include "fluid.h" #include "Fl_Window_Type.h" +#include "pixmaps.h" #include "undo.h" #include +#include #include #include #include @@ -36,8 +38,7 @@ #include "../src/flstring.h" #include - -extern Fl_Pixmap *pixmap[]; +#include //////////////////////////////////////////////////////////////// @@ -169,8 +170,6 @@ static Fl_Round_Button_Type Fl_Round_Button_type; //////////////////////////////////////////////////////////////// -extern int batch_mode; - #include #include #include @@ -956,12 +955,106 @@ extern class Fl_Wizard_Type Fl_Wizard_type; extern void select(Fl_Type *,int); extern void select_only(Fl_Type *); -#include +/** + List all known types. + This is used to convert a type name into a pointer to the prototype. + This list may contain types that are supported in .fl files, but not + available in the *New* menu. + */ +static Fl_Type *known_types[] = { + // functions + (Fl_Type*)&Fl_Function_type, + (Fl_Type*)&Fl_Code_type, + (Fl_Type*)&Fl_CodeBlock_type, + (Fl_Type*)&Fl_Decl_type, + (Fl_Type*)&Fl_DeclBlock_type, + (Fl_Type*)&Fl_Class_type, + (Fl_Type*)&Fl_Widget_Class_type, + (Fl_Type*)&Fl_Comment_type, + (Fl_Type*)&Fl_Data_type, + // groups + (Fl_Type*)&Fl_Window_type, + (Fl_Type*)&Fl_Group_type, + (Fl_Type*)&Fl_Pack_type, + (Fl_Type*)&Fl_Tabs_type, + (Fl_Type*)&Fl_Scroll_type, + (Fl_Type*)&Fl_Tile_type, + (Fl_Type*)&Fl_Wizard_type, + // buttons + (Fl_Type*)&Fl_Button_type, + (Fl_Type*)&Fl_Return_Button_type, + (Fl_Type*)&Fl_Light_Button_type, + (Fl_Type*)&Fl_Check_Button_type, + (Fl_Type*)&Fl_Repeat_Button_type, + (Fl_Type*)&Fl_Round_Button_type, + // valuators + (Fl_Type*)&Fl_Slider_type, + (Fl_Type*)&Fl_Scrollbar_type, + (Fl_Type*)&Fl_Value_Slider_type, + (Fl_Type*)&Fl_Adjuster_type, + (Fl_Type*)&Fl_Counter_type, + (Fl_Type*)&Fl_Spinner_type, + (Fl_Type*)&Fl_Dial_type, + (Fl_Type*)&Fl_Roller_type, + (Fl_Type*)&Fl_Value_Input_type, + (Fl_Type*)&Fl_Value_Output_type, + // text + (Fl_Type*)&Fl_Input_type, + (Fl_Type*)&Fl_Output_type, + (Fl_Type*)&Fl_Text_Editor_type, + (Fl_Type*)&Fl_Text_Display_type, + (Fl_Type*)&Fl_File_Input_type, + (Fl_Type*)&Fl_Simple_Terminal_type, + // menus + (Fl_Type*)&Fl_Menu_Bar_type, + (Fl_Type*)&Fl_Menu_Button_type, + (Fl_Type*)&Fl_Choice_type, + (Fl_Type*)&Fl_Input_Choice_type, + (Fl_Type*)&Fl_Submenu_type, + (Fl_Type*)&Fl_Menu_Item_type, + (Fl_Type*)&Fl_Checkbox_Menu_Item_type, + (Fl_Type*)&Fl_Radio_Menu_Item_type, + // browsers + (Fl_Type*)&Fl_Browser_type, + (Fl_Type*)&Fl_Check_Browser_type, + (Fl_Type*)&Fl_File_Browser_type, + (Fl_Type*)&Fl_Tree_type, + (Fl_Type*)&Fl_Help_View_type, + (Fl_Type*)&Fl_Table_type, + // misc + (Fl_Type*)&Fl_Box_type, + (Fl_Type*)&Fl_Clock_type, + (Fl_Type*)&Fl_Progress_type, +}; -static void cb(Fl_Widget *, void *v) { +/** + Create and add a new widget to the widget tree. + + Fluid will try to set a default postion for widgets to the user's expectation. + Using the context menu will put new widgets at the position of the mouse click. + Pulldown menu and bin actions will generate widgets no too far from previously + added widgets in the same group. + + Widgets can be added by dragging them from the widget bin to the + desired location. + + By setting the strategy, widgets are added as the last child of a group (this + is done when reading them from a file), or close to the current widget, which + the user would expect in interactive mode. + + \param[in] inPrototype pointer to one of the FL_..._type prototype; note the + lower case 't' in type. + \param[in] strategy add after current or as last child + + \see add_new_widget_from_file(const char*, int) + add_new_widget_from_user(Fl_Type*, int) + add_new_widget_from_user(const char*, int) + */ +Fl_Type *add_new_widget_from_user(Fl_Type *inPrototype, Strategy strategy) { undo_checkpoint(); undo_suspend(); - Fl_Type *t = ((Fl_Type*)v)->make(); + Fl_Type *ins = Fl_Type::current; + Fl_Type *t = ((Fl_Type*)inPrototype)->make(strategy); if (t) { if (t->is_widget() && !t->is_window()) { Fl_Widget_Type *wt = (Fl_Widget_Type *)t; @@ -994,6 +1087,23 @@ static void cb(Fl_Widget *, void *v) { } } } +#if 0 + // Fluid inserts widgets always as the last child of a matching group. + // This is great when reading a file, but if users do thins interactively, + // they expect the new widget close to where they worked previously. + if (ins) { + // if the new and current widget are siblings, just move it here. + if (ins->level==t->level) { + Fl_Type *c; + for (c=t; c && c!=ins && c->level>=t->level; c=c->prev) { } + if (c==ins) { + t->move_before(ins); // together the same as 'move_after' + ins->move_before(t); + } + } + } +#endif + // make the new widget visible select_only(t); set_modflag(1); t->open(); @@ -1002,6 +1112,36 @@ static void cb(Fl_Widget *, void *v) { undo_last --; } undo_resume(); + return t; +} + +/** + Create and add a new widget to the widget tree. + \param[in] inName find the right prototype by this name + \param[in] strategy where to add the node + \return the newly created node + \see add_new_widget_from_file(const char*, int) + add_new_widget_from_user(Fl_Type*, int) + add_new_widget_from_user(const char*, int) + */ +Fl_Type *add_new_widget_from_user(const char *inName, Strategy strategy) { + Fl_Type *prototype = typename_to_prototype(inName); + if (prototype) + return add_new_widget_from_user(prototype, strategy); + else + return NULL; +} + +/** + Callback for all menu items. + */ +static void cb(Fl_Widget *, void *v) { + Fl_Type *t = NULL; + if (Fl_Type::current && Fl_Type::current->is_group()) + t = ((Fl_Type*)v)->make(kAddAsLastChild); + else + t = ((Fl_Type*)v)->make(kAddAfterCurrent); + select_only(t); } Fl_Menu_Item New_Menu[] = { @@ -1080,10 +1220,15 @@ Fl_Menu_Item New_Menu[] = { #include -// Modify a menuitem to display an icon in front of the label. This is -// implemented using Fl_Multi_Label as the labeltype (FL_MULTI_LABEL). -// The icon (ic) may be null. If ic is null only the text (txt) is assigned -// to the label - Fl_Multi_Label is not used. txt must not be null. +/** + Modify a menuitem to display an icon in front of the label. + This is implemented using Fl_Multi_Label as the labeltype (FL_MULTI_LABEL). + The icon may be null. If ic is null only the text (is assigned + to the label and Fl_Multi_Label is not used. + \param[in] mi pointer to tme menu item that will be modified + \param[in] ic icon for the menu, may be NULL + \param[in] txt new label text, may *not* be NULL, will not be copied + */ static void make_iconlabel(Fl_Menu_Item *mi, Fl_Image *ic, const char *txt) { if (ic) { @@ -1097,9 +1242,10 @@ static void make_iconlabel(Fl_Menu_Item *mi, Fl_Image *ic, const char *txt) ml->typea = FL_IMAGE_LABEL; ml->typeb = FL_NORMAL_LABEL; ml->label(mi); + } else { + if (txt != mi->text) + mi->label(txt); } - else if (txt != mi->text) - mi->label(txt); } void fill_in_New_Menu() { @@ -1119,25 +1265,48 @@ void fill_in_New_Menu() { } } -// use keyword to pick the type, this is used to parse files: -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 (!fl_ascii_strcasecmp(tn,t->type_name())) { - r = t->make(); - break; - } - if (!fl_ascii_strcasecmp(tn,t->alt_type_name())) { - r = t->make(); - break; - } +/** + Find the correct prototype for a given type name. + \param[in] inName a C string that must match type_name() or alt_type_name() of + one of the known Fl_Type classes. + \return the matching prototype or NULL + */ +Fl_Type *typename_to_prototype(const char *inName) +{ + if (inName==NULL || *inName==0) + return NULL; + for (unsigned i = 0; i < sizeof(known_types)/sizeof(*known_types); i++) { + Fl_Type *prototype = known_types[i]; + if (fl_ascii_strcasecmp(inName, prototype->type_name())==0) + return prototype; + if (fl_ascii_strcasecmp(inName, prototype->alt_type_name())==0) + return prototype; } + return NULL; +} + +/** + Create and add a new type node to the widget tree. + + This is used by the .fl file reader. New types are always created as + the last child of the first compatible parent. New widgets have a default + setup. Their position, sizem and label will be read next in the file. + + \param[in] inName a C string that described the type we want + \param[in] strategy add after current or as last child + \return the type node that was created or NULL + \see add_new_widget_from_file(const char*, int) + add_new_widget_from_user(Fl_Type*, int) + add_new_widget_from_user(const char*, int) +*/ +Fl_Type *add_new_widget_from_file(const char *inName, Strategy strategy) { + reading_file = 1; // makes labels be null + Fl_Type *prototype = typename_to_prototype(inName); + if (!prototype) + return NULL; + Fl_Type *new_node = prototype->make(strategy); reading_file = 0; - return r; + return new_node; } //////////////////////////////////////////////////////////////// @@ -1269,8 +1438,6 @@ static symbol table[] = { {"HOR_NICE_SLIDER", FL_HOR_NICE_SLIDER}, }; -#include - 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++) diff --git a/fluid/factory.h b/fluid/factory.h index aaed57b20..7bd09eb05 100644 --- a/fluid/factory.h +++ b/fluid/factory.h @@ -17,13 +17,18 @@ #ifndef _FLUID_FACTORY_H #define _FLUID_FACTORY_H +#include "Fl_Type.h" + struct Fl_Menu_Item; -class Fl_Type; extern Fl_Menu_Item New_Menu[]; void fill_in_New_Menu(); -Fl_Type *Fl_Type_make(const char *tn); +Fl_Type *typename_to_prototype(const char *inName); + +Fl_Type *add_new_widget_from_file(const char *inName, Strategy strategy); +Fl_Type *add_new_widget_from_user(Fl_Type *inPrototype, Strategy strategy); +Fl_Type *add_new_widget_from_user(const char *inName, Strategy strategy); #endif // _FLUID_FACTORY_H diff --git a/fluid/file.cxx b/fluid/file.cxx index 37227d8b0..2732ae26b 100644 --- a/fluid/file.cxx +++ b/fluid/file.cxx @@ -45,7 +45,8 @@ /// \{ // This file contains code to read and write .fl file. -// TODO: there is a name confusion with routines that write to the C and Header files which must be fixed. +// TODO: there is a name confusion with routines that write to the C and Header +// TODO: files vs. thos the write to th fl file which should be fixed. static FILE *fout; static FILE *fin; @@ -434,10 +435,11 @@ int write_file(const char *filename, int selected_only) { \param[in] p parent node or NULL \param[in] paste if set, merge into existing design, else replace design - \param[in] options_read this is set if the options were already found in - a previous call + \param[in] strategy add nodes after current or as last child + \param[in] skip_options this is set if the options were already found in + a previous call, and there is no need to waste time searchingg for them. */ -static void read_children(Fl_Type *p, int paste, char options_read=0) { +static void read_children(Fl_Type *p, int paste, Strategy strategy, char skip_options=0) { Fl_Type::current = p; for (;;) { const char *c = read_word(); @@ -453,7 +455,7 @@ static void read_children(Fl_Type *p, int paste, char options_read=0) { } // Make sure that we don;t go through the list of options for child nodes - if (!options_read) { + if (!skip_options) { // this is the first word in a .fd file: if (!strcmp(c,"Magic:")) { read_fdesign(); @@ -470,7 +472,7 @@ static void read_children(Fl_Type *p, int paste, char options_read=0) { // back compatibility with Vincent Penne's original class code: if (!p && !strcmp(c,"define_in_struct")) { - Fl_Type *t = Fl_Type_make("class"); + Fl_Type *t = add_new_widget_from_file("class", kAddAsLastChild); t->name(read_word()); Fl_Type::current = p = t; paste = 1; // stops "missing }" error @@ -560,15 +562,15 @@ static void read_children(Fl_Type *p, int paste, char options_read=0) { } } { - Fl_Type *t = Fl_Type_make(c); + Fl_Type *t = add_new_widget_from_file(c, strategy); if (!t) { read_error("Unknown word \"%s\"", c); continue; } - t->name(read_word()); - // After reading the first widget, we no longer need to look for options - options_read = 1; + skip_options = 1; + + t->name(read_word()); c = read_word(1); if (strcmp(c,"{") && t->is_class()) { // @@ -595,7 +597,7 @@ static void read_children(Fl_Type *p, int paste, char options_read=0) { read_error("Missing child list for %s\n",t->title()); goto REUSE_C; } - read_children(t, 0, options_read); + read_children(t, 0, strategy, skip_options); } Fl_Type::current = p; @@ -608,9 +610,11 @@ static void read_children(Fl_Type *p, int paste, char options_read=0) { Read a .fl design file. \param[in] filename read this file \param[in] merge if this is set, merge the file into an existing design + at Fl_Type::current + \param[in] strategy add new nodes after current or as last child \return 0 if the operation failed, 1 if it succeeded */ -int read_file(const char *filename, int merge) { +int read_file(const char *filename, int merge, Strategy strategy) { Fl_Type *o; read_version = 0.0; if (!open_read(filename)) @@ -619,7 +623,7 @@ int read_file(const char *filename, int merge) { deselect(); else delete_all(); - read_children(Fl_Type::current, merge); + read_children(Fl_Type::current, merge, strategy); Fl_Type::current = 0; // Force menu items to be rebuilt... for (o = Fl_Type::first; o; o = o->next) @@ -720,7 +724,7 @@ void read_fdesign() { Fl_Widget_Type *group = 0; Fl_Widget_Type *widget = 0; if (!Fl_Type::current) { - Fl_Type *t = Fl_Type_make("Function"); + Fl_Type *t = add_new_widget_from_file("Function", kAddAsLastChild); t->name("create_the_forms()"); Fl_Type::current = t; } @@ -731,7 +735,7 @@ void read_fdesign() { if (!strcmp(name,"Name")) { - window = (Fl_Widget_Type*)Fl_Type_make("Fl_Window"); + window = (Fl_Widget_Type*)add_new_widget_from_file("Fl_Window", kAddAsLastChild); window->name(value); window->label(value); Fl_Type::current = widget = window; @@ -739,7 +743,7 @@ void read_fdesign() { } else if (!strcmp(name,"class")) { if (!strcmp(value,"FL_BEGIN_GROUP")) { - group = widget = (Fl_Widget_Type*)Fl_Type_make("Fl_Group"); + group = widget = (Fl_Widget_Type*)add_new_widget_from_file("Fl_Group", kAddAsLastChild); Fl_Type::current = group; } else if (!strcmp(value,"FL_END_GROUP")) { if (group) { @@ -754,10 +758,10 @@ void read_fdesign() { 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); + widget = (Fl_Widget_Type*)add_new_widget_from_file(value, kAddAsLastChild); if (!widget) { printf("class %s not found, using Fl_Button\n", value); - widget = (Fl_Widget_Type*)Fl_Type_make("Fl_Button"); + widget = (Fl_Widget_Type*)add_new_widget_from_file("Fl_Button", kAddAsLastChild); } } diff --git a/fluid/file.h b/fluid/file.h index 18b96492e..5470d1b26 100644 --- a/fluid/file.h +++ b/fluid/file.h @@ -17,6 +17,8 @@ #ifndef _FLUID_FILE_H #define _FLUID_FILE_H +#include "Fl_Type.h" + #include extern double read_version; @@ -34,7 +36,7 @@ const char *read_word(int wantbrace = 0); int write_file(const char *, int selected_only = 0); -int read_file(const char *, int merge); +int read_file(const char *, int merge, Strategy strategy=kAddAsLastChild); void read_fdesign(); #endif // _FLUID_FILE_H diff --git a/fluid/fluid.cxx b/fluid/fluid.cxx index 0f049b880..f584e182d 100644 --- a/fluid/fluid.cxx +++ b/fluid/fluid.cxx @@ -99,7 +99,9 @@ int G_debug = 0; char G_external_editor_command[512]; -/// \todo Functionality unclear. +/// If set, if the `current` node is a group, and a new group is added, it will +/// be added as sibling to the first group instead of inside the group. +/// \todo Needs to be verified. int force_parent = 0; /// This is set to create different labels when creating new widgets. @@ -197,10 +199,10 @@ const char* i18n_set = ""; /// \todo document me char i18n_program[FL_PATH_MAX] = ""; -/// \todo document me +/// Offset in pixels when adding widgets from an .fl file. int pasteoffset = 0; -/// \todo document me +/// Paste offset incrementing at every paste command. static int ipasteoffset = 0; @@ -999,11 +1001,16 @@ void delete_cb(Fl_Widget *, void *) { void paste_cb(Fl_Widget*, void*) { //if (ipasteoffset) force_parent = 1; pasteoffset = ipasteoffset; + // TODO: make the paste offset more predictable, if any at all. + // TODO: Don't use the grid if the user switched it off. if (gridx>1) pasteoffset = ((pasteoffset-1)/gridx+1)*gridx; if (gridy>1) pasteoffset = ((pasteoffset-1)/gridy+1)*gridy; undo_checkpoint(); undo_suspend(); - if (!read_file(cutfname(), 1)) { + Strategy strategy = kAddAfterCurrent; + if (Fl_Type::current && Fl_Type::current->is_group()) + strategy = kAddAsLastChild; + if (!read_file(cutfname(), 1, strategy)) { fl_message("Can't read %s: %s", cutfname(), strerror(errno)); } undo_resume(); @@ -1031,7 +1038,7 @@ void duplicate_cb(Fl_Widget*, void*) { undo_checkpoint(); undo_suspend(); - if (!read_file(cutfname(1), 1)) { + if (!read_file(cutfname(1), 1, kAddAfterCurrent)) { fl_message("Can't read %s: %s", cutfname(1), strerror(errno)); } fl_unlink(cutfname(1)); diff --git a/fluid/function_panel.cxx b/fluid/function_panel.cxx index 65326ae10..80762df28 100644 --- a/fluid/function_panel.cxx +++ b/fluid/function_panel.cxx @@ -18,6 +18,7 @@ #include "function_panel.h" #include "fluid.h" +#include "Shortcut_Button.h" #include "pixmaps.h" #include "factory.h" #include "Fl_Type.h" @@ -704,16 +705,11 @@ Fl_Double_Window* make_comment_panel() { } void type_make_cb(Fl_Widget*,void*d) { - undo_checkpoint(); - Fl_Type *t = Fl_Type_make((char*)d); - if (t) { - select_only(t); - set_modflag(1); - t->open(); - } else { - undo_current --; - undo_last --; - } + const char *type_name = (const char*)d; + if (Fl_Type::current && Fl_Type::current->is_group()) + add_new_widget_from_user(type_name, kAddAsLastChild); + else + add_new_widget_from_user(type_name, kAddAfterCurrent); } Fl_Window *widgetbin_panel=(Fl_Window *)0; @@ -789,306 +785,674 @@ Fl_Window* make_widgetbin() { } // Fl_Group* o { Fl_Group* o = new Fl_Group(87, 19, 79, 79, "Groups"); o->labelsize(12); - { Fl_Button* o = new Fl_Button(89, 21, 24, 24); + { Widget_Bin_Window_Button* o = new Widget_Bin_Window_Button(89, 21, 24, 24); o->tooltip("Window"); o->box(FL_THIN_UP_BOX); + o->color(FL_BACKGROUND_COLOR); + o->selection_color(FL_BACKGROUND_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(14); + o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Window")); + o->align(Fl_Align(FL_ALIGN_CENTER)); + o->when(FL_WHEN_RELEASE); o->image(pixmap[1]); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(114, 21, 24, 24); + } // Widget_Bin_Window_Button* o + { Widget_Bin_Button* o = new Widget_Bin_Button(114, 21, 24, 24); o->tooltip("Group"); o->box(FL_THIN_UP_BOX); + o->color(FL_BACKGROUND_COLOR); + o->selection_color(FL_BACKGROUND_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(14); + o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Group")); + o->align(Fl_Align(FL_ALIGN_CENTER)); + o->when(FL_WHEN_RELEASE); o->image(pixmap[6]); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(139, 21, 24, 24); + } // Widget_Bin_Button* o + { Widget_Bin_Button* o = new Widget_Bin_Button(139, 21, 24, 24); o->tooltip("Pack"); o->box(FL_THIN_UP_BOX); + o->color(FL_BACKGROUND_COLOR); + o->selection_color(FL_BACKGROUND_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(14); + o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Pack")); + o->align(Fl_Align(FL_ALIGN_CENTER)); + o->when(FL_WHEN_RELEASE); o->image(pixmap[22]); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(89, 46, 24, 24); + } // Widget_Bin_Button* o + { Widget_Bin_Button* o = new Widget_Bin_Button(89, 46, 24, 24); o->tooltip("Tabs"); o->box(FL_THIN_UP_BOX); + o->color(FL_BACKGROUND_COLOR); + o->selection_color(FL_BACKGROUND_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(14); + o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Tabs")); + o->align(Fl_Align(FL_ALIGN_CENTER)); + o->when(FL_WHEN_RELEASE); o->image(pixmap[13]); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(114, 46, 24, 24); + } // Widget_Bin_Button* o + { Widget_Bin_Button* o = new Widget_Bin_Button(114, 46, 24, 24); o->tooltip("Scroll"); o->box(FL_THIN_UP_BOX); + o->color(FL_BACKGROUND_COLOR); + o->selection_color(FL_BACKGROUND_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(14); + o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Scroll")); + o->align(Fl_Align(FL_ALIGN_CENTER)); + o->when(FL_WHEN_RELEASE); o->image(pixmap[19]); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(89, 71, 24, 24); + } // Widget_Bin_Button* o + { Widget_Bin_Button* o = new Widget_Bin_Button(89, 71, 24, 24); o->tooltip("Tile"); o->box(FL_THIN_UP_BOX); + o->color(FL_BACKGROUND_COLOR); + o->selection_color(FL_BACKGROUND_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(14); + o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Tile")); + o->align(Fl_Align(FL_ALIGN_CENTER)); + o->when(FL_WHEN_RELEASE); o->image(pixmap[20]); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(114, 71, 24, 24); + } // Widget_Bin_Button* o + { Widget_Bin_Button* o = new Widget_Bin_Button(114, 71, 24, 24); o->tooltip("Wizard"); o->box(FL_THIN_UP_BOX); + o->color(FL_BACKGROUND_COLOR); + o->selection_color(FL_BACKGROUND_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(14); + o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Wizard")); + o->align(Fl_Align(FL_ALIGN_CENTER)); + o->when(FL_WHEN_RELEASE); o->image(pixmap[21]); - } // Fl_Button* o + } // Widget_Bin_Button* o o->end(); } // Fl_Group* o { Fl_Group* o = new Fl_Group(171, 19, 54, 79, "Buttons"); o->labelsize(12); - { Fl_Button* o = new Fl_Button(173, 21, 24, 24); + { Widget_Bin_Button* o = new Widget_Bin_Button(173, 21, 24, 24); o->tooltip("Button"); o->box(FL_THIN_UP_BOX); + o->color(FL_BACKGROUND_COLOR); + o->selection_color(FL_BACKGROUND_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(14); + o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Button")); + o->align(Fl_Align(FL_ALIGN_CENTER)); + o->when(FL_WHEN_RELEASE); o->image(pixmap[2]); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(198, 21, 24, 24); + } // Widget_Bin_Button* o + { Widget_Bin_Button* o = new Widget_Bin_Button(198, 21, 24, 24); o->tooltip("Return Button"); o->box(FL_THIN_UP_BOX); + o->color(FL_BACKGROUND_COLOR); + o->selection_color(FL_BACKGROUND_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(14); + o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Return_Button")); + o->align(Fl_Align(FL_ALIGN_CENTER)); + o->when(FL_WHEN_RELEASE); o->image(pixmap[23]); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(173, 46, 24, 24); + } // Widget_Bin_Button* o + { Widget_Bin_Button* o = new Widget_Bin_Button(173, 46, 24, 24); o->tooltip("Light Button"); o->box(FL_THIN_UP_BOX); + o->color(FL_BACKGROUND_COLOR); + o->selection_color(FL_BACKGROUND_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(14); + o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Light_Button")); + o->align(Fl_Align(FL_ALIGN_CENTER)); + o->when(FL_WHEN_RELEASE); o->image(pixmap[24]); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(198, 46, 24, 24); + } // Widget_Bin_Button* o + { Widget_Bin_Button* o = new Widget_Bin_Button(198, 46, 24, 24); o->tooltip("Repeat Button"); o->box(FL_THIN_UP_BOX); + o->color(FL_BACKGROUND_COLOR); + o->selection_color(FL_BACKGROUND_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(14); + o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Repeat_Button")); + o->align(Fl_Align(FL_ALIGN_CENTER)); + o->when(FL_WHEN_RELEASE); o->image(pixmap[25]); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(173, 71, 24, 24); + } // Widget_Bin_Button* o + { Widget_Bin_Button* o = new Widget_Bin_Button(173, 71, 24, 24); o->tooltip("Check Button"); o->box(FL_THIN_UP_BOX); + o->color(FL_BACKGROUND_COLOR); + o->selection_color(FL_BACKGROUND_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(14); + o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Check_Button")); + o->align(Fl_Align(FL_ALIGN_CENTER)); + o->when(FL_WHEN_RELEASE); o->image(pixmap[3]); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(198, 71, 24, 24); + } // Widget_Bin_Button* o + { Widget_Bin_Button* o = new Widget_Bin_Button(198, 71, 24, 24); o->tooltip("Round Button"); o->box(FL_THIN_UP_BOX); + o->color(FL_BACKGROUND_COLOR); + o->selection_color(FL_BACKGROUND_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(14); + o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Round_Button")); + o->align(Fl_Align(FL_ALIGN_CENTER)); + o->when(FL_WHEN_RELEASE); o->image(pixmap[4]); - } // Fl_Button* o + } // Widget_Bin_Button* o o->end(); } // Fl_Group* o { Fl_Group* o = new Fl_Group(230, 19, 104, 79, "Valuators"); o->labelsize(12); - { Fl_Button* o = new Fl_Button(232, 21, 24, 24); + { Widget_Bin_Button* o = new Widget_Bin_Button(232, 21, 24, 24); o->tooltip("Slider"); o->box(FL_THIN_UP_BOX); + o->color(FL_BACKGROUND_COLOR); + o->selection_color(FL_BACKGROUND_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(14); + o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Slider")); + o->align(Fl_Align(FL_ALIGN_CENTER)); + o->when(FL_WHEN_RELEASE); o->image(pixmap[37]); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(257, 21, 24, 24); + } // Widget_Bin_Button* o + { Widget_Bin_Button* o = new Widget_Bin_Button(257, 21, 24, 24); o->tooltip("Scroll Bar"); o->box(FL_THIN_UP_BOX); + o->color(FL_BACKGROUND_COLOR); + o->selection_color(FL_BACKGROUND_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(14); + o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Scrollbar")); + o->align(Fl_Align(FL_ALIGN_CENTER)); + o->when(FL_WHEN_RELEASE); o->image(pixmap[38]); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(282, 21, 24, 24); + } // Widget_Bin_Button* o + { Widget_Bin_Button* o = new Widget_Bin_Button(282, 21, 24, 24); o->tooltip("Value Slider"); o->box(FL_THIN_UP_BOX); + o->color(FL_BACKGROUND_COLOR); + o->selection_color(FL_BACKGROUND_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(14); + o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Value_Slider")); + o->align(Fl_Align(FL_ALIGN_CENTER)); + o->when(FL_WHEN_RELEASE); o->image(pixmap[39]); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(307, 21, 24, 24); + } // Widget_Bin_Button* o + { Widget_Bin_Button* o = new Widget_Bin_Button(307, 21, 24, 24); o->tooltip("Value Output"); o->box(FL_THIN_UP_BOX); + o->color(FL_BACKGROUND_COLOR); + o->selection_color(FL_BACKGROUND_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(14); + o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Value_Output")); + o->align(Fl_Align(FL_ALIGN_CENTER)); + o->when(FL_WHEN_RELEASE); o->image(pixmap[45]); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(232, 46, 24, 24); + } // Widget_Bin_Button* o + { Widget_Bin_Button* o = new Widget_Bin_Button(232, 46, 24, 24); o->tooltip("Adjuster"); o->box(FL_THIN_UP_BOX); + o->color(FL_BACKGROUND_COLOR); + o->selection_color(FL_BACKGROUND_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(14); + o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Adjuster")); + o->align(Fl_Align(FL_ALIGN_CENTER)); + o->when(FL_WHEN_RELEASE); o->image(pixmap[40]); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(257, 46, 24, 24); + } // Widget_Bin_Button* o + { Widget_Bin_Button* o = new Widget_Bin_Button(257, 46, 24, 24); o->tooltip("Counter"); o->box(FL_THIN_UP_BOX); + o->color(FL_BACKGROUND_COLOR); + o->selection_color(FL_BACKGROUND_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(14); + o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Counter")); + o->align(Fl_Align(FL_ALIGN_CENTER)); + o->when(FL_WHEN_RELEASE); o->image(pixmap[41]); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(282, 46, 24, 24); + } // Widget_Bin_Button* o + { Widget_Bin_Button* o = new Widget_Bin_Button(282, 46, 24, 24); o->tooltip("Dial"); o->box(FL_THIN_UP_BOX); + o->color(FL_BACKGROUND_COLOR); + o->selection_color(FL_BACKGROUND_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(14); + o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Dial")); + o->align(Fl_Align(FL_ALIGN_CENTER)); + o->when(FL_WHEN_RELEASE); o->image(pixmap[42]); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(232, 71, 24, 24); + } // Widget_Bin_Button* o + { Widget_Bin_Button* o = new Widget_Bin_Button(232, 71, 24, 24); o->tooltip("Roller"); o->box(FL_THIN_UP_BOX); + o->color(FL_BACKGROUND_COLOR); + o->selection_color(FL_BACKGROUND_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(14); + o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Roller")); + o->align(Fl_Align(FL_ALIGN_CENTER)); + o->when(FL_WHEN_RELEASE); o->image(pixmap[43]); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(257, 71, 24, 24); + } // Widget_Bin_Button* o + { Widget_Bin_Button* o = new Widget_Bin_Button(257, 71, 24, 24); o->tooltip("Spinner"); o->box(FL_THIN_UP_BOX); + o->color(FL_BACKGROUND_COLOR); + o->selection_color(FL_BACKGROUND_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(14); + o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Spinner")); + o->align(Fl_Align(FL_ALIGN_CENTER)); + o->when(FL_WHEN_RELEASE); o->image(pixmap[47]); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(282, 71, 24, 24); + } // Widget_Bin_Button* o + { Widget_Bin_Button* o = new Widget_Bin_Button(282, 71, 24, 24); o->tooltip("Value Input"); o->box(FL_THIN_UP_BOX); + o->color(FL_BACKGROUND_COLOR); + o->selection_color(FL_BACKGROUND_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(14); + o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Value_Input")); + o->align(Fl_Align(FL_ALIGN_CENTER)); + o->when(FL_WHEN_RELEASE); o->image(pixmap[44]); - } // Fl_Button* o + } // Widget_Bin_Button* o o->end(); } // Fl_Group* o { Fl_Group* o = new Fl_Group(339, 19, 54, 79, "Text"); o->labelsize(12); - { Fl_Button* o = new Fl_Button(341, 21, 24, 24); + { Widget_Bin_Button* o = new Widget_Bin_Button(341, 21, 24, 24); o->tooltip("Input"); o->box(FL_THIN_UP_BOX); + o->color(FL_BACKGROUND_COLOR); + o->selection_color(FL_BACKGROUND_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(14); + o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Input")); + o->align(Fl_Align(FL_ALIGN_CENTER)); + o->when(FL_WHEN_RELEASE); o->image(pixmap[14]); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(366, 21, 24, 24); + } // Widget_Bin_Button* o + { Widget_Bin_Button* o = new Widget_Bin_Button(366, 21, 24, 24); o->tooltip("Output"); o->box(FL_THIN_UP_BOX); + o->color(FL_BACKGROUND_COLOR); + o->selection_color(FL_BACKGROUND_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(14); + o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Output")); + o->align(Fl_Align(FL_ALIGN_CENTER)); + o->when(FL_WHEN_RELEASE); o->image(pixmap[27]); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(341, 46, 24, 24); + } // Widget_Bin_Button* o + { Widget_Bin_Button* o = new Widget_Bin_Button(341, 46, 24, 24); o->tooltip("Text Edit"); o->box(FL_THIN_UP_BOX); + o->color(FL_BACKGROUND_COLOR); + o->selection_color(FL_BACKGROUND_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(14); + o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Text_Editor")); + o->align(Fl_Align(FL_ALIGN_CENTER)); + o->when(FL_WHEN_RELEASE); o->image(pixmap[29]); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(366, 46, 24, 24); + } // Widget_Bin_Button* o + { Widget_Bin_Button* o = new Widget_Bin_Button(366, 46, 24, 24); o->tooltip("Text Display"); o->box(FL_THIN_UP_BOX); + o->color(FL_BACKGROUND_COLOR); + o->selection_color(FL_BACKGROUND_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(14); + o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Text_Display")); + o->align(Fl_Align(FL_ALIGN_CENTER)); + o->when(FL_WHEN_RELEASE); o->image(pixmap[28]); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(341, 71, 24, 24); + } // Widget_Bin_Button* o + { Widget_Bin_Button* o = new Widget_Bin_Button(341, 71, 24, 24); o->tooltip("File Input"); o->box(FL_THIN_UP_BOX); + o->color(FL_BACKGROUND_COLOR); + o->selection_color(FL_BACKGROUND_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(14); + o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_File_Input")); + o->align(Fl_Align(FL_ALIGN_CENTER)); + o->when(FL_WHEN_RELEASE); o->image(pixmap[30]); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(366, 71, 24, 24); + } // Widget_Bin_Button* o + { Widget_Bin_Button* o = new Widget_Bin_Button(366, 71, 24, 24); o->tooltip("Simple Terminal"); o->box(FL_THIN_UP_BOX); + o->color(FL_BACKGROUND_COLOR); + o->selection_color(FL_BACKGROUND_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(14); + o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Simple_Terminal")); + o->align(Fl_Align(FL_ALIGN_CENTER)); + o->when(FL_WHEN_RELEASE); o->image(pixmap[52]); - } // Fl_Button* o + } // Widget_Bin_Button* o o->end(); } // Fl_Group* o { Fl_Group* o = new Fl_Group(398, 19, 79, 79, "Menus"); o->labelsize(12); - { Fl_Button* o = new Fl_Button(400, 21, 24, 24); + { Widget_Bin_Button* o = new Widget_Bin_Button(400, 21, 24, 24); o->tooltip("Input Choice"); o->box(FL_THIN_UP_BOX); + o->color(FL_BACKGROUND_COLOR); + o->selection_color(FL_BACKGROUND_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(14); + o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Input_Choice")); + o->align(Fl_Align(FL_ALIGN_CENTER)); + o->when(FL_WHEN_RELEASE); o->image(pixmap[53]); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(425, 21, 24, 24); + } // Widget_Bin_Button* o + { Widget_Bin_Button* o = new Widget_Bin_Button(425, 21, 24, 24); o->tooltip("Menu Item"); o->box(FL_THIN_UP_BOX); + o->color(FL_BACKGROUND_COLOR); + o->selection_color(FL_BACKGROUND_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(14); + o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("menuitem")); + o->align(Fl_Align(FL_ALIGN_CENTER)); + o->when(FL_WHEN_RELEASE); o->image(pixmap[16]); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(450, 21, 24, 24); + } // Widget_Bin_Button* o + { Widget_Bin_Button* o = new Widget_Bin_Button(450, 21, 24, 24); o->tooltip("Menu Bar"); o->box(FL_THIN_UP_BOX); + o->color(FL_BACKGROUND_COLOR); + o->selection_color(FL_BACKGROUND_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(14); + o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Menu_Bar")); + o->align(Fl_Align(FL_ALIGN_CENTER)); + o->when(FL_WHEN_RELEASE); o->image(pixmap[17]); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(400, 46, 24, 24); + } // Widget_Bin_Button* o + { Widget_Bin_Button* o = new Widget_Bin_Button(400, 46, 24, 24); o->tooltip("Menu Button"); o->box(FL_THIN_UP_BOX); + o->color(FL_BACKGROUND_COLOR); + o->selection_color(FL_BACKGROUND_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(14); + o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Menu_Button")); + o->align(Fl_Align(FL_ALIGN_CENTER)); + o->when(FL_WHEN_RELEASE); o->image(pixmap[26]); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(425, 46, 24, 24); + } // Widget_Bin_Button* o + { Widget_Bin_Button* o = new Widget_Bin_Button(425, 46, 24, 24); o->tooltip("Checkbox Menu Item"); o->box(FL_THIN_UP_BOX); + o->color(FL_BACKGROUND_COLOR); + o->selection_color(FL_BACKGROUND_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(14); + o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("checkmenuitem")); + o->align(Fl_Align(FL_ALIGN_CENTER)); + o->when(FL_WHEN_RELEASE); o->image(pixmap[54]); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(450, 46, 24, 24); + } // Widget_Bin_Button* o + { Widget_Bin_Button* o = new Widget_Bin_Button(450, 46, 24, 24); o->tooltip("Sub Menu"); o->box(FL_THIN_UP_BOX); + o->color(FL_BACKGROUND_COLOR); + o->selection_color(FL_BACKGROUND_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(14); + o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("submenu")); + o->align(Fl_Align(FL_ALIGN_CENTER)); + o->when(FL_WHEN_RELEASE); o->image(pixmap[18]); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(400, 71, 24, 24); + } // Widget_Bin_Button* o + { Widget_Bin_Button* o = new Widget_Bin_Button(400, 71, 24, 24); o->tooltip("Choice"); o->box(FL_THIN_UP_BOX); + o->color(FL_BACKGROUND_COLOR); + o->selection_color(FL_BACKGROUND_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(14); + o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Choice")); + o->align(Fl_Align(FL_ALIGN_CENTER)); + o->when(FL_WHEN_RELEASE); o->image(pixmap[15]); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(425, 71, 24, 24); + } // Widget_Bin_Button* o + { Widget_Bin_Button* o = new Widget_Bin_Button(425, 71, 24, 24); o->tooltip("Radio Menu Item"); o->box(FL_THIN_UP_BOX); + o->color(FL_BACKGROUND_COLOR); + o->selection_color(FL_BACKGROUND_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(14); + o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("radiomenuitem")); + o->align(Fl_Align(FL_ALIGN_CENTER)); + o->when(FL_WHEN_RELEASE); o->image(pixmap[55]); - } // Fl_Button* o + } // Widget_Bin_Button* o o->end(); } // Fl_Group* o { Fl_Group* o = new Fl_Group(482, 19, 54, 79, "Browsers"); o->labelsize(12); - { Fl_Button* o = new Fl_Button(484, 21, 24, 24); + { Widget_Bin_Button* o = new Widget_Bin_Button(484, 21, 24, 24); o->tooltip("Browser"); o->box(FL_THIN_UP_BOX); + o->color(FL_BACKGROUND_COLOR); + o->selection_color(FL_BACKGROUND_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(14); + o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Browser")); + o->align(Fl_Align(FL_ALIGN_CENTER)); + o->when(FL_WHEN_RELEASE); o->image(pixmap[31]); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(509, 21, 24, 24); + } // Widget_Bin_Button* o + { Widget_Bin_Button* o = new Widget_Bin_Button(509, 21, 24, 24); o->tooltip("Tree"); o->box(FL_THIN_UP_BOX); + o->color(FL_BACKGROUND_COLOR); + o->selection_color(FL_BACKGROUND_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(14); + o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Tree")); + o->align(Fl_Align(FL_ALIGN_CENTER)); + o->when(FL_WHEN_RELEASE); o->image(pixmap[50]); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(484, 46, 24, 24); + } // Widget_Bin_Button* o + { Widget_Bin_Button* o = new Widget_Bin_Button(484, 46, 24, 24); o->tooltip("Check Browser"); o->box(FL_THIN_UP_BOX); + o->color(FL_BACKGROUND_COLOR); + o->selection_color(FL_BACKGROUND_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(14); + o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Check_Browser")); + o->align(Fl_Align(FL_ALIGN_CENTER)); + o->when(FL_WHEN_RELEASE); o->image(pixmap[32]); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(509, 46, 24, 24); + } // Widget_Bin_Button* o + { Widget_Bin_Button* o = new Widget_Bin_Button(509, 46, 24, 24); o->tooltip("Help Browser"); o->box(FL_THIN_UP_BOX); + o->color(FL_BACKGROUND_COLOR); + o->selection_color(FL_BACKGROUND_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(14); + o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Help_View")); + o->align(Fl_Align(FL_ALIGN_CENTER)); + o->when(FL_WHEN_RELEASE); o->image(pixmap[35]); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(484, 71, 24, 24); + } // Widget_Bin_Button* o + { Widget_Bin_Button* o = new Widget_Bin_Button(484, 71, 24, 24); o->tooltip("File Browser"); o->box(FL_THIN_UP_BOX); + o->color(FL_BACKGROUND_COLOR); + o->selection_color(FL_BACKGROUND_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(14); + o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_File_Browser")); + o->align(Fl_Align(FL_ALIGN_CENTER)); + o->when(FL_WHEN_RELEASE); o->image(pixmap[33]); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(509, 71, 24, 24); + } // Widget_Bin_Button* o + { Widget_Bin_Button* o = new Widget_Bin_Button(509, 71, 24, 24); o->tooltip("Table"); o->box(FL_THIN_UP_BOX); + o->color(FL_BACKGROUND_COLOR); + o->selection_color(FL_BACKGROUND_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(14); + o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Table")); + o->align(Fl_Align(FL_ALIGN_CENTER)); + o->when(FL_WHEN_RELEASE); o->image(pixmap[51]); - } // Fl_Button* o + } // Widget_Bin_Button* o o->end(); } // Fl_Group* o { Fl_Group* o = new Fl_Group(540, 19, 55, 79, "Misc"); o->labelsize(12); - { Fl_Button* o = new Fl_Button(542, 21, 24, 24); + { Widget_Bin_Button* o = new Widget_Bin_Button(542, 21, 24, 24); o->tooltip("Box"); o->box(FL_THIN_UP_BOX); + o->color(FL_BACKGROUND_COLOR); + o->selection_color(FL_BACKGROUND_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(14); + o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Box")); + o->align(Fl_Align(FL_ALIGN_CENTER)); + o->when(FL_WHEN_RELEASE); o->image(pixmap[5]); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(567, 21, 24, 24); + } // Widget_Bin_Button* o + { Widget_Bin_Button* o = new Widget_Bin_Button(567, 21, 24, 24); o->tooltip("Clock"); o->box(FL_THIN_UP_BOX); + o->color(FL_BACKGROUND_COLOR); + o->selection_color(FL_BACKGROUND_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(14); + o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Clock")); + o->align(Fl_Align(FL_ALIGN_CENTER)); + o->when(FL_WHEN_RELEASE); o->image(pixmap[34]); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(542, 46, 24, 24); + } // Widget_Bin_Button* o + { Widget_Bin_Button* o = new Widget_Bin_Button(542, 46, 24, 24); o->tooltip("Progress"); o->box(FL_THIN_UP_BOX); + o->color(FL_BACKGROUND_COLOR); + o->selection_color(FL_BACKGROUND_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(14); + o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Progress")); + o->align(Fl_Align(FL_ALIGN_CENTER)); + o->when(FL_WHEN_RELEASE); o->image(pixmap[36]); - } // Fl_Button* o + } // Widget_Bin_Button* o o->end(); } // Fl_Group* o widgetbin_panel->set_non_modal(); diff --git a/fluid/function_panel.fl b/fluid/function_panel.fl index df0e307b2..e3f4d76de 100644 --- a/fluid/function_panel.fl +++ b/fluid/function_panel.fl @@ -25,6 +25,9 @@ comment {// decl {\#include "fluid.h"} {private local } +decl {\#include "Shortcut_Button.h"} {private global +} + decl {\#include "pixmaps.h"} {private local } @@ -84,7 +87,7 @@ Function {make_function_panel()} {open } MenuItem {} { label global - user_data 1 user_data_type long selected + user_data 1 user_data_type long xywh {15 15 100 20} labelsize 11 } } @@ -522,18 +525,10 @@ Function {make_comment_panel()} {} { } } -Function {type_make_cb(Fl_Widget*,void*d)} {return_type void +Function {type_make_cb(Fl_Widget*,void*d)} {open return_type void } { - code {undo_checkpoint(); - Fl_Type *t = Fl_Type_make((char*)d); - if (t) { - select_only(t); - set_modflag(1); - t->open(); - } else { - undo_current --; - undo_last --; - }} {} + code {const char *type_name = (const char*)d; +add_new_widget_from_user(type_name);} {} } Function {make_widgetbin()} {open @@ -543,7 +538,7 @@ Function {make_widgetbin()} {open callback {if (Fl::event()==FL_SHORTCUT && Fl::event_key()==FL_Escape) exit_cb((Fl_Widget*)o, v); else - toggle_widgetbin_cb((Fl_Widget*)o, v);} + toggle_widgetbin_cb((Fl_Widget*)o, v);} open xywh {449 206 600 102} type Single align 80 non_modal visible } { Fl_Group {} { @@ -611,45 +606,52 @@ else } { Fl_Button {} { user_data {"Fl_Window"} - callback type_make_cb + callback type_make_cb selected tooltip Window xywh {89 21 24 24} box THIN_UP_BOX code0 {o->image(pixmap[1]);} + class Widget_Bin_Window_Button } Fl_Button {} { user_data {"Fl_Group"} callback type_make_cb tooltip Group xywh {114 21 24 24} box THIN_UP_BOX code0 {o->image(pixmap[6]);} + class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Pack"} callback type_make_cb tooltip Pack xywh {139 21 24 24} box THIN_UP_BOX code0 {o->image(pixmap[22]);} + class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Tabs"} callback type_make_cb tooltip Tabs xywh {89 46 24 24} box THIN_UP_BOX code0 {o->image(pixmap[13]);} + class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Scroll"} callback type_make_cb tooltip Scroll xywh {114 46 24 24} box THIN_UP_BOX code0 {o->image(pixmap[19]);} + class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Tile"} callback type_make_cb tooltip Tile xywh {89 71 24 24} box THIN_UP_BOX code0 {o->image(pixmap[20]);} + class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Wizard"} callback type_make_cb tooltip Wizard xywh {114 71 24 24} box THIN_UP_BOX code0 {o->image(pixmap[21]);} + class Widget_Bin_Button } } Fl_Group {} { @@ -661,36 +663,42 @@ else callback type_make_cb tooltip Button xywh {173 21 24 24} box THIN_UP_BOX code0 {o->image(pixmap[2]);} + class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Return_Button"} callback type_make_cb tooltip {Return Button} xywh {198 21 24 24} box THIN_UP_BOX code0 {o->image(pixmap[23]);} + class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Light_Button"} callback type_make_cb tooltip {Light Button} xywh {173 46 24 24} box THIN_UP_BOX code0 {o->image(pixmap[24]);} + class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Repeat_Button"} callback type_make_cb tooltip {Repeat Button} xywh {198 46 24 24} box THIN_UP_BOX code0 {o->image(pixmap[25]);} + class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Check_Button"} callback type_make_cb tooltip {Check Button} xywh {173 71 24 24} box THIN_UP_BOX code0 {o->image(pixmap[3]);} + class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Round_Button"} callback type_make_cb tooltip {Round Button} xywh {198 71 24 24} box THIN_UP_BOX code0 {o->image(pixmap[4]);} + class Widget_Bin_Button } } Fl_Group {} { @@ -702,60 +710,70 @@ else callback type_make_cb tooltip Slider xywh {232 21 24 24} box THIN_UP_BOX code0 {o->image(pixmap[37]);} + class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Scrollbar"} callback type_make_cb tooltip {Scroll Bar} xywh {257 21 24 24} box THIN_UP_BOX code0 {o->image(pixmap[38]);} + class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Value_Slider"} callback type_make_cb tooltip {Value Slider} xywh {282 21 24 24} box THIN_UP_BOX code0 {o->image(pixmap[39]);} + class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Value_Output"} callback type_make_cb tooltip {Value Output} xywh {307 21 24 24} box THIN_UP_BOX code0 {o->image(pixmap[45]);} + class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Adjuster"} callback type_make_cb tooltip Adjuster xywh {232 46 24 24} box THIN_UP_BOX code0 {o->image(pixmap[40]);} + class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Counter"} callback type_make_cb tooltip Counter xywh {257 46 24 24} box THIN_UP_BOX code0 {o->image(pixmap[41]);} + class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Dial"} callback type_make_cb tooltip Dial xywh {282 46 24 24} box THIN_UP_BOX code0 {o->image(pixmap[42]);} + class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Roller"} callback type_make_cb tooltip Roller xywh {232 71 24 24} box THIN_UP_BOX code0 {o->image(pixmap[43]);} + class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Spinner"} callback type_make_cb tooltip Spinner xywh {257 71 24 24} box THIN_UP_BOX code0 {o->image(pixmap[47]);} + class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Value_Input"} callback type_make_cb tooltip {Value Input} xywh {282 71 24 24} box THIN_UP_BOX code0 {o->image(pixmap[44]);} + class Widget_Bin_Button } } Fl_Group {} { @@ -767,36 +785,42 @@ else callback type_make_cb tooltip Input xywh {341 21 24 24} box THIN_UP_BOX code0 {o->image(pixmap[14]);} + class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Output"} callback type_make_cb tooltip Output xywh {366 21 24 24} box THIN_UP_BOX code0 {o->image(pixmap[27]);} + class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Text_Editor"} callback type_make_cb tooltip {Text Edit} xywh {341 46 24 24} box THIN_UP_BOX code0 {o->image(pixmap[29]);} + class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Text_Display"} callback type_make_cb tooltip {Text Display} xywh {366 46 24 24} box THIN_UP_BOX code0 {o->image(pixmap[28]);} + class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_File_Input"} callback type_make_cb tooltip {File Input} xywh {341 71 24 24} box THIN_UP_BOX code0 {o->image(pixmap[30]);} + class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Simple_Terminal"} callback type_make_cb tooltip {Simple Terminal} xywh {366 71 24 24} box THIN_UP_BOX code0 {o->image(pixmap[52]);} + class Widget_Bin_Button } } Fl_Group {} { @@ -808,48 +832,56 @@ else callback type_make_cb tooltip {Input Choice} xywh {400 21 24 24} box THIN_UP_BOX code0 {o->image(pixmap[53]);} + class Widget_Bin_Button } Fl_Button {} { user_data {"menuitem"} callback type_make_cb tooltip {Menu Item} xywh {425 21 24 24} box THIN_UP_BOX code0 {o->image(pixmap[16]);} + class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Menu_Bar"} callback type_make_cb tooltip {Menu Bar} xywh {450 21 24 24} box THIN_UP_BOX code0 {o->image(pixmap[17]);} + class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Menu_Button"} callback type_make_cb tooltip {Menu Button} xywh {400 46 24 24} box THIN_UP_BOX code0 {o->image(pixmap[26]);} + class Widget_Bin_Button } Fl_Button {} { user_data {"checkmenuitem"} callback type_make_cb tooltip {Checkbox Menu Item} xywh {425 46 24 24} box THIN_UP_BOX code0 {o->image(pixmap[54]);} + class Widget_Bin_Button } Fl_Button {} { user_data {"submenu"} callback type_make_cb tooltip {Sub Menu} xywh {450 46 24 24} box THIN_UP_BOX code0 {o->image(pixmap[18]);} + class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Choice"} callback type_make_cb tooltip Choice xywh {400 71 24 24} box THIN_UP_BOX code0 {o->image(pixmap[15]);} + class Widget_Bin_Button } Fl_Button {} { user_data {"radiomenuitem"} callback type_make_cb tooltip {Radio Menu Item} xywh {425 71 24 24} box THIN_UP_BOX code0 {o->image(pixmap[55]);} + class Widget_Bin_Button } } Fl_Group {} { @@ -861,36 +893,42 @@ else callback type_make_cb tooltip Browser xywh {484 21 24 24} box THIN_UP_BOX code0 {o->image(pixmap[31]);} + class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Tree"} callback type_make_cb tooltip Tree xywh {509 21 24 24} box THIN_UP_BOX code0 {o->image(pixmap[50]);} + class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Check_Browser"} callback type_make_cb tooltip {Check Browser} xywh {484 46 24 24} box THIN_UP_BOX code0 {o->image(pixmap[32]);} + class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Help_View"} callback type_make_cb tooltip {Help Browser} xywh {509 46 24 24} box THIN_UP_BOX code0 {o->image(pixmap[35]);} + class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_File_Browser"} callback type_make_cb tooltip {File Browser} xywh {484 71 24 24} box THIN_UP_BOX code0 {o->image(pixmap[33]);} + class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Table"} callback type_make_cb tooltip Table xywh {509 71 24 24} box THIN_UP_BOX code0 {o->image(pixmap[51]);} + class Widget_Bin_Button } } Fl_Group {} { @@ -902,18 +940,21 @@ else callback type_make_cb tooltip Box xywh {542 21 24 24} box THIN_UP_BOX code0 {o->image(pixmap[5]);} + class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Clock"} callback type_make_cb tooltip Clock xywh {567 21 24 24} box THIN_UP_BOX code0 {o->image(pixmap[34]);} + class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Progress"} callback type_make_cb tooltip Progress xywh {542 46 24 24} box THIN_UP_BOX code0 {o->image(pixmap[36]);} + class Widget_Bin_Button } } } diff --git a/fluid/undo.cxx b/fluid/undo.cxx index 38d70c2e1..09f2867d9 100644 --- a/fluid/undo.cxx +++ b/fluid/undo.cxx @@ -19,6 +19,7 @@ #include "fluid.h" #include "file.h" #include "Fl_Type.h" +#include "widget_browser.h" #include #include @@ -107,11 +108,19 @@ void undo_cb(Fl_Widget *, void *) { } undo_suspend(); + // Undo first deletes all widgets which resets the widget_tree browser. + // Save the current scroll position, so we don;t scroll back to 0 at undo. + int x = widget_browser->hposition(); + int y = widget_browser->position(); if (!read_file(undo_filename(undo_current - 1), 0)) { // Unable to read checkpoint file, don't undo... undo_resume(); return; } + // Restore old browser position. + // Ideally, we would save the browser position insied the undo file. + widget_browser->hposition(x); + widget_browser->position(y); undo_current --;