]> git.xonotic.org Git - xonotic/netradiant.git/blobdiff - libs/uilib/uilib.cpp
Dialog: wrap GTK widgets in data binding
[xonotic/netradiant.git] / libs / uilib / uilib.cpp
index 4832d92ffaec570a49318cd813b8c96d7eb17041..e4fb3d321351e25f3c429ed19c6e19c427f4eed9 100644 (file)
@@ -46,50 +46,39 @@ namespace ui {
 
     template<class T> _IMPL(T,);
 
-#define this (verify<self>::test(*static_cast<self>(this)))
+    template<class T>
+    using pointer_remove_const = std::add_pointer<
+            typename std::remove_const<
+                    typename std::remove_pointer<T>::type
+            >::type
+    >;
+
+#define this (verify<self>::test(*static_cast<self>(const_cast<pointer_remove_const<decltype(this)>::type>(this))))
 
     IMPL(Editable, GTK_EDITABLE);
 
     void IEditable::editable(bool value)
     {
-        gtk_editable_set_editable(GTK_EDITABLE(this), value);
+        gtk_editable_set_editable(this, value);
     }
 
+    IMPL(TreeModel, GTK_TREE_MODEL);
+
     IMPL(Widget, GTK_WIDGET);
 
     Widget::Widget(ui::New_t) : Widget(nullptr)
     {}
 
-    alert_response IWidget::alert(std::string text, std::string title, alert_type type, alert_icon icon)
+    Window IWidget::window()
     {
-        auto ret = gtk_MessageBox(this, text.c_str(),
-                                  title.c_str(),
-                                  type == alert_type::OK ? eMB_OK :
-                                  type == alert_type::OKCANCEL ? eMB_OKCANCEL :
-                                  type == alert_type::YESNO ? eMB_YESNO :
-                                  type == alert_type::YESNOCANCEL ? eMB_YESNOCANCEL :
-                                  type == alert_type::NOYES ? eMB_NOYES :
-                                  eMB_OK,
-                                  icon == alert_icon::Default ? eMB_ICONDEFAULT :
-                                  icon == alert_icon::Error ? eMB_ICONERROR :
-                                  icon == alert_icon::Warning ? eMB_ICONWARNING :
-                                  icon == alert_icon::Question ? eMB_ICONQUESTION :
-                                  icon == alert_icon::Asterisk ? eMB_ICONASTERISK :
-                                  eMB_ICONDEFAULT
-        );
-        return
-                ret == eIDOK ? alert_response::OK :
-                ret == eIDCANCEL ? alert_response::CANCEL :
-                ret == eIDYES ? alert_response::YES :
-                ret == eIDNO ? alert_response::NO :
-                alert_response::OK;
+        return Window::from(gtk_widget_get_toplevel(this));
     }
 
     const char *
     IWidget::file_dialog(bool open, const char *title, const char *path, const char *pattern, bool want_load,
                          bool want_import, bool want_save)
     {
-        return ::file_dialog(this, open, title, path, pattern, want_load, want_import, want_save);
+        return ::file_dialog(this.window(), open, title, path, pattern, want_load, want_import, want_save);
     }
 
     bool IWidget::visible()
@@ -97,11 +86,25 @@ namespace ui {
         return gtk_widget_get_visible(this) != 0;
     }
 
+    void IWidget::visible(bool shown)
+    {
+        if (shown) {
+            this.show();
+        } else {
+            this.hide();
+        }
+    }
+
     void IWidget::show()
     {
         gtk_widget_show(this);
     }
 
+    void IWidget::hide()
+    {
+        gtk_widget_hide(this);
+    }
+
     Dimensions IWidget::dimensions()
     {
         GtkAllocation allocation;
@@ -114,6 +117,11 @@ namespace ui {
         gtk_widget_set_size_request(this, width, height);
     }
 
+    void IWidget::destroy()
+    {
+        gtk_widget_destroy(this);
+    }
+
     IMPL(Container, GTK_CONTAINER);
 
     void IContainer::add(Widget widget)
@@ -137,6 +145,31 @@ namespace ui {
     )))
     {}
 
+    alert_response IWindow::alert(std::string text, std::string title, alert_type type, alert_icon icon)
+    {
+        auto ret = gtk_MessageBox(this, text.c_str(),
+                                  title.c_str(),
+                                  type == alert_type::OK ? eMB_OK :
+                                  type == alert_type::OKCANCEL ? eMB_OKCANCEL :
+                                  type == alert_type::YESNO ? eMB_YESNO :
+                                  type == alert_type::YESNOCANCEL ? eMB_YESNOCANCEL :
+                                  type == alert_type::NOYES ? eMB_NOYES :
+                                  eMB_OK,
+                                  icon == alert_icon::Default ? eMB_ICONDEFAULT :
+                                  icon == alert_icon::Error ? eMB_ICONERROR :
+                                  icon == alert_icon::Warning ? eMB_ICONWARNING :
+                                  icon == alert_icon::Question ? eMB_ICONQUESTION :
+                                  icon == alert_icon::Asterisk ? eMB_ICONASTERISK :
+                                  eMB_ICONDEFAULT
+        );
+        return
+                ret == eIDOK ? alert_response::OK :
+                ret == eIDCANCEL ? alert_response::CANCEL :
+                ret == eIDYES ? alert_response::YES :
+                ret == eIDNO ? alert_response::NO :
+                alert_response::OK;
+    }
+
     Window IWindow::create_dialog_window(const char *title, void func(), void *data, int default_w, int default_h)
     {
         return Window(::create_dialog_window(this, title, func, data, default_w, default_h));
@@ -195,9 +228,14 @@ namespace ui {
 
     IMPL(ToggleButton, GTK_TOGGLE_BUTTON);
 
-    bool IToggleButton::active()
+    bool IToggleButton::active() const
     {
-        return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(this)) != 0;
+        return gtk_toggle_button_get_active(this) != 0;
+    }
+
+    void IToggleButton::active(bool value)
+    {
+        gtk_toggle_button_set_active(this, value);
     }
 
     IMPL(CheckButton, GTK_CHECK_BUTTON);
@@ -237,6 +275,18 @@ namespace ui {
         gtk_scrolled_window_set_policy(this, static_cast<GtkPolicyType>(x), static_cast<GtkPolicyType>(y));
     }
 
+    IMPL(Box, GTK_BOX);
+
+    void IBox::pack_start(ui::Widget child, bool expand, bool fill, unsigned int padding)
+    {
+        gtk_box_pack_start(this, child, expand, fill, padding);
+    }
+
+    void IBox::pack_end(ui::Widget child, bool expand, bool fill, unsigned int padding)
+    {
+        gtk_box_pack_end(this, child, expand, fill, padding);
+    }
+
     IMPL(VBox, GTK_VBOX);
 
     VBox::VBox(bool homogenous, int spacing) : VBox(GTK_VBOX(gtk_vbox_new(homogenous, spacing)))
@@ -269,6 +319,14 @@ namespace ui {
     )
     {}
 
+    void ITable::attach(Widget child, TableAttach attach, TableAttachOptions options, TablePadding padding) {
+        gtk_table_attach(this, child,
+                         attach.left, attach.right, attach.top, attach.bottom,
+                         static_cast<GtkAttachOptions>(options.x), static_cast<GtkAttachOptions>(options.y),
+                         padding.x, padding.y
+        );
+    }
+
     IMPL(TextView, GTK_TEXT_VIEW);
 
     TextView::TextView(ui::New_t) : TextView(GTK_TEXT_VIEW(gtk_text_view_new()))
@@ -378,6 +436,8 @@ namespace ui {
         gtk_list_store_append(this, nullptr);
     }
 
+    IMPL(TreeStore, GTK_TREE_STORE);
+
     // IMPL(TreePath, GTK_TREE_PATH);
 
     TreePath::TreePath(ui::New_t) : TreePath(gtk_tree_path_new())