diff --git a/wpf/box.cpp b/wpf/box.cpp new file mode 100644 index 00000000..49d54686 --- /dev/null +++ b/wpf/box.cpp @@ -0,0 +1,194 @@ +// 26 november 2015 +#include "uipriv_wpf.hpp" + +using namespace System::Collections::Generic; + +// TODO +// - save Alignment of children? +// - SnapsToDevicePixels? http://stackoverflow.com/questions/10718985/grid-border-gap-between-cells + +ref class boxChild { +public: + uiControl *c; + Border ^border; + int stretchy; +}; + +struct uiBox { + uiWindowsControl c; + // we could've used StackPanel but that doesn't care about available size + gcroot *grid; + gcroot ^> *children; + int vertical; + int padded; +}; + +static void onDestroy(uiBox *b); + +uiWindowsDefineControlWithOnDestroy( + uiBox, // type name + uiBoxType, // type function + grid, // handle + onDestroy(hthis); // on destroy +) + +static void onDestroy(uiBox *b) +{ + List ^children; + + children = *(b->children); + while (children->Count != 0) { + children[0]->border->Child = nullptr; + uiControlSetParent(children[0]->c, NULL); + uiControlDestroy(children[0]->c); + children->RemoveAt(0); + } + delete b->children; +} + +static void boxContainerUpdateState(uiControl *c) +{ + uiBox *b = uiBox(c); + List ^children; + int i; + + children = *(b->children); + for (i = 0; i < children->Count; i++) + controlUpdateState(children[i]->c); +} + +// Grid unfortunately does not have a way to set the spacing between rows and columns. +// This means we have to do padding ourselves. +static void resetMargins(uiBox *b) +{ + double paddingUnit; + Thickness first; + Thickness after; + List ^children; + int i; + + children = *(b->children); + if (children->Count == 0) + return; + + paddingUnit = 0; + if (b->padded) + paddingUnit = 5; + first = Thickness(0, 0, 0, 0); + after = Thickness(paddingUnit, 0, 0, 0); + if (b->vertical) + after = Thickness(0, paddingUnit, 0, 0); + + // TODO padding? + children[0]->border->Margin = first; + for (i = 1; i < children->Count; i++) + children[i]->border->Margin = after; +} + +void uiBoxAppend(uiBox *b, uiControl *c, int stretchy) +{ + Grid ^g; + boxChild ^bc; + int pos; + + bc = gcnew boxChild(); + bc->c = c; + bc->border = gcnew Border(); + bc->stretchy = stretchy; + + bc->border->Child = genericHandle(bc->c); + + g = *(b->grid); + + // get position before adding the child so that we get the right count value + pos = g->ColumnDefinitions->Count; + if (b->vertical) + pos = g->RowDefinitions->Count; + + g->Children->Add(bc->border); + + if (b->vertical) { + g->SetRow(bc->border, pos); + g->SetColumn(bc->border, 0); + // apparently we have to do this ourselves... + g->RowDefinitions->Add(gcnew RowDefinition()); + if (bc->stretchy) + g->RowDefinitions[pos]->Height = GridLength(1, GridUnitType::Star); + else + g->RowDefinitions[pos]->Height = GridLength(1, GridUnitType::Auto); + } else { + g->SetRow(bc->border, 0); + g->SetColumn(bc->border, pos); + g->ColumnDefinitions->Add(gcnew ColumnDefinition()); + if (bc->stretchy) + g->ColumnDefinitions[pos]->Width = GridLength(1, GridUnitType::Star); + else + g->ColumnDefinitions[pos]->Width = GridLength(1, GridUnitType::Auto); + } + + uiControlSetParent(bc->c, uiControl(b)); + (*(b->children))->Add(bc); + resetMargins(b); +} + +void uiBoxDelete(uiBox *b, uintmax_t index) +{ + boxChild ^bc; + List ^children; + + children = *(b->children); + bc = children[index]; + children->RemoveAt(index); + uiControlSetParent(bc->c, NULL); + bc->border->Child = nullptr; + (*(b->grid))->Children->RemoveAt(index); + resetMargins(b); +} + +int uiBoxPadded(uiBox *b) +{ + return b->padded; +} + +void uiBoxSetPadded(uiBox *b, int padded) +{ + b->padded = padded; + resetMargins(b); +} + +static uiBox *finishNewBox(int vertical) +{ + uiBox *b; + + b = (uiBox *) uiNewControl(uiBoxType()); + + b->grid = new gcroot(); + *(b->grid) = gcnew Grid(); + + b->vertical = vertical; + if (b->vertical) { + (*(b->grid))->ColumnDefinitions->Add(gcnew ColumnDefinition()); + (*(b->grid))->ColumnDefinitions[0]->Width = GridLength(1, GridUnitType::Star); + } else { + (*(b->grid))->RowDefinitions->Add(gcnew RowDefinition()); + (*(b->grid))->RowDefinitions[0]->Height = GridLength(1, GridUnitType::Star); + } + + b->children = new gcroot ^>(); + *(b->children) = gcnew List(); + + uiWindowsFinishNewControl(b, uiBox, grid); + uiControl(b)->ContainerUpdateState = boxContainerUpdateState; + + return b; +} + +uiBox *uiNewHorizontalBox(void) +{ + return finishNewBox(0); +} + +uiBox *uiNewVerticalBox(void) +{ + return finishNewBox(1); +} diff --git a/wpf/control.cpp b/wpf/control.cpp index 6939ad2b..dc4c9e52 100644 --- a/wpf/control.cpp +++ b/wpf/control.cpp @@ -10,11 +10,11 @@ uintmax_t uiWindowsControlType(void) return type_uiWindowsControl; } -Control ^genericHandle(uiControl *c) +UIElement ^genericHandle(uiControl *c) { - gcroot *h; + gcroot *h; - h = (gcroot *) uiControlHandle(c); + h = (gcroot *) uiControlHandle(c); return *h; } diff --git a/wpf/libui.msbuild b/wpf/libui.msbuild index 9436320f..a65e6249 100755 --- a/wpf/libui.msbuild +++ b/wpf/libui.msbuild @@ -75,6 +75,7 @@ false + diff --git a/wpf/ui_wpf.hpp b/wpf/ui_wpf.hpp index db172bcf..dfee82fb 100644 --- a/wpf/ui_wpf.hpp +++ b/wpf/ui_wpf.hpp @@ -19,7 +19,7 @@ typedef struct uiWindowsControl uiWindowsControl; struct uiWindowsControl { uiControl c; // TODO make truly private - gcroot *genericHandle; + gcroot *genericHandle; }; _UI_EXTERN uintmax_t uiWindowsControlType(void); #define uiWindowsControl(this) ((uiWindowsControl *) uiIsA((this), uiWindowsControlType(), 1)) @@ -56,7 +56,7 @@ _UI_EXTERN uintmax_t uiWindowsControlType(void); uiControl(variable)->CommitDestroy = _ ## type ## CommitDestroy; \ uiControl(variable)->Handle = _ ## type ## Handle; \ uiControl(variable)->ContainerUpdateState = _ ## type ## ContainerUpdateState; \ - uiWindowsControl(variable)->genericHandle = new gcroot(); \ + uiWindowsControl(variable)->genericHandle = new gcroot(); \ *(uiWindowsControl(variable)->genericHandle) = *(variable->handle); \ uiWindowsFinishControl(uiControl(variable)); diff --git a/wpf/uipriv_wpf.hpp b/wpf/uipriv_wpf.hpp index 0f228ddb..f1424300 100644 --- a/wpf/uipriv_wpf.hpp +++ b/wpf/uipriv_wpf.hpp @@ -18,4 +18,4 @@ using namespace System::Windows::Controls; extern String ^fromUTF8(const char *); // control.cpp -extern Control ^genericHandle(uiControl *c); +extern UIElement ^genericHandle(uiControl *c); diff --git a/wpf/xtest.c b/wpf/xtest.c index 67d018c1..92b122cd 100644 --- a/wpf/xtest.c +++ b/wpf/xtest.c @@ -12,12 +12,20 @@ int main(void) uiInitOptions o; uiWindow *w; uiButton *btn; + uiBox *box; if (uiInit(&o) != NULL) return 1; w = uiNewWindow("Hello from C", 320, 240, 0); uiWindowOnClosing(w, onClosing, NULL); + box = uiNewVerticalBox(); btn = uiNewButton("Hello from C"); - uiWindowSetChild(w, uiControl(btn)); + uiBoxAppend(box, uiControl(btn), 0); + btn = uiNewButton("Hello from C"); + uiBoxAppend(box, uiControl(btn), 0); + btn = uiNewButton("Hello from C"); + uiBoxAppend(box, uiControl(btn), 0); + uiWindowSetChild(w, uiControl(box)); + uiBoxSetPadded(box, 1); uiWindowSetMargined(w, 1); uiControlShow(uiControl(w)); uiMain(); diff --git a/wpf/xtest.go b/wpf/xtest.go index 4d076a08..06915757 100644 --- a/wpf/xtest.go +++ b/wpf/xtest.go @@ -11,6 +11,9 @@ var uiWindowOnClosing = libui.NewProc("uiWindowOnClosing") var uiNewButton = libui.NewProc("uiNewButton") var uiWindowSetChild = libui.NewProc("uiWindowSetChild") var uiWindowSetMargined = libui.NewProc("uiWindowSetMargined") +var uiNewVerticalBox = libui.NewProc("uiNewVerticalBox") +var uiBoxAppend = libui.NewProc("uiBoxAppend") +var uiBoxSetPadded = libui.NewProc("uiBoxSetPadded") var uiControlShow = libui.NewProc("uiControlShow") var uiMain = libui.NewProc("uiMain") var uiQuit = libui.NewProc("uiQuit") @@ -31,9 +34,24 @@ func main() { uintptr(unsafe.Pointer(&s[0])), 320, 240, 0) uiWindowOnClosing.Call(w, syscall.NewCallbackCDecl(onClosing), 0) + box, _, _ := uiNewVerticalBox.Call() btn, _, _ := uiNewButton.Call( uintptr(unsafe.Pointer(&s[0]))) - uiWindowSetChild.Call(w, btn) + uiBoxAppend.Call(box, btn, 0) + btn, _, _ = uiNewButton.Call( + uintptr(unsafe.Pointer(&s[0]))) + uiBoxAppend.Call(box, btn, 1) + btn, _, _ = uiNewButton.Call( + uintptr(unsafe.Pointer(&s[0]))) + uiBoxAppend.Call(box, btn, 0) + btn, _, _ = uiNewButton.Call( + uintptr(unsafe.Pointer(&s[0]))) + uiBoxAppend.Call(box, btn, 1) + btn, _, _ = uiNewButton.Call( + uintptr(unsafe.Pointer(&s[0]))) + uiBoxAppend.Call(box, btn, 0) + uiWindowSetChild.Call(w, box) + uiBoxSetPadded.Call(box, 1) uiWindowSetMargined.Call(w, 1) uiControlShow.Call(w) uiMain.Call(w)