Smoke test of the GUI, at last on Linux.
This commit is contained in:
parent
06d8609200
commit
0457282d47
5 changed files with 79 additions and 440 deletions
12
Makefile
12
Makefile
|
|
@ -1,18 +1,21 @@
|
|||
PACKAGES = zlib sqlite3 libusb-1.0 protobuf
|
||||
PACKAGES = zlib sqlite3 libusb-1.0 protobuf gtk+-3.0
|
||||
|
||||
export CFLAGS = -x c++ --std=gnu++2a -ffunction-sections -fdata-sections \
|
||||
export CFLAGS = -ffunction-sections -fdata-sections
|
||||
export CXXFLAGS = $(CFLAGS) \
|
||||
--std=gnu++2a \
|
||||
-Wno-deprecated-enum-enum-conversion \
|
||||
-Wno-deprecated-enum-float-conversion
|
||||
export LDFLAGS = -pthread
|
||||
|
||||
export COPTFLAGS = -Os
|
||||
export LDOPTFLAGS = -Os
|
||||
export LDOPTFLAGS = -Os -ldl
|
||||
|
||||
export CDBGFLAGS = -O0 -g
|
||||
export LDDBGFLAGS = -O0 -g
|
||||
export LDDBGFLAGS = -O0 -g -ldl
|
||||
|
||||
ifeq ($(OS), Windows_NT)
|
||||
export PROTOC = /mingw32/bin/protoc
|
||||
export CC = /mingw32/bin/gcc
|
||||
export CXX = /mingw32/bin/g++
|
||||
export AR = /mingw32/bin/ar rc
|
||||
export RANLIB = /mingw32/bin/ranlib
|
||||
|
|
@ -30,6 +33,7 @@ $(error You must have these pkg-config packages installed: $(PACKAGES))
|
|||
endif
|
||||
|
||||
export PROTOC = protoc
|
||||
export CC = gcc
|
||||
export CXX = g++
|
||||
export AR = ar rc
|
||||
export RANLIB = ranlib
|
||||
|
|
|
|||
|
|
@ -1,22 +0,0 @@
|
|||
// 21 june 2016
|
||||
#include "../ui.h"
|
||||
#include "uipriv.h"
|
||||
|
||||
void *uiTableModelGiveInt(int i)
|
||||
{
|
||||
return (void *) ((intptr_t) i);
|
||||
}
|
||||
|
||||
int uiTableModelTakeInt(void *v)
|
||||
{
|
||||
return (int) ((intptr_t) v);
|
||||
}
|
||||
|
||||
uiTableColumn *uiTableAppendTextColumn(uiTable *t, const char *name, int modelColumn)
|
||||
{
|
||||
uiTableColumn *tc;
|
||||
|
||||
tc = uiTableAppendColumn(t, name);
|
||||
uiTableColumnAppendTextPart(tc, modelColumn, 1);
|
||||
return tc;
|
||||
}
|
||||
|
|
@ -1,406 +0,0 @@
|
|||
// 26 june 2016
|
||||
#include "uipriv_unix.h"
|
||||
|
||||
void *uiTableModelStrdup(const char *str)
|
||||
{
|
||||
return g_strdup(str);
|
||||
}
|
||||
|
||||
void *uiTableModelGiveColor(double r, double g, double b, double a)
|
||||
{
|
||||
GdkRGBA rgba;
|
||||
|
||||
rgba.red = r;
|
||||
rgba.green = g;
|
||||
rgba.blue = b;
|
||||
rgba.alpha = a;
|
||||
return gdk_rgba_copy(&rgba);
|
||||
}
|
||||
|
||||
uiTableModel *uiNewTableModel(uiTableModelHandler *mh)
|
||||
{
|
||||
uiTableModel *m;
|
||||
|
||||
m = uiTableModel(g_object_new(uiTableModelType, NULL));
|
||||
m->mh = mh;
|
||||
return m;
|
||||
}
|
||||
|
||||
void uiFreeTableModel(uiTableModel *m)
|
||||
{
|
||||
g_object_unref(m);
|
||||
}
|
||||
|
||||
void uiTableModelRowInserted(uiTableModel *m, int newIndex)
|
||||
{
|
||||
GtkTreePath *path;
|
||||
GtkTreeIter iter;
|
||||
|
||||
path = gtk_tree_path_new_from_indices(newIndex, -1);
|
||||
iter.stamp = STAMP_GOOD;
|
||||
iter.user_data = GINT_TO_POINTER(newIndex);
|
||||
gtk_tree_model_row_inserted(GTK_TREE_MODEL(m), path, &iter);
|
||||
gtk_tree_path_free(path);
|
||||
}
|
||||
|
||||
void uiTableModelRowChanged(uiTableModel *m, int index)
|
||||
{
|
||||
GtkTreePath *path;
|
||||
GtkTreeIter iter;
|
||||
|
||||
path = gtk_tree_path_new_from_indices(index, -1);
|
||||
iter.stamp = STAMP_GOOD;
|
||||
iter.user_data = GINT_TO_POINTER(index);
|
||||
gtk_tree_model_row_changed(GTK_TREE_MODEL(m), path, &iter);
|
||||
gtk_tree_path_free(path);
|
||||
}
|
||||
|
||||
void uiTableModelRowDeleted(uiTableModel *m, int oldIndex)
|
||||
{
|
||||
GtkTreePath *path;
|
||||
|
||||
path = gtk_tree_path_new_from_indices(oldIndex, -1);
|
||||
gtk_tree_model_row_deleted(GTK_TREE_MODEL(m), path);
|
||||
gtk_tree_path_free(path);
|
||||
}
|
||||
|
||||
enum {
|
||||
partText,
|
||||
partImage,
|
||||
partButton,
|
||||
partCheckbox,
|
||||
partProgressBar,
|
||||
};
|
||||
|
||||
struct tablePart {
|
||||
int type;
|
||||
int textColumn;
|
||||
int imageColumn;
|
||||
int valueColumn;
|
||||
int colorColumn;
|
||||
GtkCellRenderer *r;
|
||||
uiTable *tv; // for pixbufs and background color
|
||||
};
|
||||
|
||||
struct uiTableColumn {
|
||||
GtkTreeViewColumn *c;
|
||||
uiTable *tv; // for pixbufs and background color
|
||||
GPtrArray *parts;
|
||||
};
|
||||
|
||||
struct uiTable {
|
||||
uiUnixControl c;
|
||||
GtkWidget *widget;
|
||||
GtkContainer *scontainer;
|
||||
GtkScrolledWindow *sw;
|
||||
GtkWidget *treeWidget;
|
||||
GtkTreeView *tv;
|
||||
GPtrArray *columns;
|
||||
uiTableModel *model;
|
||||
int backgroundColumn;
|
||||
};
|
||||
|
||||
// use the same size as GtkFileChooserWidget's treeview
|
||||
// TODO refresh when icon theme changes
|
||||
// TODO doesn't work when scaled
|
||||
// TODO is this even necessary?
|
||||
static void setImageSize(GtkCellRenderer *r)
|
||||
{
|
||||
gint size;
|
||||
gint width, height;
|
||||
gint xpad, ypad;
|
||||
|
||||
size = 16; // fallback used by GtkFileChooserWidget
|
||||
if (gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &width, &height) != FALSE)
|
||||
size = MAX(width, height);
|
||||
gtk_cell_renderer_get_padding(r, &xpad, &ypad);
|
||||
gtk_cell_renderer_set_fixed_size(r,
|
||||
2 * xpad + size,
|
||||
2 * ypad + size);
|
||||
}
|
||||
|
||||
static void applyColor(GtkTreeModel *mm, GtkTreeIter *iter, int modelColumn, GtkCellRenderer *r, const char *prop, const char *propSet)
|
||||
{
|
||||
GValue value = G_VALUE_INIT;
|
||||
GdkRGBA *rgba;
|
||||
|
||||
gtk_tree_model_get_value(mm, iter, modelColumn, &value);
|
||||
rgba = (GdkRGBA *) g_value_get_boxed(&value);
|
||||
if (rgba != NULL)
|
||||
g_object_set(r, prop, rgba, NULL);
|
||||
else
|
||||
g_object_set(r, propSet, FALSE, NULL);
|
||||
g_value_unset(&value);
|
||||
}
|
||||
|
||||
static void dataFunc(GtkTreeViewColumn *c, GtkCellRenderer *r, GtkTreeModel *mm, GtkTreeIter *iter, gpointer data)
|
||||
{
|
||||
struct tablePart *part = (struct tablePart *) data;
|
||||
GValue value = G_VALUE_INIT;
|
||||
const gchar *str;
|
||||
uiImage *img;
|
||||
int pval;
|
||||
|
||||
switch (part->type) {
|
||||
case partText:
|
||||
gtk_tree_model_get_value(mm, iter, part->textColumn, &value);
|
||||
str = g_value_get_string(&value);
|
||||
g_object_set(r, "text", str, NULL);
|
||||
if (part->colorColumn != -1)
|
||||
applyColor(mm, iter,
|
||||
part->colorColumn,
|
||||
r, "foreground-rgba", "foreground-set");
|
||||
break;
|
||||
case partImage:
|
||||
//TODO setImageSize(r);
|
||||
gtk_tree_model_get_value(mm, iter, part->imageColumn, &value);
|
||||
img = (uiImage *) g_value_get_pointer(&value);
|
||||
g_object_set(r, "surface",
|
||||
uiprivImageAppropriateSurface(img, part->tv->treeWidget),
|
||||
NULL);
|
||||
break;
|
||||
case partButton:
|
||||
gtk_tree_model_get_value(mm, iter, part->textColumn, &value);
|
||||
str = g_value_get_string(&value);
|
||||
g_object_set(r, "text", str, NULL);
|
||||
break;
|
||||
case partCheckbox:
|
||||
gtk_tree_model_get_value(mm, iter, part->valueColumn, &value);
|
||||
g_object_set(r, "active", g_value_get_int(&value) != 0, NULL);
|
||||
break;
|
||||
case partProgressBar:
|
||||
gtk_tree_model_get_value(mm, iter, part->valueColumn, &value);
|
||||
pval = g_value_get_int(&value);
|
||||
if (pval == -1) {
|
||||
// TODO
|
||||
} else
|
||||
g_object_set(r,
|
||||
"pulse", -1,
|
||||
"value", pval,
|
||||
NULL);
|
||||
break;
|
||||
}
|
||||
g_value_unset(&value);
|
||||
|
||||
if (part->tv->backgroundColumn != -1)
|
||||
applyColor(mm, iter,
|
||||
part->tv->backgroundColumn,
|
||||
r, "cell-background-rgba", "cell-background-set");
|
||||
}
|
||||
|
||||
static void onEdited(struct tablePart *part, int column, const char *pathstr, const void *data)
|
||||
{
|
||||
GtkTreePath *path;
|
||||
int row;
|
||||
uiTableModel *m;
|
||||
|
||||
path = gtk_tree_path_new_from_string(pathstr);
|
||||
row = gtk_tree_path_get_indices(path)[0];
|
||||
gtk_tree_path_free(path);
|
||||
m = part->tv->model;
|
||||
(*(m->mh->SetCellValue))(m->mh, m, row, column, data);
|
||||
// and update
|
||||
uiTableModelRowChanged(m, row);
|
||||
}
|
||||
|
||||
static void appendPart(uiTableColumn *c, struct tablePart *part, GtkCellRenderer *r, int expand)
|
||||
{
|
||||
part->r = r;
|
||||
gtk_tree_view_column_pack_start(c->c, part->r, expand != 0);
|
||||
gtk_tree_view_column_set_cell_data_func(c->c, part->r, dataFunc, part, NULL);
|
||||
g_ptr_array_add(c->parts, part);
|
||||
}
|
||||
|
||||
static void textEdited(GtkCellRendererText *renderer, gchar *path, gchar *newText, gpointer data)
|
||||
{
|
||||
struct tablePart *part = (struct tablePart *) data;
|
||||
|
||||
onEdited(part, part->textColumn, path, newText);
|
||||
}
|
||||
|
||||
void uiTableColumnAppendTextPart(uiTableColumn *c, int modelColumn, int expand)
|
||||
{
|
||||
struct tablePart *part;
|
||||
GtkCellRenderer *r;
|
||||
|
||||
part = uiprivNew(struct tablePart);
|
||||
part->type = partText;
|
||||
part->textColumn = modelColumn;
|
||||
part->tv = c->tv;
|
||||
part->colorColumn = -1;
|
||||
|
||||
r = gtk_cell_renderer_text_new();
|
||||
g_object_set(r, "editable", FALSE, NULL);
|
||||
g_signal_connect(r, "edited", G_CALLBACK(textEdited), part);
|
||||
|
||||
appendPart(c, part, r, expand);
|
||||
}
|
||||
|
||||
void uiTableColumnAppendImagePart(uiTableColumn *c, int modelColumn, int expand)
|
||||
{
|
||||
struct tablePart *part;
|
||||
|
||||
part = uiprivNew(struct tablePart);
|
||||
part->type = partImage;
|
||||
part->imageColumn = modelColumn;
|
||||
part->tv = c->tv;
|
||||
appendPart(c, part,
|
||||
gtk_cell_renderer_pixbuf_new(),
|
||||
expand);
|
||||
}
|
||||
|
||||
// TODO wrong type here
|
||||
static void buttonClicked(GtkCellRenderer *r, gchar *pathstr, gpointer data)
|
||||
{
|
||||
struct tablePart *part = (struct tablePart *) data;
|
||||
|
||||
onEdited(part, part->textColumn, pathstr, NULL);
|
||||
}
|
||||
|
||||
void uiTableColumnAppendButtonPart(uiTableColumn *c, int modelColumn, int expand)
|
||||
{
|
||||
struct tablePart *part;
|
||||
GtkCellRenderer *r;
|
||||
|
||||
part = uiprivNew(struct tablePart);
|
||||
part->type = partButton;
|
||||
part->textColumn = modelColumn;
|
||||
part->tv = c->tv;
|
||||
|
||||
r = uiprivNewCellRendererButton();
|
||||
g_object_set(r, "sensitive", TRUE, NULL); // editable by default
|
||||
g_signal_connect(r, "clicked", G_CALLBACK(buttonClicked), part);
|
||||
|
||||
appendPart(c, part, r, expand);
|
||||
}
|
||||
|
||||
// yes, we need to do all this twice :|
|
||||
static void checkboxToggled(GtkCellRendererToggle *r, gchar *pathstr, gpointer data)
|
||||
{
|
||||
struct tablePart *part = (struct tablePart *) data;
|
||||
GtkTreePath *path;
|
||||
int row;
|
||||
uiTableModel *m;
|
||||
void *value;
|
||||
int intval;
|
||||
|
||||
path = gtk_tree_path_new_from_string(pathstr);
|
||||
row = gtk_tree_path_get_indices(path)[0];
|
||||
gtk_tree_path_free(path);
|
||||
m = part->tv->model;
|
||||
value = (*(m->mh->CellValue))(m->mh, m, row, part->valueColumn);
|
||||
intval = !uiTableModelTakeInt(value);
|
||||
onEdited(part, part->valueColumn, pathstr, uiTableModelGiveInt(intval));
|
||||
}
|
||||
|
||||
void uiTableColumnAppendCheckboxPart(uiTableColumn *c, int modelColumn, int expand)
|
||||
{
|
||||
struct tablePart *part;
|
||||
GtkCellRenderer *r;
|
||||
|
||||
part = uiprivNew(struct tablePart);
|
||||
part->type = partCheckbox;
|
||||
part->valueColumn = modelColumn;
|
||||
part->tv = c->tv;
|
||||
|
||||
r = gtk_cell_renderer_toggle_new();
|
||||
g_object_set(r, "sensitive", TRUE, NULL); // editable by default
|
||||
g_signal_connect(r, "toggled", G_CALLBACK(checkboxToggled), part);
|
||||
|
||||
appendPart(c, part, r, expand);
|
||||
}
|
||||
|
||||
void uiTableColumnAppendProgressBarPart(uiTableColumn *c, int modelColumn, int expand)
|
||||
{
|
||||
struct tablePart *part;
|
||||
|
||||
part = uiprivNew(struct tablePart);
|
||||
part->type = partProgressBar;
|
||||
part->valueColumn = modelColumn;
|
||||
part->tv = c->tv;
|
||||
appendPart(c, part,
|
||||
gtk_cell_renderer_progress_new(),
|
||||
expand);
|
||||
}
|
||||
|
||||
void uiTableColumnPartSetEditable(uiTableColumn *c, int part, int editable)
|
||||
{
|
||||
struct tablePart *p;
|
||||
|
||||
p = (struct tablePart *) g_ptr_array_index(c->parts, part);
|
||||
switch (p->type) {
|
||||
case partImage:
|
||||
case partProgressBar:
|
||||
return;
|
||||
case partButton:
|
||||
case partCheckbox:
|
||||
g_object_set(p->r, "sensitive", editable != 0, NULL);
|
||||
return;
|
||||
}
|
||||
g_object_set(p->r, "editable", editable != 0, NULL);
|
||||
}
|
||||
|
||||
void uiTableColumnPartSetTextColor(uiTableColumn *c, int part, int modelColumn)
|
||||
{
|
||||
struct tablePart *p;
|
||||
|
||||
p = (struct tablePart *) g_ptr_array_index(c->parts, part);
|
||||
p->colorColumn = modelColumn;
|
||||
// TODO refresh table
|
||||
}
|
||||
|
||||
uiUnixControlAllDefaultsExceptDestroy(uiTable)
|
||||
|
||||
static void uiTableDestroy(uiControl *c)
|
||||
{
|
||||
uiTable *t = uiTable(c);
|
||||
|
||||
// TODO
|
||||
g_object_unref(t->widget);
|
||||
uiFreeControl(uiControl(t));
|
||||
}
|
||||
|
||||
uiTableColumn *uiTableAppendColumn(uiTable *t, const char *name)
|
||||
{
|
||||
uiTableColumn *c;
|
||||
|
||||
c = uiprivNew(uiTableColumn);
|
||||
c->c = gtk_tree_view_column_new();
|
||||
gtk_tree_view_column_set_resizable(c->c, TRUE);
|
||||
gtk_tree_view_column_set_title(c->c, name);
|
||||
gtk_tree_view_append_column(t->tv, c->c);
|
||||
c->tv = t; // TODO rename field to t, cascade
|
||||
c->parts = g_ptr_array_new();
|
||||
return c;
|
||||
}
|
||||
|
||||
void uiTableSetRowBackgroundColorModelColumn(uiTable *t, int modelColumn)
|
||||
{
|
||||
t->backgroundColumn = modelColumn;
|
||||
// TODO refresh table
|
||||
}
|
||||
|
||||
uiTable *uiNewTable(uiTableModel *model)
|
||||
{
|
||||
uiTable *t;
|
||||
|
||||
uiUnixNewControl(uiTable, t);
|
||||
|
||||
t->model = model;
|
||||
t->backgroundColumn = -1;
|
||||
|
||||
t->widget = gtk_scrolled_window_new(NULL, NULL);
|
||||
t->scontainer = GTK_CONTAINER(t->widget);
|
||||
t->sw = GTK_SCROLLED_WINDOW(t->widget);
|
||||
gtk_scrolled_window_set_shadow_type(t->sw, GTK_SHADOW_IN);
|
||||
|
||||
t->treeWidget = gtk_tree_view_new_with_model(GTK_TREE_MODEL(t->model));
|
||||
t->tv = GTK_TREE_VIEW(t->treeWidget);
|
||||
// TODO set up t->tv
|
||||
|
||||
gtk_container_add(t->scontainer, t->treeWidget);
|
||||
// and make the tree view visible; only the scrolled window's visibility is controlled by libui
|
||||
gtk_widget_show(t->treeWidget);
|
||||
|
||||
return t;
|
||||
}
|
||||
63
mkninja.sh
63
mkninja.sh
|
|
@ -3,11 +3,17 @@ set -e
|
|||
|
||||
cat <<EOF
|
||||
rule cxx
|
||||
command = $CXX $CFLAGS \$flags -I. -c -o \$out \$in -MMD -MF \$out.d
|
||||
command = $CXX $CXXFLAGS \$flags -I. -c -o \$out \$in -MMD -MF \$out.d
|
||||
description = CXX \$out
|
||||
depfile = \$out.d
|
||||
deps = gcc
|
||||
|
||||
rule cc
|
||||
command = $CC $CFLAGS \$flags -I. -c -o \$out \$in -MMD -MF \$out.d
|
||||
description = CC \$out
|
||||
depfile = \$out.d
|
||||
deps = gcc
|
||||
|
||||
rule proto
|
||||
command = (echo \$in > \$def) && $PROTOC \$flags \$in
|
||||
description = PROTO \$in
|
||||
|
|
@ -82,17 +88,34 @@ buildlibrary() {
|
|||
dobjs=
|
||||
for src in "$@"; do
|
||||
local obj
|
||||
local dobj
|
||||
obj="$OBJDIR/opt/${src%%.c*}.o"
|
||||
oobjs="$oobjs $obj"
|
||||
dobj="$OBJDIR/dbg/${src%%.c*}.o"
|
||||
dobjs="$dobjs $dobj"
|
||||
|
||||
echo "build $obj : cxx $src | $deps"
|
||||
echo " flags=$flags $COPTFLAGS"
|
||||
|
||||
obj="$OBJDIR/dbg/${src%%.c*}.o"
|
||||
dobjs="$dobjs $obj"
|
||||
case "${src##*.}" in
|
||||
c)
|
||||
echo "build $obj : cc $src | $deps"
|
||||
echo " flags=$flags $COPTFLAGS"
|
||||
echo "build $dobj : cc $src | $deps"
|
||||
echo " flags=$flags $CDBGFLAGS"
|
||||
;;
|
||||
|
||||
cc|cpp)
|
||||
echo "build $obj : cxx $src | $deps"
|
||||
echo " flags=$flags $COPTFLAGS"
|
||||
echo "build $dobj : cxx $src | $deps"
|
||||
echo " flags=$flags $CDBGFLAGS"
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Unknown file extension" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "build $obj : cxx $src | $deps"
|
||||
echo " flags=$flags $CDBGFLAGS"
|
||||
done
|
||||
|
||||
echo build $OBJDIR/opt/$lib : library $oobjs
|
||||
|
|
@ -277,6 +300,11 @@ buildlibrary libagg.a \
|
|||
dep/stb/stb_image_write.c \
|
||||
dep/agg/src/*.cpp
|
||||
|
||||
buildlibrary libui.a \
|
||||
-Idep/libui \
|
||||
dep/libui/common/*.c \
|
||||
dep/libui/unix/*.c \
|
||||
|
||||
buildlibrary libfmt.a \
|
||||
dep/fmt/format.cc \
|
||||
dep/fmt/os.cc \
|
||||
|
|
@ -451,11 +479,15 @@ done
|
|||
|
||||
buildmktable formats $OBJDIR/formats.cc $FORMATS
|
||||
|
||||
buildlibrary libfrontend.a \
|
||||
buildlibrary libformats.a \
|
||||
-I$OBJDIR/proto \
|
||||
-d $OBJDIR/proto/libconfig.def \
|
||||
$(for a in $FORMATS; do echo $OBJDIR/proto/src/formats/$a.cc; done) \
|
||||
$OBJDIR/formats.cc \
|
||||
|
||||
buildlibrary libfrontend.a \
|
||||
-I$OBJDIR/proto \
|
||||
-d $OBJDIR/proto/libconfig.def \
|
||||
src/fe-analysedriveresponse.cc \
|
||||
src/fe-analyselayout.cc \
|
||||
src/fe-inspect.cc \
|
||||
|
|
@ -470,14 +502,29 @@ buildlibrary libfrontend.a \
|
|||
src/fe-write.cc \
|
||||
src/fluxengine.cc \
|
||||
|
||||
buildlibrary libgui.a \
|
||||
-Idep/libui \
|
||||
src/gui/main.cc
|
||||
|
||||
buildprogram fluxengine \
|
||||
libfrontend.a \
|
||||
libformats.a \
|
||||
libbackend.a \
|
||||
libconfig.a \
|
||||
libfl2.a \
|
||||
libfmt.a \
|
||||
libagg.a \
|
||||
|
||||
buildprogram fluxengine-gui \
|
||||
libgui.a \
|
||||
libformats.a \
|
||||
libbackend.a \
|
||||
libconfig.a \
|
||||
libfl2.a \
|
||||
libfmt.a \
|
||||
libui.a \
|
||||
libagg.a \
|
||||
|
||||
buildlibrary libemu.a \
|
||||
dep/emu/fnmatch.c
|
||||
|
||||
|
|
|
|||
16
src/gui/main.cc
Normal file
16
src/gui/main.cc
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
#include "globals.h"
|
||||
#include "ui.h"
|
||||
|
||||
static uiWindow* mainwin;
|
||||
|
||||
int main(int argc, const char* argv[])
|
||||
{
|
||||
uiInitOptions o = {0};
|
||||
uiInit(&o);
|
||||
|
||||
mainwin = uiNewWindow("example", 640, 480, 1);
|
||||
uiControlShow(uiControl(mainwin));
|
||||
uiMain();
|
||||
return 0;
|
||||
}
|
||||
|
||||
Loading…
Reference in a new issue