Implemented uiBox on WPF.

This commit is contained in:
Pietro Gagliardi 2015-11-26 01:26:30 -05:00
parent 99521f4801
commit 7e6c3c0abe
7 changed files with 229 additions and 8 deletions

194
wpf/box.cpp Normal file
View File

@ -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 ^> *grid;
gcroot<List<boxChild ^> ^> *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<boxChild ^> ^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<boxChild ^> ^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<boxChild ^> ^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<boxChild ^> ^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<Grid ^>();
*(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<List<boxChild ^> ^>();
*(b->children) = gcnew List<boxChild ^>();
uiWindowsFinishNewControl(b, uiBox, grid);
uiControl(b)->ContainerUpdateState = boxContainerUpdateState;
return b;
}
uiBox *uiNewHorizontalBox(void)
{
return finishNewBox(0);
}
uiBox *uiNewVerticalBox(void)
{
return finishNewBox(1);
}

View File

@ -10,11 +10,11 @@ uintmax_t uiWindowsControlType(void)
return type_uiWindowsControl;
}
Control ^genericHandle(uiControl *c)
UIElement ^genericHandle(uiControl *c)
{
gcroot<Control ^> *h;
gcroot<UIElement ^> *h;
h = (gcroot<Control ^> *) uiControlHandle(c);
h = (gcroot<UIElement ^> *) uiControlHandle(c);
return *h;
}

View File

@ -75,6 +75,7 @@
<ClCompile Include="alloc.c">
<CompileAsManaged>false</CompileAsManaged>
</ClCompile>
<ClCompile Include="box.cpp" />
<ClCompile Include="button.cpp" />
<ClCompile Include="control.cpp" />
<ClCompile Include="debug.c">

View File

@ -19,7 +19,7 @@ typedef struct uiWindowsControl uiWindowsControl;
struct uiWindowsControl {
uiControl c;
// TODO make truly private
gcroot<System::Windows::Controls::Control ^> *genericHandle;
gcroot<System::Windows::UIElement ^> *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<System::Windows::Controls::Control ^>(); \
uiWindowsControl(variable)->genericHandle = new gcroot<System::Windows::UIElement ^>(); \
*(uiWindowsControl(variable)->genericHandle) = *(variable->handle); \
uiWindowsFinishControl(uiControl(variable));

View File

@ -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);

View File

@ -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();

View File

@ -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)