Implemented uiBox on WPF.
This commit is contained in:
parent
99521f4801
commit
7e6c3c0abe
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
10
wpf/xtest.c
10
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();
|
||||
|
|
20
wpf/xtest.go
20
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)
|
||||
|
|
Loading…
Reference in New Issue