diff --git a/haiku/GNUmakeinc.mk b/haiku/GNUmakeinc.mk index 29e77c93..a07580aa 100644 --- a/haiku/GNUmakeinc.mk +++ b/haiku/GNUmakeinc.mk @@ -5,7 +5,8 @@ CXXFILES += \ haiku/control.cpp \ haiku/main.cpp \ haiku/text.cpp \ - haiku/util.cpp + haiku/util.cpp \ + haiku/window.cpp HFILES += \ haiku/uipriv_haiku.hpp diff --git a/haiku/window.cpp b/haiku/window.cpp new file mode 100644 index 00000000..9b22b5ea --- /dev/null +++ b/haiku/window.cpp @@ -0,0 +1,156 @@ +// 18 november 2015 +#include "uipriv_haiku.hpp" + +class libuiBWindow : public BWindow { +public: + // C++11! Inherit constructors. + using BWindow::BWindow; + + uiWindow *w; + virtual bool QuitRequested(); +}; + +struct uiWindow { + uiHaikuControl c; + + libuiBWindow *window; + + struct child *child; + int margined; + + int (*onClosing)(uiWindow *, void *); + void *onClosingData; +}; + +uiHaikuDefineControlWithOnDestroy( + uiWindow, // type name + uiWindowType, // type function + window, // handle + complain("attempt to use default CommitDestroy() code for uiWindow on Haiku"); // on destroy +) + +// TODO is this correct? +bool libuiBWindow::QuitRequested() +{ + // manually destroy the window ourselves; don't let the default BWindow code do it directly + if ((*(this->w->onClosing))(this->w, this->w->onClosingData)) + uiControlDestroy(uiControl(this->w)); + // don't continue to the default BWindow code; we destroyed the window by now + return false; +} + +static int defaultOnClosing(uiWindow *w, void *data) +{ + return 0; +} + +static void windowCommitDestroy(uiControl *c) +{ + uiWindow *w = uiWindow(c); + + // first hide ourselves + w->window->Hide(); + // now destroy the child +//TODO if (w->child != NULL) +//TODO childDestroy(w->child); + // and finally destroy ourselves + // this is why we don't use the libui-provided CommitDestroy() implementation + w->window->Lock(); + w->window->Quit(); + // w->window is now destroyed for us +} + +// The default implementations assume a BView, which a uiWindow is not. +static void windowCommitShow(uiControl *c) +{ + uiWindow *w = uiWindow(c); + + // This is documented as behaving how we want with regards to presentation. + w->window->Show(); +} + +static void windowCommitHide(uiControl *c) +{ + uiWindow *w = uiWindow(c); + + w->window->Hide(); +} + +static void windowContainerUpdateState(uiControl *c) +{ +/*TODO + uiWindow *w = uiWindow(c); + + if (w->child != NULL) + childUpdateState(w->child); +*/ +} + +char *uiWindowTitle(uiWindow *w) +{ + return uiHaikuStrdupText(w->window->Title()); +} + +void uiWindowSetTitle(uiWindow *w, const char *title) +{ + w->window->SetTitle(title); + // don't queue resize; the caption isn't part of what affects layout and sizing of the client area (it'll be ellipsized if too long) +} + +void uiWindowOnClosing(uiWindow *w, int (*f)(uiWindow *, void *), void *data) +{ + w->onClosing = f; + w->onClosingData = data; +} + +void uiWindowSetChild(uiWindow *w, uiControl *child) +{ +/*TODO + if (w->child != NULL) + childDestroy(w->child); + w->child = newChildWithBox(child, uiControl(w), w->vboxContainer, w->margined); + if (w->child != NULL) { + gtk_widget_set_hexpand(childBox(w->child), TRUE); + gtk_widget_set_halign(childBox(w->child), GTK_ALIGN_FILL); + gtk_widget_set_vexpand(childBox(w->child), TRUE); + gtk_widget_set_valign(childBox(w->child), GTK_ALIGN_FILL); + } +*/ +} + +int uiWindowMargined(uiWindow *w) +{ + return w->margined; +} + +void uiWindowSetMargined(uiWindow *w, int margined) +{ + w->margined = margined; +//TODO if (w->child != NULL) +//TODO childSetMargined(w->child, w->margined); +} + +uiWindow *uiNewWindow(const char *title, int width, int height, int hasMenubar) +{ + uiWindow *w; + + w = (uiWindow *) uiNewControl(uiWindowType()); + + // TODO find out how to make it ignore position + // The given rect is the size of the inside of the window, just as we want. + w->window = new libuiBWindow( + BRect(100, 100, width, height), + title, + B_TITLED_WINDOW, + B_ASYNCHRONOUS_CONTROLS); + + uiWindowOnClosing(w, defaultOnClosing, NULL); + + uiHaikuFinishNewControl(w, uiWindow); + uiControl(w)->CommitDestroy = windowCommitDestroy; + uiControl(w)->CommitShow = windowCommitShow; + uiControl(w)->CommitHide = windowCommitHide; + uiControl(w)->ContainerUpdateState = windowContainerUpdateState; + + return w; +} diff --git a/ui_haiku.hpp b/ui_haiku.hpp index 08dcbfe6..db0e0f2b 100644 --- a/ui_haiku.hpp +++ b/ui_haiku.hpp @@ -26,7 +26,7 @@ _UI_EXTERN uintmax_t uiHaikuControlType(void); uintmax_t typefn(void) \ { \ if (_ ## type ## Type == 0) \ - _ ## type ## Type = uiRegisterType(#type, uiDarwinControlType(), sizeof (type)); \ + _ ## type ## Type = uiRegisterType(#type, uiHaikuControlType(), sizeof (type)); \ return _ ## type ## Type; \ } \ static void _ ## type ## CommitDestroy(uiControl *c) \