diff options
| author | Matthias Melcher <github@matthiasm.com> | 2023-07-19 17:44:44 +0200 |
|---|---|---|
| committer | Matthias Melcher <github@matthiasm.com> | 2023-07-19 17:45:28 +0200 |
| commit | f8a327877699a8565d36b2f0b1cbe074f224fba4 (patch) | |
| tree | 00673ec9887fa97a108a56910c97df6b37c6ff8c /fluid/Fl_Menu_Type.h | |
| parent | 9ee8cdc727e7c510c28b51318b953d82aa1dd936 (diff) | |
FLUID: emulated RTTI for all types
Complete type hierarchy in Fl_Types doc
Window now derives correctly from Group
Menu Items now correctly (functionally in FLUID) derived form Button
Menu Buttons have a better hierarchy
Fixing two possible crash bugs where Input_Choice was assumed to be a Menu_
Hoping I have not degraded the original code!
Diffstat (limited to 'fluid/Fl_Menu_Type.h')
| -rw-r--r-- | fluid/Fl_Menu_Type.h | 201 |
1 files changed, 144 insertions, 57 deletions
diff --git a/fluid/Fl_Menu_Type.h b/fluid/Fl_Menu_Type.h index 69de6bfaa..f6238930b 100644 --- a/fluid/Fl_Menu_Type.h +++ b/fluid/Fl_Menu_Type.h @@ -21,17 +21,28 @@ #ifndef _FLUID_FL_MENU_TYPE_H #define _FLUID_FL_MENU_TYPE_H -#include "Fl_Widget_Type.h" +#include "Fl_Button_Type.h" +#include <FL/Fl_Choice.H> #include <FL/Fl_Menu_.H> #include <FL/Fl_Menu_Button.H> #include <FL/Fl_Input_Choice.H> #include <FL/Fl_Window.H> #include <FL/Fl_Menu_Bar.H> +extern Fl_Menu_Item dummymenu[]; +extern Fl_Menu_Item button_type_menu[]; extern Fl_Menu_Item menu_item_type_menu[]; -class Fl_Menu_Item_Type : public Fl_Widget_Type { // FIXME: hmmmmm +/** + \brief Manage all types on menu items. + Deriving Fl_Menu_Item_Type from Fl_Button_Type is intentional. For the purpose + of editing, a Menu Item is implemented with `o` pointing to an Fl_Button for + holding all properties. + */ +class Fl_Menu_Item_Type : public Fl_Button_Type +{ + typedef Fl_Button_Type super; public: Fl_Menu_Item* subtypes() FL_OVERRIDE {return menu_item_type_menu;} const char* type_name() FL_OVERRIDE {return "MenuItem";} @@ -48,23 +59,45 @@ public: void write_code1(Fd_Code_Writer& f) FL_OVERRIDE; void write_code2(Fd_Code_Writer& f) FL_OVERRIDE; ID id() const FL_OVERRIDE { return ID_Menu_Item; } + bool is_a(ID inID) FL_OVERRIDE { return (inID==ID_Menu_Item) ? true : super::is_a(inID); } }; -class Fl_Radio_Menu_Item_Type : public Fl_Menu_Item_Type { +/** + \brief Manage Radio style Menu Items. + */ +class Fl_Radio_Menu_Item_Type : public Fl_Menu_Item_Type +{ + typedef Fl_Menu_Item_Type super; public: const char* type_name() FL_OVERRIDE {return "RadioMenuItem";} Fl_Type* make(Strategy strategy) FL_OVERRIDE; ID id() const FL_OVERRIDE { return ID_Radio_Menu_Item; } + bool is_a(ID inID) FL_OVERRIDE { return (inID==ID_Radio_Menu_Item) ? true : super::is_a(inID); } }; -class Fl_Checkbox_Menu_Item_Type : public Fl_Menu_Item_Type { +/** + \brief Manage Checkbox style Menu Items. + */ +class Fl_Checkbox_Menu_Item_Type : public Fl_Menu_Item_Type +{ + typedef Fl_Menu_Item_Type super; public: const char* type_name() FL_OVERRIDE {return "CheckMenuItem";} Fl_Type* make(Strategy strategy) FL_OVERRIDE; ID id() const FL_OVERRIDE { return ID_Checkbox_Menu_Item; } + bool is_a(ID inID) FL_OVERRIDE { return (inID==ID_Checkbox_Menu_Item) ? true : super::is_a(inID); } }; -class Fl_Submenu_Type : public Fl_Menu_Item_Type { +/** + \brief Manage Submenu style Menu Items. + Submenu Items are simply buttons just like all other menu items, but they + can also hold a pointer to a list of submenus, or have a flag set that + allows submenus to follow in the current array. As buttons, they can + be clicked by the user, and they will call their callback, if one is set. + */ +class Fl_Submenu_Type : public Fl_Menu_Item_Type +{ + typedef Fl_Menu_Item_Type super; public: Fl_Menu_Item* subtypes() FL_OVERRIDE {return 0;} const char* type_name() FL_OVERRIDE {return "Submenu";} @@ -78,9 +111,90 @@ public: void move_child(Fl_Type*a, Fl_Type*b) FL_OVERRIDE {parent->move_child(a,b);} void remove_child(Fl_Type*a) FL_OVERRIDE {parent->remove_child(a);} ID id() const FL_OVERRIDE { return ID_Submenu; } + bool is_a(ID inID) FL_OVERRIDE { return (inID==ID_Submenu) ? true : super::is_a(inID); } +}; + +// ----------------------------------------------------------------------------- + +/** + \brief Base class for all widgets that can have a pulldown menu attached. + Widgets with this type can be derived from Fl_Menu_ or from + Fl_Group (Fl_Input_Choice). + */ +class Fl_Menu_Manager_Type : public Fl_Widget_Type +{ + typedef Fl_Widget_Type super; +public: + int is_parent() const FL_OVERRIDE {return 1;} + int menusize; + virtual void build_menu() = 0; + Fl_Menu_Manager_Type() : Fl_Widget_Type() {menusize = 0;} + void add_child(Fl_Type*, Fl_Type*) FL_OVERRIDE { build_menu(); } + void move_child(Fl_Type*, Fl_Type*) FL_OVERRIDE { build_menu(); } + void remove_child(Fl_Type*) FL_OVERRIDE { build_menu();} + Fl_Type* click_test(int x, int y) FL_OVERRIDE = 0; + void write_code2(Fd_Code_Writer& f) FL_OVERRIDE; + void copy_properties() FL_OVERRIDE = 0; + ID id() const FL_OVERRIDE { return ID_Menu_Manager_; } + bool is_a(ID inID) FL_OVERRIDE { return (inID==ID_Menu_Manager_) ? true : super::is_a(inID); } }; -class Fl_Menu_Type : public Fl_Widget_Type { +/** + \brief Manage the composite widget Input Choice. + \note Input Choice is a composite window, so `o` will be pointing to a widget + derived from Fl_Group. All menu related methods from Fl_Menu_Trait_Type must + be virtual and must be reimplemented here (click_test, build_menu, textstuff). + */ +class Fl_Input_Choice_Type : public Fl_Menu_Manager_Type +{ + typedef Fl_Menu_Manager_Type super; + int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) FL_OVERRIDE { + Fl_Input_Choice *myo = (Fl_Input_Choice*)(w==4 ? ((Fl_Widget_Type*)this->factory)->o : this->o); + switch (w) { + case 4: + case 0: f = (Fl_Font)myo->textfont(); s = myo->textsize(); c = myo->textcolor(); break; + case 1: myo->textfont(f); break; + case 2: myo->textsize(s); break; + case 3: myo->textcolor(c); break; + } + return 1; + } +public: + void ideal_size(int &w, int &h) FL_OVERRIDE { + Fl_Input_Choice *myo = (Fl_Input_Choice *)o; + fl_font(myo->textfont(), myo->textsize()); + h = fl_height() + myo->textsize() - 6; + w = o->w() - 20 - Fl::box_dw(o->box()); + int ww = (int)fl_width('m'); + w = ((w + ww - 1) / ww) * ww + 20 + Fl::box_dw(o->box()); + if (h < 15) h = 15; + if (w < (15 + h)) w = 15 + h; + } + ~Fl_Input_Choice_Type() { + if (menusize) delete[] (Fl_Menu_Item*)(((Fl_Input_Choice*)o)->menu()); + } + const char *type_name() FL_OVERRIDE {return "Fl_Input_Choice";} + const char *alt_type_name() FL_OVERRIDE {return "fltk::ComboBox";} + Fl_Type* click_test(int,int) FL_OVERRIDE; + Fl_Widget *widget(int X,int Y,int W,int H) FL_OVERRIDE { + Fl_Input_Choice *myo = new Fl_Input_Choice(X,Y,W,H,"input choice:"); + myo->menu(dummymenu); + myo->value("input"); + return myo; + } + Fl_Widget_Type *_make() FL_OVERRIDE {return new Fl_Input_Choice_Type();} + void build_menu() FL_OVERRIDE; + ID id() const FL_OVERRIDE { return ID_Input_Choice; } + bool is_a(ID inID) FL_OVERRIDE { return (inID==ID_Input_Choice) ? true : super::is_a(inID); } + void copy_properties() FL_OVERRIDE; +}; + +/** + \brief Base class to handle widgets that are derived from Fl_Menu_. + */ +class Fl_Menu_Base_Type : public Fl_Menu_Manager_Type +{ + typedef Fl_Menu_Manager_Type super; int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) FL_OVERRIDE { Fl_Menu_ *myo = (Fl_Menu_*)(w==4 ? ((Fl_Widget_Type*)this->factory)->o : this->o); switch (w) { @@ -93,26 +207,25 @@ class Fl_Menu_Type : public Fl_Widget_Type { return 1; } public: - int is_menu_button() const FL_OVERRIDE {return 1;} int is_parent() const FL_OVERRIDE {return 1;} - int menusize; - virtual void build_menu(); - Fl_Menu_Type() : Fl_Widget_Type() {menusize = 0;} - ~Fl_Menu_Type() { + void build_menu() FL_OVERRIDE; + ~Fl_Menu_Base_Type() { if (menusize) delete[] (Fl_Menu_Item*)(((Fl_Menu_*)o)->menu()); } - void add_child(Fl_Type*, Fl_Type*) FL_OVERRIDE {build_menu();} - void move_child(Fl_Type*, Fl_Type*) FL_OVERRIDE {build_menu();} - void remove_child(Fl_Type*) FL_OVERRIDE {build_menu();} Fl_Type* click_test(int x, int y) FL_OVERRIDE; - void write_code2(Fd_Code_Writer& f) FL_OVERRIDE; void copy_properties() FL_OVERRIDE; ID id() const FL_OVERRIDE { return ID_Menu_; } + bool is_a(ID inID) FL_OVERRIDE { return (inID==ID_Menu_) ? true : super::is_a(inID); } }; extern Fl_Menu_Item button_type_menu[]; -class Fl_Menu_Button_Type : public Fl_Menu_Type { +/** + \brief Makae Menu Button widgets. + */ +class Fl_Menu_Button_Type : public Fl_Menu_Base_Type +{ + typedef Fl_Menu_Base_Type super; Fl_Menu_Item *subtypes() FL_OVERRIDE {return button_type_menu;} public: void ideal_size(int &w, int &h) FL_OVERRIDE { @@ -128,12 +241,16 @@ public: return new Fl_Menu_Button(X,Y,W,H,"menu");} Fl_Widget_Type *_make() FL_OVERRIDE {return new Fl_Menu_Button_Type();} ID id() const FL_OVERRIDE { return ID_Menu_Button; } + bool is_a(ID inID) FL_OVERRIDE { return (inID==ID_Menu_Button) ? true : super::is_a(inID); } }; -extern Fl_Menu_Item dummymenu[]; -#include <FL/Fl_Choice.H> -class Fl_Choice_Type : public Fl_Menu_Type { +/** + \brief Manage Choice type menu widgets. + */ +class Fl_Choice_Type : public Fl_Menu_Base_Type +{ + typedef Fl_Menu_Base_Type super; public: void ideal_size(int &w, int &h) FL_OVERRIDE { Fl_Widget_Type::ideal_size(w, h); @@ -155,47 +272,16 @@ public: } Fl_Widget_Type *_make() FL_OVERRIDE {return new Fl_Choice_Type();} ID id() const FL_OVERRIDE { return ID_Choice; } + bool is_a(ID inID) FL_OVERRIDE { return (inID==ID_Choice) ? true : super::is_a(inID); } }; -class Fl_Input_Choice_Type : public Fl_Menu_Type { // FIXME: Composite: Fl_Group - int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) FL_OVERRIDE { - Fl_Input_Choice *myo = (Fl_Input_Choice*)(w==4 ? ((Fl_Widget_Type*)this->factory)->o : this->o); - switch (w) { - case 4: - case 0: f = (Fl_Font)myo->textfont(); s = myo->textsize(); c = myo->textcolor(); break; - case 1: myo->textfont(f); break; - case 2: myo->textsize(s); break; - case 3: myo->textcolor(c); break; - } - return 1; - } -public: - void ideal_size(int &w, int &h) FL_OVERRIDE { - Fl_Input_Choice *myo = (Fl_Input_Choice *)o; - fl_font(myo->textfont(), myo->textsize()); - h = fl_height() + myo->textsize() - 6; - w = o->w() - 20 - Fl::box_dw(o->box()); - int ww = (int)fl_width('m'); - w = ((w + ww - 1) / ww) * ww + 20 + Fl::box_dw(o->box()); - if (h < 15) h = 15; - if (w < (15 + h)) w = 15 + h; - } - const char *type_name() FL_OVERRIDE {return "Fl_Input_Choice";} - const char *alt_type_name() FL_OVERRIDE {return "fltk::ComboBox";} - Fl_Type* click_test(int,int) FL_OVERRIDE; - Fl_Widget *widget(int X,int Y,int W,int H) FL_OVERRIDE { - Fl_Input_Choice *myo = new Fl_Input_Choice(X,Y,W,H,"input choice:"); - myo->menu(dummymenu); - myo->value("input"); - return myo; - } - Fl_Widget_Type *_make() FL_OVERRIDE {return new Fl_Input_Choice_Type();} - void build_menu() FL_OVERRIDE; - ID id() const FL_OVERRIDE { return ID_Input_Choice; } - void copy_properties() FL_OVERRIDE; -}; -class Fl_Menu_Bar_Type : public Fl_Menu_Type { +/** + \brief Manage Menubar widgets. + */ +class Fl_Menu_Bar_Type : public Fl_Menu_Base_Type +{ + typedef Fl_Menu_Base_Type super; public: void ideal_size(int &w, int &h) FL_OVERRIDE { w = o->window()->w(); @@ -207,6 +293,7 @@ public: Fl_Widget *widget(int X,int Y,int W,int H) FL_OVERRIDE {return new Fl_Menu_Bar(X,Y,W,H);} Fl_Widget_Type *_make() FL_OVERRIDE {return new Fl_Menu_Bar_Type();} ID id() const FL_OVERRIDE { return ID_Menu_Bar; } + bool is_a(ID inID) FL_OVERRIDE { return (inID==ID_Menu_Bar) ? true : super::is_a(inID); } }; |
