summaryrefslogtreecommitdiff
path: root/fluid/Fl_Menu_Type.h
diff options
context:
space:
mode:
authorMatthias Melcher <github@matthiasm.com>2023-07-19 17:44:44 +0200
committerMatthias Melcher <github@matthiasm.com>2023-07-19 17:45:28 +0200
commitf8a327877699a8565d36b2f0b1cbe074f224fba4 (patch)
tree00673ec9887fa97a108a56910c97df6b37c6ff8c /fluid/Fl_Menu_Type.h
parent9ee8cdc727e7c510c28b51318b953d82aa1dd936 (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.h201
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); }
};