]> de.git.xonotic.org Git - xonotic/netradiant.git/blobdiff - libs/uilib/uilib.h
GTK: wrap GTK_WIDGET
[xonotic/netradiant.git] / libs / uilib / uilib.h
index 72ec0ca434c453353df058efcbd80133f170f287..e15bdbe4ab5bfa8db1dfa5d73ede82e24dd07d19 100644 (file)
@@ -2,6 +2,7 @@
 #define INCLUDED_UILIB_H
 
 #include <string>
+#include <glib-object.h>
 
 struct _GdkEventKey;
 struct _GtkAccelGroup;
@@ -14,12 +15,14 @@ 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;
@@ -28,13 +31,16 @@ 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;
@@ -45,10 +51,12 @@ 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;
@@ -57,14 +65,24 @@ struct _GtkWidget;
 struct _GtkWindow;
 struct _GTypeInstance;
 
+#if GTK_TARGET == 3
+struct _GtkGLArea;
+#endif
+
+#if GTK_TARGET == 2
+using _GtkGLArea = struct _GtkDrawingArea;
+#endif
+
 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 {
@@ -95,6 +113,20 @@ namespace ui {
         POPUP
     };
 
+    enum class Shadow {
+        NONE,
+        IN,
+        OUT,
+        ETCHED_IN,
+        ETCHED_OUT
+    };
+
+    enum class Policy {
+        ALWAYS,
+        AUTOMATIC,
+        NEVER
+    };
+
     namespace details {
 
         enum class Convert {
@@ -134,14 +166,18 @@ namespace ui {
         };
     }
 
+    extern struct Null {} null;
+    extern struct New_t {} New;
+
     class Object :
             public details::Convertible<Object, _GtkObject *, details::Convert::Explicit>,
             public details::Convertible<Object, _GTypeInstance *, details::Convert::Explicit> {
     public:
+        using self = Object *;
         using native = _GtkObject *;
         native _handle;
 
-        Object(native h) : _handle(h)
+        explicit Object(native h) : _handle(h)
         {}
 
         explicit operator bool() const
@@ -149,21 +185,36 @@ namespace ui {
 
         explicit operator void *() const
         { return _handle; }
+
+        void unref()
+        { g_object_unref(_handle); }
+
+        void ref()
+        { g_object_ref(_handle); }
+
+        template<class Lambda>
+        gulong connect(char const *detailed_signal, Lambda &&c_handler, void *data);
+
+        template<class Lambda>
+        gulong connect(char const *detailed_signal, Lambda &&c_handler, Object data);
     };
     static_assert(sizeof(Object) == sizeof(Object::native), "object slicing");
 
 #define WRAP(name, super, T, interfaces, ctors, methods) \
     class name; \
-    class I##name { \
+    class I##name : public details::Convertible<name, T *, details::Convert::Implicit> { \
     public: \
         using self = name *; \
         methods \
     }; \
-    class name : public super, public details::Convertible<name, T *, details::Convert::Implicit>, public I##name, public details::Mixin<name, void interfaces>::type { \
+    class name : public super, public I##name, public details::Mixin<name, void interfaces>::type { \
     public: \
         using self = name *; \
         using native = T *; \
         explicit name(native h) : super(reinterpret_cast<super::native>(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; } \
@@ -171,18 +222,29 @@ namespace ui {
 
     // https://developer.gnome.org/gtk2/stable/ch01.html
 
+    // GInterface
+
     WRAP(CellEditable, Object, _GtkCellEditable, (),
     ,
     );
 
     WRAP(Editable, Object, _GtkEditable, (),
-         Editable();
     ,
          void editable(bool value);
     );
 
+    WRAP(TreeModel, Object, _GtkTreeModel, (),
+    ,
+    );
+
+    // GObject
+
+    struct Dimensions {
+        int width;
+        int height;
+    };
+
     WRAP(Widget, Object, _GtkWidget, (),
-         Widget();
     ,
          alert_response alert(
                  std::string text,
@@ -199,11 +261,23 @@ namespace ui {
                  bool want_import = false,
                  bool want_save = false
          );
+         bool visible();
+         void visible(bool shown);
          void show();
+         void hide();
+         Dimensions dimensions();
+         void dimensions(int width, int height);
+         void destroy();
     );
 
     WRAP(Container, Widget, _GtkContainer, (),
     ,
+         void add(Widget widget);
+
+         void remove(Widget widget);
+
+         template<class Lambda>
+         void foreach(Lambda &&lambda);
     );
 
     WRAP(Bin, Container, _GtkBin, (),
@@ -212,8 +286,7 @@ namespace ui {
 
     class AccelGroup;
     WRAP(Window, Bin, _GtkWindow, (),
-         Window();
-         Window(window_type type);
+         explicit Window(window_type type);
     ,
          Window create_dialog_window(
                  const char *title,
@@ -250,13 +323,12 @@ namespace ui {
     );
 
     WRAP(Frame, Bin, _GtkFrame, (),
-         Frame(const char *label = nullptr);
+         explicit Frame(const char *label = nullptr);
     ,
     );
 
     WRAP(Button, Bin, _GtkButton, (),
-         Button();
-         Button(const char *label);
+         explicit Button(const char *label);
     ,
     );
 
@@ -266,7 +338,7 @@ namespace ui {
     );
 
     WRAP(CheckButton, ToggleButton, _GtkCheckButton, (),
-         CheckButton(const char *label);
+         explicit CheckButton(const char *label);
     ,
     );
 
@@ -279,12 +351,19 @@ namespace ui {
     );
 
     WRAP(MenuItem, Item, _GtkMenuItem, (),
-         MenuItem();
-         MenuItem(const char *label, bool mnemonic = false);
+         explicit MenuItem(const char *label, bool mnemonic = false);
     ,
     );
+
+    WRAP(CheckMenuItem, MenuItem, _GtkCheckMenuItem, (),
+    ,
+    );
+
+    WRAP(RadioMenuItem, CheckMenuItem, _GtkRadioMenuItem, (),
+    ,
+    );
+
     WRAP(TearoffMenuItem, MenuItem, _GtkTearoffMenuItem, (),
-         TearoffMenuItem();
     ,
     );
 
@@ -293,7 +372,6 @@ namespace ui {
     );
 
     WRAP(ComboBoxText, ComboBox, _GtkComboBoxText, (),
-         ComboBoxText();
     ,
     );
 
@@ -314,12 +392,14 @@ namespace ui {
     );
 
     WRAP(ScrolledWindow, Bin, _GtkScrolledWindow, (),
-         ScrolledWindow();
     ,
+         void overflow(Policy x, Policy y);
     );
 
     WRAP(Box, Container, _GtkBox, (),
     ,
+         void pack_start(ui::Widget child, bool expand, bool fill, unsigned int padding);
+         void pack_end(ui::Widget child, bool expand, bool fill, unsigned int padding);
     );
 
     WRAP(VBox, Box, _GtkVBox, (),
@@ -337,12 +417,10 @@ namespace ui {
     );
 
     WRAP(HPaned, Paned, _GtkHPaned, (),
-         HPaned();
     ,
     );
 
     WRAP(VPaned, Paned, _GtkVPaned, (),
-         VPaned();
     ,
     );
 
@@ -350,24 +428,30 @@ namespace ui {
     ,
     );
 
-    WRAP(Menu, Widget, _GtkMenu, (),
-         Menu();
+    WRAP(MenuBar, MenuShell, _GtkMenuBar, (),
+    ,
+    );
+
+    WRAP(Menu, MenuShell, _GtkMenu, (),
     ,
     );
 
-    WRAP(Table, Widget, _GtkTable, (),
+    WRAP(Table, Container, _GtkTable, (),
          Table(std::size_t rows, std::size_t columns, bool homogenous);
     ,
     );
 
-    WRAP(TextView, Widget, _GtkTextView, (),
-         TextView();
+    WRAP(TextView, Container, _GtkTextView, (),
+    ,
+         void text(char const *str);
+    );
+
+    WRAP(Toolbar, Container, _GtkToolbar, (),
     ,
     );
 
     class TreeModel;
     WRAP(TreeView, Widget, _GtkTreeView, (),
-         TreeView();
          TreeView(TreeModel model);
     ,
     );
@@ -377,19 +461,20 @@ namespace ui {
     );
 
     WRAP(Label, Widget, _GtkLabel, (),
-         Label(const char *label);
+         explicit Label(const char *label);
     ,
+         void text(char const *str);
     );
 
     WRAP(Image, Widget, _GtkImage, (),
-         Image();
     ,
     );
 
     WRAP(Entry, Widget, _GtkEntry, (IEditable, ICellEditable),
-         Entry();
-         Entry(std::size_t max_length);
+         explicit Entry(std::size_t max_length);
     ,
+        char const *text();
+        void text(char const *str);
     );
 
     class Adjustment;
@@ -407,7 +492,7 @@ namespace ui {
     );
 
     WRAP(HScale, Scale, _GtkHScale, (),
-         HScale(Adjustment adjustment);
+         explicit HScale(Adjustment adjustment);
          HScale(double min, double max, double step);
     ,
     );
@@ -425,7 +510,6 @@ namespace ui {
     );
 
     WRAP(CellRendererText, CellRenderer, _GtkCellRendererText, (),
-         CellRendererText();
     ,
     );
 
@@ -439,27 +523,91 @@ namespace ui {
     );
 
     WRAP(AccelGroup, Object, _GtkAccelGroup, (),
-         AccelGroup();
     ,
     );
 
-    WRAP(ListStore, Object, _GtkListStore, (),
+    WRAP(EntryCompletion, Object, _GtkEntryCompletion, (),
+    ,
+    );
+
+    WRAP(ListStore, Object, _GtkListStore, (ITreeModel),
     ,
          void clear();
+
+         template<class... T>
+         void append(T... args);
+
+         void append();
     );
 
-    WRAP(TreeModel, Widget, _GtkTreeModel, (),
+    WRAP(TreeSelection, Object, _GtkTreeSelection, (),
     ,
     );
 
+    // GBoxed
+
     WRAP(TreePath, Object, _GtkTreePath, (),
-         TreePath();
-         TreePath(const char *path);
+         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<self>(this))
+
+    template<class Lambda>
+    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<class Lambda>
+    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<class Lambda>
+    void IContainer::foreach(Lambda &&lambda)
+    {
+        GtkCallback cb = [](_GtkWidget *widget, void *data) -> void {
+            using Function = typename std::decay<Lambda>::type;
+            Function *f = static_cast<Function *>(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<class... T>
+    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