summaryrefslogtreecommitdiff
path: root/fluid
diff options
context:
space:
mode:
Diffstat (limited to 'fluid')
-rw-r--r--fluid/Fl_Menu_Type.cxx124
-rw-r--r--fluid/Fl_Menu_Type.h12
-rw-r--r--fluid/Fl_Type.cxx13
-rw-r--r--fluid/Fl_Widget_Type.cxx11
4 files changed, 148 insertions, 12 deletions
diff --git a/fluid/Fl_Menu_Type.cxx b/fluid/Fl_Menu_Type.cxx
index 6ab652e14..bf88d57eb 100644
--- a/fluid/Fl_Menu_Type.cxx
+++ b/fluid/Fl_Menu_Type.cxx
@@ -290,19 +290,49 @@ void Fl_Menu_Item_Type::write_static(Fd_Code_Writer& f) {
f.write_c("\n");
// Matt: disabled f.tag(FD_TAG_MENU_CALLBACK, get_uid());
f.write_c("}\n");
+
+ // If the menu item is part of a Class or Widget Class, FLUID generates
+ // a dummy static callback which retrieves a pointer to the class and then
+ // calls the original callback from within the class context.
+ // k is the name of the enclosing class (or classes)
if (k) {
+ // Implement the callback as a static member function
f.write_c("void %s::%s(Fl_Menu_* o, %s v) {\n", k, cn, ut);
- f.write_c("%s((%s*)(o", f.indent(1), k);
+ // Find the Fl_Menu_ container for this menu item
Fl_Type* t = parent; while (t->is_a(ID_Menu_Item)) t = t->parent;
- Fl_Type *q = 0;
- // Go up one more level for Fl_Input_Choice, as these are groups themselves
- if (t && t->is_a(ID_Input_Choice))
- f.write_c("->parent()");
- for (t = t->parent; t && t->is_widget() && !is_class(); q = t, t = t->parent)
- f.write_c("->parent()");
- if (!q || !q->is_a(ID_Widget_Class))
- f.write_c("->user_data()");
- f.write_c("))->%s_i(o,v);\n}\n", cn);
+ if (t) {
+ Fl_Widget_Type *tw = (t->is_widget()) ? static_cast<Fl_Widget_Type*>(t) : NULL;
+ Fl_Type *q = NULL;
+ // Generate code to call the callback
+ if (tw->is_a(ID_Menu_Bar) && ((Fl_Menu_Bar_Type*)tw)->is_sys_menu_bar()) {
+ // Fl_Sys_Menu_Bar removes itself from any parent on macOS, so we
+ // wrapped it in a class and remeber the parent class in a new
+ // class memeber variable.
+ Fl_Menu_Bar_Type *tmb = (Fl_Menu_Bar_Type*)tw;
+ f.write_c("%s%s* sys_menu_bar = ((%s*)o);\n", f.indent(1),
+ tmb->sys_menubar_proxy_name(), tmb->sys_menubar_proxy_name());
+ f.write_c("%s%s* parent_class = ((%s*)sys_menu_bar->_parent_class);\n",
+ f.indent(1), k, k);
+ f.write_c("%sparent_class->%s_i(o,v);\n}\n",
+ f.indent(1), cn);
+ } else {
+ f.write_c("%s((%s*)(o", f.indent(1), k);
+ // The class pointer is in the user_data field of the top widget
+ if (t && t->is_a(ID_Input_Choice)) {
+ // Go up one more level for Fl_Input_Choice, as these are groups themselves
+ f.write_c("->parent()");
+ }
+ // Now generate code to find the topmost widget in this class
+ for (t = t->parent; t && t->is_widget() && !is_class(); q = t, t = t->parent)
+ f.write_c("->parent()");
+ // user_data is cast into a pointer to the
+ if (!q || !q->is_a(ID_Widget_Class))
+ f.write_c("->user_data()");
+ f.write_c("))->%s_i(o,v);\n}\n", cn);
+ }
+ } else {
+ f.write_c("#error Enclosing Fl_Menu_* not found\n");
+ }
}
}
if (image) {
@@ -700,10 +730,80 @@ Fl_Type* Fl_Input_Choice_Type::click_test(int, int) {
Fl_Menu_Bar_Type Fl_Menu_Bar_type;
-////////////////////////////////////////////////////////////////
-// Shortcut entry item in panel:
+Fl_Menu_Item menu_bar_type_menu[] = {
+ {"Fl_Menu_Bar",0,0,(void*)0},
+ {"Fl_Sys_Menu_Bar",0,0,(void*)1},
+ {0}};
+Fl_Menu_Bar_Type::Fl_Menu_Bar_Type()
+: _proxy_name(NULL)
+{
+}
+
+Fl_Menu_Bar_Type::~Fl_Menu_Bar_Type() {
+ if (_proxy_name)
+ ::free(_proxy_name);
+}
+
+/**
+ \brief Return true if this is an Fl_Sys_Menu_Bar.
+ This test fails if subclass() is the name of a class that the user may have
+ derived from Fl_Sys_Menu_Bar.
+ */
+bool Fl_Menu_Bar_Type::is_sys_menu_bar() {
+ if (o->type()==1) return true;
+ return ( subclass() && (strcmp(subclass(), "Fl_Sys_Menu_Bar")==0) );
+}
+const char *Fl_Menu_Bar_Type::sys_menubar_name() {
+ if (subclass())
+ return subclass();
+ else
+ return "Fl_Sys_Menu_Bar";
+}
+
+const char *Fl_Menu_Bar_Type::sys_menubar_proxy_name() {
+ if (!_proxy_name)
+ _proxy_name = (char*)::malloc(128);
+ ::snprintf(_proxy_name, 63, "%s_Proxy", sys_menubar_name());
+ return _proxy_name;
+}
+
+
+void Fl_Menu_Bar_Type::write_static(Fd_Code_Writer& f) {
+ super::write_static(f);
+ if (is_sys_menu_bar()) {
+ f.write_h_once("#include <FL/Fl_Sys_Menu_Bar.H>");
+ if (is_in_class()) {
+ // Make room for a pointer to the enclosing class.
+ f.write_c_once( // must be less than 1024 bytes!
+ "\nclass %s: public %s {\n"
+ "public:\n"
+ " %s(int x, int y, int w, int h, const char *l=NULL)\n"
+ " : %s(x, y, w, h, l) { }\n"
+ " void *_parent_class;\n"
+ "};\n",
+ sys_menubar_proxy_name(), sys_menubar_name(),
+ sys_menubar_proxy_name(), sys_menubar_name()
+ );
+ }
+ }
+}
+
+void Fl_Menu_Bar_Type::write_code1(Fd_Code_Writer& f) {
+ super::write_code1(f);
+ if (is_sys_menu_bar() && is_in_class()) {
+ f.write_c("%s((%s*)%s)->_parent_class = (void*)this;\n",
+ f.indent(), sys_menubar_proxy_name(), name() ? name() : "o");
+ }
+}
+
+//void Fl_Menu_Bar_Type::write_code2(Fd_Code_Writer& f) {
+// super::write_code2(f);
+//}
+
+////////////////////////////////////////////////////////////////
+// Shortcut entry item in panel:
void shortcut_in_cb(Fl_Shortcut_Button* i, void* v) {
if (v == LOAD) {
if (current_widget->is_button())
diff --git a/fluid/Fl_Menu_Type.h b/fluid/Fl_Menu_Type.h
index 3824270a6..13c1573ec 100644
--- a/fluid/Fl_Menu_Type.h
+++ b/fluid/Fl_Menu_Type.h
@@ -35,6 +35,7 @@
extern Fl_Menu_Item dummymenu[];
extern Fl_Menu_Item button_type_menu[];
extern Fl_Menu_Item menu_item_type_menu[];
+extern Fl_Menu_Item menu_bar_type_menu[];
/**
\brief Manage all types on menu items.
@@ -261,13 +262,24 @@ public:
class Fl_Menu_Bar_Type : public Fl_Menu_Base_Type
{
typedef Fl_Menu_Base_Type super;
+ Fl_Menu_Item *subtypes() FL_OVERRIDE {return menu_bar_type_menu;}
public:
+ Fl_Menu_Bar_Type();
+ ~Fl_Menu_Bar_Type() FL_OVERRIDE;
const char *type_name() FL_OVERRIDE {return "Fl_Menu_Bar";}
const char *alt_type_name() FL_OVERRIDE {return "fltk::MenuBar";}
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();}
+ void write_static(Fd_Code_Writer& f) FL_OVERRIDE;
+ 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_Bar; }
bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Menu_Bar) ? true : super::is_a(inID); }
+ bool is_sys_menu_bar();
+ const char *sys_menubar_name();
+ const char *sys_menubar_proxy_name();
+protected:
+ char *_proxy_name;
};
diff --git a/fluid/Fl_Type.cxx b/fluid/Fl_Type.cxx
index 1654bfd20..a9e2bcb4b 100644
--- a/fluid/Fl_Type.cxx
+++ b/fluid/Fl_Type.cxx
@@ -1006,6 +1006,19 @@ const char *Fl_Type::callback_name(Fd_Code_Writer& f) {
return f.unique_id(this, "cb", name(), label());
}
+/**
+ \brief Return the class name if this type is inside a Class or Widget Class.
+
+ This methods traverses up the hirarchy to find out if this Type is located
+ inside a Class or Widget Class. It then return the name of that class. If
+ need_nest is set, class_name searches all the way up the tree and concatenates
+ the names of classes within classes, separated by a "::".
+
+ \param need_nest if clear, search up one level to the first enclosing class.
+ If set, recurse all the way up to the top node.
+ \return the name of the enclosing class, or names of the enclosing classes
+ in a static buffe (don't call free), or NULL if this Type is not inside a class
+ */
const char* Fl_Type::class_name(const int need_nest) const {
Fl_Type* p = parent;
while (p) {
diff --git a/fluid/Fl_Widget_Type.cxx b/fluid/Fl_Widget_Type.cxx
index 5864b6ab6..160234aa4 100644
--- a/fluid/Fl_Widget_Type.cxx
+++ b/fluid/Fl_Widget_Type.cxx
@@ -54,6 +54,11 @@ int Fl_Widget_Type::is_widget() const {return 1;}
int Fl_Widget_Type::is_public() const {return public_;}
const char* subclassname(Fl_Type* l) {
+ if (l->is_a(ID_Menu_Bar)) {
+ Fl_Menu_Bar_Type *mb = static_cast<Fl_Menu_Bar_Type*>(l);
+ if (mb->is_sys_menu_bar())
+ return mb->sys_menubar_name();
+ }
if (l->is_widget()) {
Fl_Widget_Type* p = (Fl_Widget_Type*)l;
const char* c = p->subclass();
@@ -2991,6 +2996,12 @@ void Fl_Widget_Type::write_code1(Fd_Code_Writer& f) {
f.write_c("new %s(0, 0, %d, %d", t, o->w(), o->h());
else
f.write_c("new %s(%d, %d", t, o->w(), o->h());
+ } else if (is_a(ID_Menu_Bar)
+ && ((Fl_Menu_Bar_Type*)this)->is_sys_menu_bar()
+ && is_in_class()) {
+ f.write_c("(%s*)new %s(%d, %d, %d, %d",
+ t, ((Fl_Menu_Bar_Type*)this)->sys_menubar_proxy_name(),
+ o->x(), o->y(), o->w(), o->h());
} else {
f.write_c("new %s(%d, %d, %d, %d", t, o->x(), o->y(), o->w(), o->h());
}