X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fnetradiant.git;a=blobdiff_plain;f=libs%2Fuilib%2Fuilib.h;h=b4d315c96327dc72d0b0bf0d6638e4b8dd40595e;hp=f3f490c3ba7ec22f7a92b6bd25ba335c35bf05e2;hb=f92114c3f8baaedf9e0a4ff21141e9349d838f5c;hpb=2c07c3a2aaa0b9b16a8fcd50259ebbf28d9f9dc9 diff --git a/libs/uilib/uilib.h b/libs/uilib/uilib.h index f3f490c3..b4d315c9 100644 --- a/libs/uilib/uilib.h +++ b/libs/uilib/uilib.h @@ -2,50 +2,89 @@ #define INCLUDED_UILIB_H #include +#include + +struct _GdkEventKey; +struct _GtkAccelGroup; +struct _GtkAdjustment; +struct _GtkAlignment; +struct _GtkBin; +struct _GtkBox; +struct _GtkButton; +struct _GtkCellEditable; +struct _GtkCellRenderer; +struct _GtkCellRendererText; +struct _GtkCheckButton; +struct _GtkCheckMenuItem; +struct _GtkComboBox; +struct _GtkComboBoxText; +struct _GtkContainer; +struct _GtkDialog; +struct _GtkEditable; +struct _GtkEntry; +struct _GtkEntryCompletion; +struct _GtkFrame; +struct _GtkHBox; +struct _GtkHPaned; +struct _GtkHScale; +struct _GtkImage; +struct _GtkItem; +struct _GtkLabel; +struct _GtkListStore; +struct _GtkTreeIter; +struct _GtkMenu; +struct _GtkMenuBar; +struct _GtkMenuItem; +struct _GtkMenuShell; +struct _GtkMisc; +struct _GtkObject; +struct _GtkPaned; +struct _GtkRadioButton; +struct _GtkRadioMenuItem; +struct _GtkRadioToolButton; +struct _GtkRange; +struct _GtkScale; +struct _GtkScrolledWindow; +struct _GtkSpinButton; +struct _GtkTable; +struct _GtkTearoffMenuItem; +struct _GtkTextView; +struct _GtkToggleButton; +struct _GtkToggleToolButton; +struct _GtkToolbar; +struct _GtkToolButton; +struct _GtkToolItem; +struct _GtkTreeModel; +struct _GtkTreePath; +struct _GtkTreeSelection; +struct _GtkTreeView; +struct _GtkTreeViewColumn; +struct _GtkVBox; +struct _GtkVPaned; +struct _GtkWidget; +struct _GtkWindow; +struct _GTypeInstance; + +#if GTK_TARGET == 3 +struct _GtkGLArea; +#endif + +#if GTK_TARGET == 2 +using _GtkGLArea = struct _GtkDrawingArea; +#endif -using ui_accelgroup = struct _GtkAccelGroup; -using ui_adjustment = struct _GtkAdjustment; -using ui_alignment = struct _GtkAlignment; -using ui_box = struct _GtkBox; -using ui_button = struct _GtkButton; -using ui_checkbutton = struct _GtkCheckButton; -using ui_combobox = struct _GtkComboBox; -using ui_comboboxtext = struct _GtkComboBoxText; -using ui_cellrenderer = struct _GtkCellRenderer; -using ui_cellrenderertext = struct _GtkCellRendererText; -using ui_entry = struct _GtkEntry; -using ui_evkey = struct _GdkEventKey; -using ui_frame = struct _GtkFrame; -using ui_hbox = struct _GtkHBox; -using ui_hscale = struct _GtkHScale; -using ui_hpaned = struct _GtkHPaned; -using ui_image = struct _GtkImage; -using ui_label = struct _GtkLabel; -using ui_menu = struct _GtkMenu; -using ui_menuitem = struct _GtkMenuItem; -using ui_modal = struct ModalDialog; -using ui_object = struct _GtkObject; -using ui_paned = struct _GtkPaned; -using ui_scrolledwindow = struct _GtkScrolledWindow; -using ui_spinbutton = struct _GtkSpinButton; -using ui_table = struct _GtkTable; -using ui_textview = struct _GtkTextView; -using ui_treemodel = struct _GtkTreeModel; -using ui_treepath = struct _GtkTreePath; -using ui_treeview = struct _GtkTreeView; -using ui_treeviewcolumn = struct _GtkTreeViewColumn; -using ui_typeinst = struct _GTypeInstance; -using ui_vbox = struct _GtkVBox; -using ui_vpaned = struct _GtkVPaned; -using ui_widget = struct _GtkWidget; -using ui_window = struct _GtkWindow; +struct ModalDialog; namespace ui { - void init(int argc, char *argv[]); + bool init(int *argc, char **argv[], char const *parameter_string, char const **error); void main(); + void process(); + + extern class Widget root; + enum class alert_type { OK, OKCANCEL, @@ -74,211 +113,493 @@ namespace ui { POPUP }; - template - struct Convertible; - - template - struct Convertible { - operator T *() const - { return reinterpret_cast(static_cast(this)->_handle); } + enum class Shadow { + NONE, + IN, + OUT, + ETCHED_IN, + ETCHED_OUT }; - template - struct Convertible { - explicit operator T *() const - { return reinterpret_cast(static_cast(this)->_handle); } + enum class Policy { + ALWAYS, + AUTOMATIC, + NEVER }; - class Object : public Convertible { + namespace details { + + enum class Convert { + Implicit, Explicit + }; + + template + struct Convertible; + + template + struct Convertible { + operator T() const + { return reinterpret_cast(static_cast(this)->_handle); } + }; + + template + struct Convertible { + explicit operator T() const + { return reinterpret_cast(static_cast(this)->_handle); } + }; + + template + struct All : T ... { + All() + {}; + }; + + template + struct Mixin; + template + struct Mixin { + using type = All; + }; + template + struct Mixin { + using type = All; + }; + } + + extern struct Null {} null; + extern struct New_t {} New; + + class Object : + public details::Convertible, + public details::Convertible { public: - using native = ui_object; - void *_handle; + using self = Object *; + using native = _GtkObject *; + native _handle; - Object(void *h) : _handle(h) - { } + explicit Object(native h) : _handle(h) + {} explicit operator bool() const { return _handle != nullptr; } - explicit operator ui_typeinst *() const - { return (ui_typeinst *) _handle; } - explicit operator void *() const { return _handle; } - }; - - static_assert(sizeof(Object) == sizeof(ui_widget *), "object slicing"); - class Widget : public Object, public Convertible { - public: - using native = ui_widget; - explicit Widget(ui_widget *h = nullptr) : Object((void *) h) - { } + void unref() + { g_object_unref(_handle); } - alert_response alert(std::string text, std::string title = "NetRadiant", - alert_type type = alert_type::OK, alert_icon icon = alert_icon::Default); + template + gulong connect(char const *detailed_signal, Lambda &&c_handler, void *data); - const char *file_dialog(bool open, const char *title, const char *path = nullptr, - const char *pattern = nullptr, bool want_load = false, bool want_import = false, - bool want_save = false); + template + gulong connect(char const *detailed_signal, Lambda &&c_handler, Object data); }; + static_assert(sizeof(Object) == sizeof(Object::native), "object slicing"); - static_assert(sizeof(Widget) == sizeof(Object), "object slicing"); - - extern Widget root; - -#define WRAP(name, super, impl, methods) \ - class name : public super, public Convertible { \ - public: \ - using native = impl; \ - explicit name(impl *h) : super(reinterpret_cast(h)) {} \ +#define WRAP(name, super, T, interfaces, ctors, methods) \ + class name; \ + class I##name : public details::Convertible { \ + public: \ + using self = name *; \ methods \ }; \ + class name : public super, public I##name, public details::Mixin::type { \ + public: \ + using self = name *; \ + using native = T *; \ + explicit name(native h) : super(reinterpret_cast(h)) {} \ + explicit name(Null n) : name((native) nullptr) {} \ + explicit name(New_t); \ + static name from(void *ptr) { return name((native) ptr); } \ + ctors \ + }; \ inline bool operator<(name self, name other) { return self._handle < other._handle; } \ static_assert(sizeof(name) == sizeof(super), "object slicing") - WRAP(AccelGroup, Object, ui_accelgroup, - AccelGroup(); + // https://developer.gnome.org/gtk2/stable/ch01.html + + // GInterface + + WRAP(CellEditable, Object, _GtkCellEditable, (), + , ); - WRAP(Adjustment, Widget, ui_adjustment, - Adjustment(double value, - double lower, double upper, - double step_increment, double page_increment, - double page_size); + WRAP(Editable, Object, _GtkEditable, (), + , + void editable(bool value); + ); + + WRAP(TreeModel, Object, _GtkTreeModel, (), + , + ); + + // GObject + + struct Dimensions { + int width; + int height; + }; + + WRAP(Widget, Object, _GtkWidget, (), + , + alert_response alert( + std::string text, + std::string title = "NetRadiant", + alert_type type = alert_type::OK, + alert_icon icon = alert_icon::Default + ); + const char *file_dialog( + bool open, + const char *title, + const char *path = nullptr, + const char *pattern = nullptr, + bool want_load = false, + bool want_import = false, + bool want_save = false + ); + bool visible(); + void show(); + Dimensions dimensions(); + void dimensions(int width, int height); ); - WRAP(Alignment, Widget, ui_alignment, + WRAP(Container, Widget, _GtkContainer, (), + , + void add(Widget widget); + + void remove(Widget widget); + + template + void foreach(Lambda &&lambda); + ); + + WRAP(Bin, Container, _GtkBin, (), + , + ); + + class AccelGroup; + WRAP(Window, Bin, _GtkWindow, (), + explicit Window(window_type type); + , + Window create_dialog_window( + const char *title, + void func(), + void *data, + int default_w = -1, + int default_h = -1 + ); + + Window create_modal_dialog_window( + const char *title, + ModalDialog &dialog, + int default_w = -1, + int default_h = -1 + ); + + Window create_floating_window(const char *title); + + std::uint64_t on_key_press( + bool (*f)(Widget widget, _GdkEventKey *event, void *extra), + void *extra = nullptr + ); + + void add_accel_group(AccelGroup group); + ); + + WRAP(Dialog, Window, _GtkDialog, (), + , + ); + + WRAP(Alignment, Bin, _GtkAlignment, (), Alignment(float xalign, float yalign, float xscale, float yscale); + , + ); + + WRAP(Frame, Bin, _GtkFrame, (), + explicit Frame(const char *label = nullptr); + , + ); + + WRAP(Button, Bin, _GtkButton, (), + explicit Button(const char *label); + , + ); + + WRAP(ToggleButton, Button, _GtkToggleButton, (), + , + bool active(); + ); + + WRAP(CheckButton, ToggleButton, _GtkCheckButton, (), + explicit CheckButton(const char *label); + , + ); + + WRAP(RadioButton, CheckButton, _GtkRadioButton, (), + , ); - WRAP(Box, Widget, ui_box,); + WRAP(Item, Bin, _GtkItem, (), + , + ); + + WRAP(MenuItem, Item, _GtkMenuItem, (), + explicit MenuItem(const char *label, bool mnemonic = false); + , + ); - WRAP(Button, Widget, ui_button, - Button(); - Button(const char *label); + WRAP(CheckMenuItem, MenuItem, _GtkCheckMenuItem, (), + , ); - WRAP(CellRenderer, Object, ui_cellrenderer,); + WRAP(RadioMenuItem, CheckMenuItem, _GtkRadioMenuItem, (), + , + ); - WRAP(CellRendererText, CellRenderer, ui_cellrenderertext, - CellRendererText(); + WRAP(TearoffMenuItem, MenuItem, _GtkTearoffMenuItem, (), + , ); - WRAP(CheckButton, Widget, ui_checkbutton, - CheckButton(const char *label); + WRAP(ComboBox, Bin, _GtkComboBox, (), + , ); - WRAP(ComboBox, Widget, ui_combobox,); + WRAP(ComboBoxText, ComboBox, _GtkComboBoxText, (), + , + ); + + WRAP(ToolItem, Bin, _GtkToolItem, (), + , + ); + + WRAP(ToolButton, ToolItem, _GtkToolButton, (), + , + ); + + WRAP(ToggleToolButton, ToolButton, _GtkToggleToolButton, (), + , + ); + + WRAP(RadioToolButton, ToggleToolButton, _GtkRadioToolButton, (), + , + ); - WRAP(ComboBoxText, ComboBox, ui_comboboxtext, - ComboBoxText(); + WRAP(ScrolledWindow, Bin, _GtkScrolledWindow, (), + , + void overflow(Policy x, Policy y); ); - WRAP(Entry, Widget, ui_entry, - Entry(); - Entry(std::size_t max_length); + WRAP(Box, Container, _GtkBox, (), + , ); - WRAP(Frame, Widget, ui_frame, - Frame(const char *label = nullptr); + WRAP(VBox, Box, _GtkVBox, (), + VBox(bool homogenous, int spacing); + , ); - WRAP(HBox, Box, ui_hbox, + WRAP(HBox, Box, _GtkHBox, (), HBox(bool homogenous, int spacing); + , ); - WRAP(HScale, Widget, ui_hscale, - HScale(Adjustment adjustment); - HScale(double min, double max, double step); + WRAP(Paned, Container, _GtkPaned, (), + , ); - WRAP(Image, Widget, ui_image, - Image(); + WRAP(HPaned, Paned, _GtkHPaned, (), + , ); - WRAP(Label, Widget, ui_label, - Label(const char *label); + WRAP(VPaned, Paned, _GtkVPaned, (), + , ); - WRAP(Menu, Widget, ui_menu, - Menu(); + WRAP(MenuShell, Container, _GtkMenuShell, (), + , ); - WRAP(MenuItem, Widget, ui_menuitem, - MenuItem(const char *label, bool mnemonic = false); + WRAP(MenuBar, MenuShell, _GtkMenuBar, (), + , ); - WRAP(Paned, Widget, ui_paned,); + WRAP(Menu, MenuShell, _GtkMenu, (), + , + ); - WRAP(HPaned, Paned, ui_hpaned, - HPaned(); - ); + WRAP(Table, Container, _GtkTable, (), + Table(std::size_t rows, std::size_t columns, bool homogenous); + , + ); + + WRAP(TextView, Container, _GtkTextView, (), + , + void text(char const *str); + ); - WRAP(VPaned, Paned, ui_vpaned, - VPaned(); - ); + WRAP(Toolbar, Container, _GtkToolbar, (), + , + ); + + class TreeModel; + WRAP(TreeView, Widget, _GtkTreeView, (), + TreeView(TreeModel model); + , + ); + + WRAP(Misc, Widget, _GtkMisc, (), + , + ); - WRAP(ScrolledWindow, Widget, ui_scrolledwindow, - ScrolledWindow(); + WRAP(Label, Widget, _GtkLabel, (), + explicit Label(const char *label); + , + void text(char const *str); ); - WRAP(SpinButton, Widget, ui_spinbutton, + WRAP(Image, Widget, _GtkImage, (), + , + ); + + WRAP(Entry, Widget, _GtkEntry, (IEditable, ICellEditable), + explicit Entry(std::size_t max_length); + , + char const *text(); + void text(char const *str); + ); + + class Adjustment; + WRAP(SpinButton, Entry, _GtkSpinButton, (), SpinButton(Adjustment adjustment, double climb_rate, std::size_t digits); + , ); - WRAP(Table, Widget, ui_table, - Table(std::size_t rows, std::size_t columns, bool homogenous); + WRAP(Range, Widget, _GtkRange, (), + , ); - WRAP(TextView, Widget, ui_textview, - TextView(); + WRAP(Scale, Range, _GtkScale, (), + , ); - WRAP(TreeModel, Widget, ui_treemodel,); + WRAP(HScale, Scale, _GtkHScale, (), + explicit HScale(Adjustment adjustment); + HScale(double min, double max, double step); + , + ); - WRAP(TreePath, Object, ui_treepath, - TreePath(); - TreePath(const char *path); + WRAP(Adjustment, Object, _GtkAdjustment, (), + Adjustment(double value, + double lower, double upper, + double step_increment, double page_increment, + double page_size); + , ); - WRAP(TreeView, Widget, ui_treeview, - TreeView(); - TreeView(TreeModel model); + WRAP(CellRenderer, Object, _GtkCellRenderer, (), + , + ); + + WRAP(CellRendererText, CellRenderer, _GtkCellRendererText, (), + , ); struct TreeViewColumnAttribute { const char *attribute; int column; }; - WRAP(TreeViewColumn, Widget, ui_treeviewcolumn, + WRAP(TreeViewColumn, Object, _GtkTreeViewColumn, (), TreeViewColumn(const char *title, CellRenderer renderer, std::initializer_list attributes); + , ); - WRAP(VBox, Box, ui_vbox, - VBox(bool homogenous, int spacing); + WRAP(AccelGroup, Object, _GtkAccelGroup, (), + , + ); + + WRAP(EntryCompletion, Object, _GtkEntryCompletion, (), + , ); - WRAP(Window, Widget, ui_window, - Window() : Window(nullptr) {}; - Window(window_type type); + WRAP(ListStore, Object, _GtkListStore, (ITreeModel), + , + void clear(); - Window create_dialog_window(const char *title, void func(), void *data, int default_w = -1, - int default_h = -1); + template + void append(T... args); - Window create_modal_dialog_window(const char *title, ui_modal &dialog, int default_w = -1, - int default_h = -1); + void append(); + ); - Window create_floating_window(const char *title); + WRAP(TreeSelection, Object, _GtkTreeSelection, (), + , + ); - std::uint64_t on_key_press(bool (*f)(Widget widget, ui_evkey *event, void *extra), - void *extra = nullptr); + // GBoxed - void add_accel_group(AccelGroup group); + WRAP(TreePath, Object, _GtkTreePath, (), + explicit TreePath(const char *path); + , + ); + + // Custom + + WRAP(GLArea, Widget, _GtkGLArea, (), + , + guint on_render(GCallback pFunction, void *data); ); #undef WRAP + // callbacks + + namespace { + using GtkCallback = void (*)(_GtkWidget *, void *); + extern "C" { + void gtk_container_foreach(_GtkContainer *, GtkCallback, void *); + } + } + +#define this (*static_cast(this)) + + template + gulong Object::connect(char const *detailed_signal, Lambda &&c_handler, void *data) + { + return g_signal_connect(G_OBJECT(this), detailed_signal, c_handler, data); + } + + template + gulong Object::connect(char const *detailed_signal, Lambda &&c_handler, Object data) + { + return g_signal_connect(G_OBJECT(this), detailed_signal, c_handler, (_GtkObject *) data); + } + + template + void IContainer::foreach(Lambda &&lambda) + { + GtkCallback cb = [](_GtkWidget *widget, void *data) -> void { + using Function = typename std::decay::type; + Function *f = static_cast(data); + (*f)(Widget(widget)); + }; + gtk_container_foreach(this, cb, &lambda); + } + + namespace { + extern "C" { + void gtk_list_store_insert_with_values(_GtkListStore *, _GtkTreeIter *, gint position, ...); + } + } + + template + void IListStore::append(T... args) { + static_assert(sizeof...(args) % 2 == 0, "received an odd number of arguments"); + gtk_list_store_insert_with_values(this, NULL, -1, args..., -1); + } + +#undef this + } #endif