diff options
| author | Matthias Melcher <github@matthiasm.com> | 2025-03-16 17:16:12 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-03-16 17:16:12 -0400 |
| commit | 51a55bc73660f64e8f4b32b8b4d3858f2a786f7b (patch) | |
| tree | 122ad9f838fcf8f61ed7cf5fa031e8ed69817e10 /fluid/nodes/Menu_Node.h | |
| parent | 13a7073a1e007ce5b71ef70bced1a9b15158820d (diff) | |
Fluid: restructuring and rejuvenation of the source code.
* Add classes for application and project
* Removed all globals from Fluid.h
* Extracting args and project history into their own classes
* Moving globals into Application class
* Initialize values inside headers for some classes.
* Undo functionality wrapped in a class inside Project.
* File reader and writer are now linked to a project.
* Avoid global project access
* Nodes (former Types) will be managed by a new Tree class.
* Removed static members (hidden globals) form Node/Fl_Type.
* Adding Tree iterator.
* Use nullptr instead of 0, NULL, or 0L
* Renamed Fl_..._Type to ..._Node, FL_OVERRIDE -> override
* Renaming ..._type to ...::prototype
* Splitting Widget Panel into multiple files.
* Moved callback code into widget panel file.
* Cleaning up Fluid_Image -> Image_asset
* Moving Fd_Snap_Action into new namespace fld::app::Snap_Action etc.
* Moved mergeback into proj folder.
* `enum ID` is now `enum class Type`.
Diffstat (limited to 'fluid/nodes/Menu_Node.h')
| -rw-r--r-- | fluid/nodes/Menu_Node.h | 310 |
1 files changed, 310 insertions, 0 deletions
diff --git a/fluid/nodes/Menu_Node.h b/fluid/nodes/Menu_Node.h new file mode 100644 index 000000000..59d3b06bb --- /dev/null +++ b/fluid/nodes/Menu_Node.h @@ -0,0 +1,310 @@ +// +// Menu Node header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2025 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 +// + +// Type for creating all subclasses of Fl_Widget +// This should have the widget pointer in it, but it is still in the +// Node base class. +// + + +#ifndef FLUID_NODES_MENU_NODE_H +#define FLUID_NODES_MENU_NODE_H + +#include "nodes/Button_Node.h" + +#include "Fluid.h" +#include "app/Snap_Action.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[]; +extern Fl_Menu_Item menu_bar_type_menu[]; + +/** + \brief Manage all types on menu items. + Deriving Menu_Item_Node from Button_Node is intentional. For the purpose + of editing, a Menu Item is implemented with `o` pointing to an Fl_Button for + holding all properties. + */ +class Menu_Item_Node : public Button_Node +{ +public: + typedef Button_Node super; + static Menu_Item_Node prototype; +public: + Fl_Menu_Item* subtypes() override {return menu_item_type_menu;} + const char* type_name() override {return "MenuItem";} + const char* alt_type_name() override {return "fltk::Item";} + Node* make(Strategy strategy) override; + Node* make(int flags, Strategy strategy); + int is_button() const override {return 1;} // this gets shortcut to work + Fl_Widget* widget(int,int,int,int) override {return nullptr;} + Widget_Node* _make() override {return nullptr;} + virtual const char* menu_name(fld::io::Code_Writer& f, int& i); + int flags(); + void write_static(fld::io::Code_Writer& f) override; + void write_item(fld::io::Code_Writer& f); + void write_code1(fld::io::Code_Writer& f) override; + void write_code2(fld::io::Code_Writer& f) override; + int is_true_widget() const override { return 0; } + Type type() const override { return Type::Menu_Item; } + bool is_a(Type inType) const override { return (inType==Type::Menu_Item) ? true : super::is_a(inType); } +}; + +/** + \brief Manage Radio style Menu Items. + */ +class Radio_Menu_Item_Node : public Menu_Item_Node +{ +public: + typedef Menu_Item_Node super; + static Radio_Menu_Item_Node prototype; +public: + const char* type_name() override {return "RadioMenuItem";} + Node* make(Strategy strategy) override; + Type type() const override { return Type::Radio_Menu_Item; } + bool is_a(Type inType) const override { return (inType==Type::Radio_Menu_Item) ? true : super::is_a(inType); } +}; + +/** + \brief Manage Checkbox style Menu Items. + */ +class Checkbox_Menu_Item_Node : public Menu_Item_Node +{ +public: + typedef Menu_Item_Node super; + static Checkbox_Menu_Item_Node prototype; +public: + const char* type_name() override {return "CheckMenuItem";} + Node* make(Strategy strategy) override; + Type type() const override { return Type::Checkbox_Menu_Item; } + bool is_a(Type inType) const override { return (inType==Type::Checkbox_Menu_Item) ? true : super::is_a(inType); } +}; + +/** + \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 Submenu_Node : public Menu_Item_Node +{ +public: + typedef Menu_Item_Node super; + static Submenu_Node prototype; +public: + Fl_Menu_Item* subtypes() override {return nullptr;} + const char* type_name() override {return "Submenu";} + const char* alt_type_name() override {return "fltk::ItemGroup";} + int can_have_children() const override {return 1;} + int is_button() const override {return 0;} // disable shortcut + Node* make(Strategy strategy) override; + // changes to submenu must propagate up so build_menu is called + // on the parent Menu_Node: + void add_child(Node*a, Node*b) override {parent->add_child(a,b);} + void move_child(Node*a, Node*b) override {parent->move_child(a,b);} + void remove_child(Node*a) override {parent->remove_child(a);} + Type type() const override { return Type::Submenu; } + bool is_a(Type inType) const override { return (inType==Type::Submenu) ? true : super::is_a(inType); } +}; + +// ----------------------------------------------------------------------------- + +/** + \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 Menu_Manager_Node : public Widget_Node +{ + typedef Widget_Node super; +public: + void ideal_size(int &w, int &h) override { + auto layout = Fluid.proj.layout; + h = layout->textsize_not_null() + 8; + w = layout->textsize_not_null() * 6 + 8; + fld::app::Snap_Action::better_size(w, h); + } + int can_have_children() const override {return 1;} + int menusize; + virtual void build_menu() = 0; + Menu_Manager_Node() : Widget_Node() {menusize = 0;} + void add_child(Node*, Node*) override { build_menu(); } + void move_child(Node*, Node*) override { build_menu(); } + void remove_child(Node*) override { build_menu();} + Node* click_test(int x, int y) override = 0; + void write_code2(fld::io::Code_Writer& f) override; + void copy_properties() override = 0; + Type type() const override { return Type::Menu_Manager_; } + bool is_a(Type inType) const override { return (inType==Type::Menu_Manager_) ? true : super::is_a(inType); } +}; + +/** + \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 Input_Choice_Node : public Menu_Manager_Node +{ +public: + typedef Menu_Manager_Node super; + static Input_Choice_Node prototype; +private: + int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) override { + Fl_Input_Choice *myo = (Fl_Input_Choice*)(w==4 ? ((Widget_Node*)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: + ~Input_Choice_Node() { + if (menusize) delete[] (Fl_Menu_Item*)(((Fl_Input_Choice*)o)->menu()); + } + const char *type_name() override {return "Fl_Input_Choice";} + const char *alt_type_name() override {return "fltk::ComboBox";} + Node* click_test(int,int) override; + Fl_Widget *widget(int X,int Y,int W,int H) override { + Fl_Input_Choice *myo = new Fl_Input_Choice(X,Y,W,H,"input choice:"); + myo->menu(dummymenu); + myo->value("input"); + return myo; + } + Widget_Node *_make() override {return new Input_Choice_Node();} + void build_menu() override; + Type type() const override { return Type::Input_Choice; } + bool is_a(Type inType) const override { return (inType==Type::Input_Choice) ? true : super::is_a(inType); } + void copy_properties() override; +}; + +/** + \brief Base class to handle widgets that are derived from Fl_Menu_. + */ +class Menu_Base_Node : public Menu_Manager_Node +{ + typedef Menu_Manager_Node super; + int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) override { + Fl_Menu_ *myo = (Fl_Menu_*)(w==4 ? ((Widget_Node*)this->factory)->o : this->o); + switch (w) { + case 4: + case 0: f = 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: + int can_have_children() const override {return 1;} + void build_menu() override; + ~Menu_Base_Node() { + if (menusize) delete[] (Fl_Menu_Item*)(((Fl_Menu_*)o)->menu()); + } + Node* click_test(int x, int y) override; + void copy_properties() override; + Type type() const override { return Type::Menu_; } + bool is_a(Type inType) const override { return (inType==Type::Menu_) ? true : super::is_a(inType); } +}; + +extern Fl_Menu_Item button_type_menu[]; + +/** + \brief Make Menu Button widgets. + */ +class Menu_Button_Node : public Menu_Base_Node +{ +public: + typedef Menu_Base_Node super; + static Menu_Button_Node prototype; +private: + Fl_Menu_Item *subtypes() override {return button_type_menu;} +public: + const char *type_name() override {return "Fl_Menu_Button";} + const char *alt_type_name() override {return "fltk::MenuButton";} + Fl_Widget *widget(int X,int Y,int W,int H) override { + return new Fl_Menu_Button(X,Y,W,H,"menu");} + Widget_Node *_make() override {return new Menu_Button_Node();} + Type type() const override { return Type::Menu_Button; } + bool is_a(Type inType) const override { return (inType==Type::Menu_Button) ? true : super::is_a(inType); } +}; + + +/** + \brief Manage Choice type menu widgets. + */ +class Choice_Node : public Menu_Base_Node +{ +public: + typedef Menu_Base_Node super; + static Choice_Node prototype; +public: + const char *type_name() override {return "Fl_Choice";} + const char *alt_type_name() override {return "fltk::Choice";} + Fl_Widget *widget(int X,int Y,int W,int H) override { + Fl_Choice *myo = new Fl_Choice(X,Y,W,H,"choice:"); + myo->menu(dummymenu); + return myo; + } + Widget_Node *_make() override {return new Choice_Node();} + Type type() const override { return Type::Choice; } + bool is_a(Type inType) const override { return (inType==Type::Choice) ? true : super::is_a(inType); } +}; + + +/** + \brief Manage Menubar widgets. + */ +class Menu_Bar_Node : public Menu_Base_Node +{ +public: + typedef Menu_Base_Node super; + static Menu_Bar_Node prototype; +private: + Fl_Menu_Item *subtypes() override {return menu_bar_type_menu;} +public: + Menu_Bar_Node(); + ~Menu_Bar_Node() override; + const char *type_name() override {return "Fl_Menu_Bar";} + const char *alt_type_name() override {return "fltk::MenuBar";} + Fl_Widget *widget(int X,int Y,int W,int H) override {return new Fl_Menu_Bar(X,Y,W,H);} + Widget_Node *_make() override {return new Menu_Bar_Node();} + void write_static(fld::io::Code_Writer& f) override; + void write_code1(fld::io::Code_Writer& f) override; +// void write_code2(fld::io::Code_Writer& f) override; + Type type() const override { return Type::Menu_Bar; } + bool is_a(Type inType) const override { return (inType==Type::Menu_Bar) ? true : super::is_a(inType); } + bool is_sys_menu_bar(); + const char *sys_menubar_name(); + const char *sys_menubar_proxy_name(); +protected: + char *_proxy_name; +}; + + +#endif // FLUID_NODES_MENU_NODE_H |
