aboutsummaryrefslogtreecommitdiff
path: root/src/libui_sdl/libui/test
diff options
context:
space:
mode:
Diffstat (limited to 'src/libui_sdl/libui/test')
-rw-r--r--src/libui_sdl/libui/test/CMakeLists.txt38
-rw-r--r--src/libui_sdl/libui/test/drawtests.c1978
-rw-r--r--src/libui_sdl/libui/test/images/andlabs_16x16test_24june2016.pngbin0 -> 272 bytes
-rw-r--r--src/libui_sdl/libui/test/images/andlabs_32x32test_24june2016.pngbin0 -> 432 bytes
-rw-r--r--src/libui_sdl/libui/test/images/gen.go98
-rw-r--r--src/libui_sdl/libui/test/images/tango-icon-theme-0.8.90_16x16_x-office-spreadsheet.pngbin0 -> 704 bytes
-rw-r--r--src/libui_sdl/libui/test/images/tango-icon-theme-0.8.90_32x32_x-office-spreadsheet.pngbin0 -> 1518 bytes
-rw-r--r--src/libui_sdl/libui/test/main.c180
-rw-r--r--src/libui_sdl/libui/test/menus.c112
-rw-r--r--src/libui_sdl/libui/test/page1.c171
-rw-r--r--src/libui_sdl/libui/test/page10.c185
-rw-r--r--src/libui_sdl/libui/test/page11.c54
-rw-r--r--src/libui_sdl/libui/test/page12.c60
-rw-r--r--src/libui_sdl/libui/test/page13.c157
-rw-r--r--src/libui_sdl/libui/test/page14.c350
-rw-r--r--src/libui_sdl/libui/test/page15.c260
-rw-r--r--src/libui_sdl/libui/test/page2.c215
-rw-r--r--src/libui_sdl/libui/test/page3.c69
-rw-r--r--src/libui_sdl/libui/test/page4.c165
-rw-r--r--src/libui_sdl/libui/test/page5.c99
-rw-r--r--src/libui_sdl/libui/test/page6.c126
-rw-r--r--src/libui_sdl/libui/test/page7.c25
-rw-r--r--src/libui_sdl/libui/test/page7a.c139
-rw-r--r--src/libui_sdl/libui/test/page7b.c71
-rw-r--r--src/libui_sdl/libui/test/page7c.c133
-rw-r--r--src/libui_sdl/libui/test/page8.c46
-rw-r--r--src/libui_sdl/libui/test/page9.c289
-rw-r--r--src/libui_sdl/libui/test/resources.rc13
-rw-r--r--src/libui_sdl/libui/test/spaced.c177
-rw-r--r--src/libui_sdl/libui/test/test.h91
-rw-r--r--src/libui_sdl/libui/test/test.manifest20
-rw-r--r--src/libui_sdl/libui/test/test.static.manifest32
32 files changed, 5353 insertions, 0 deletions
diff --git a/src/libui_sdl/libui/test/CMakeLists.txt b/src/libui_sdl/libui/test/CMakeLists.txt
new file mode 100644
index 0000000..e4924bb
--- /dev/null
+++ b/src/libui_sdl/libui/test/CMakeLists.txt
@@ -0,0 +1,38 @@
+# 3 june 2016
+
+if(WIN32)
+ set(_TEST_RESOURCES_RC resources.rc)
+endif()
+
+_add_exec(tester
+ drawtests.c
+ main.c
+ menus.c
+ page1.c
+ page2.c
+ page3.c
+ page4.c
+ page5.c
+ page6.c
+ page7.c
+ page7a.c
+ page7b.c
+ page7c.c
+ page8.c
+ page9.c
+ page10.c
+ page11.c
+ page12.c
+ page13.c
+ page14.c
+ page15.c
+ spaced.c
+ ${_TEST_RESOURCES_RC}
+)
+target_include_directories(tester
+ PRIVATE test
+)
+set_target_properties(tester PROPERTIES
+ OUTPUT_NAME test
+ WIN32_EXECUTABLE FALSE
+)
diff --git a/src/libui_sdl/libui/test/drawtests.c b/src/libui_sdl/libui/test/drawtests.c
new file mode 100644
index 0000000..b6de753
--- /dev/null
+++ b/src/libui_sdl/libui/test/drawtests.c
@@ -0,0 +1,1978 @@
+// 9 october 2015
+#include "test.h"
+
+// TODO
+// - test multiple clips
+// - test saving and restoring clips
+
+struct drawtest {
+ const char *name;
+ void (*draw)(uiAreaDrawParams *p);
+ // TODO mouse event
+};
+
+static void drawOriginal(uiAreaDrawParams *p)
+{
+ uiDrawPath *path;
+ uiDrawBrush brush;
+ uiDrawStrokeParams sp;
+
+ sp.Dashes = NULL;
+ sp.NumDashes = 0;
+ sp.DashPhase = 0;
+
+ brush.Type = uiDrawBrushTypeSolid;
+ brush.A = 1;
+
+ brush.R = 1;
+ brush.G = 0;
+ brush.B = 0;
+ path = uiDrawNewPath(uiDrawFillModeWinding);
+ uiDrawPathNewFigure(path, p->ClipX + 5, p->ClipY + 5);
+ uiDrawPathLineTo(path, (p->ClipX + p->ClipWidth) - 5, (p->ClipY + p->ClipHeight) - 5);
+ uiDrawPathEnd(path);
+ sp.Cap = uiDrawLineCapFlat;
+ sp.Join = uiDrawLineJoinMiter;
+ sp.Thickness = 1;
+ sp.MiterLimit = uiDrawDefaultMiterLimit;
+ uiDrawStroke(p->Context, path, &brush, &sp);
+ uiDrawFreePath(path);
+
+ brush.R = 0;
+ brush.G = 0;
+ brush.B = 0.75;
+ path = uiDrawNewPath(uiDrawFillModeWinding);
+ uiDrawPathNewFigure(path, p->ClipX, p->ClipY);
+ uiDrawPathLineTo(path, p->ClipX + p->ClipWidth, p->ClipY);
+ uiDrawPathLineTo(path, 50, 150);
+ uiDrawPathLineTo(path, 50, 50);
+ uiDrawPathCloseFigure(path);
+ uiDrawPathEnd(path);
+ sp.Cap = uiDrawLineCapFlat;
+ sp.Join = uiDrawLineJoinRound;
+ sp.Thickness = 5;
+ uiDrawStroke(p->Context, path, &brush, &sp);
+ uiDrawFreePath(path);
+
+ brush.R = 0;
+ brush.G = 0.75;
+ brush.B = 0;
+ brush.A = 0.5;
+ path = uiDrawNewPath(uiDrawFillModeWinding);
+ uiDrawPathAddRectangle(path, 120, 80, 50, 50);
+ uiDrawPathEnd(path);
+ uiDrawFill(p->Context, path, &brush);
+ uiDrawFreePath(path);
+ brush.A = 1;
+
+ brush.R = 0;
+ brush.G = 0.5;
+ brush.B = 0;
+ path = uiDrawNewPath(uiDrawFillModeWinding);
+ uiDrawPathNewFigure(path, 5.5, 10.5);
+ uiDrawPathLineTo(path, 5.5, 50.5);
+ uiDrawPathEnd(path);
+ sp.Cap = uiDrawLineCapFlat;
+ sp.Join = uiDrawLineJoinMiter;
+ sp.Thickness = 1;
+ sp.MiterLimit = uiDrawDefaultMiterLimit;
+ uiDrawStroke(p->Context, path, &brush, &sp);
+ uiDrawFreePath(path);
+
+ brush.R = 0.5;
+ brush.G = 0.75;
+ brush.B = 0;
+ path = uiDrawNewPath(uiDrawFillModeWinding);
+ uiDrawPathNewFigure(path, 400, 100);
+ uiDrawPathArcTo(path,
+ 400, 100,
+ 50,
+ 30. * (uiPi / 180.),
+ 300. * (uiPi / 180.),
+ 0);
+ // the sweep test below doubles as a clockwise test so a checkbox isn't needed anymore
+ uiDrawPathLineTo(path, 400, 100);
+ uiDrawPathNewFigureWithArc(path,
+ 510, 100,
+ 50,
+ 30. * (uiPi / 180.),
+ 300. * (uiPi / 180.),
+ 0);
+ uiDrawPathCloseFigure(path);
+ // and now with 330 to make sure sweeps work properly
+ uiDrawPathNewFigure(path, 400, 210);
+ uiDrawPathArcTo(path,
+ 400, 210,
+ 50,
+ 30. * (uiPi / 180.),
+ 330. * (uiPi / 180.),
+ 0);
+ uiDrawPathLineTo(path, 400, 210);
+ uiDrawPathNewFigureWithArc(path,
+ 510, 210,
+ 50,
+ 30. * (uiPi / 180.),
+ 330. * (uiPi / 180.),
+ 0);
+ uiDrawPathCloseFigure(path);
+ uiDrawPathEnd(path);
+ sp.Cap = uiDrawLineCapFlat;
+ sp.Join = uiDrawLineJoinMiter;
+ sp.Thickness = 1;
+ sp.MiterLimit = uiDrawDefaultMiterLimit;
+ uiDrawStroke(p->Context, path, &brush, &sp);
+ uiDrawFreePath(path);
+
+ brush.R = 0;
+ brush.G = 0.5;
+ brush.B = 0.75;
+ path = uiDrawNewPath(uiDrawFillModeWinding);
+ uiDrawPathNewFigure(path, 300, 300);
+ uiDrawPathBezierTo(path,
+ 350, 320,
+ 310, 390,
+ 435, 372);
+ uiDrawPathEnd(path);
+ sp.Cap = uiDrawLineCapFlat;
+ sp.Join = uiDrawLineJoinMiter;
+ sp.Thickness = 1;
+ sp.MiterLimit = uiDrawDefaultMiterLimit;
+ uiDrawStroke(p->Context, path, &brush, &sp);
+ uiDrawFreePath(path);
+}
+
+static void drawArcs(uiAreaDrawParams *p)
+{
+ uiDrawPath *path;
+ int start = 20;
+ int step = 20;
+ int rad = 25;
+ int x, y;
+ double angle;
+ double add;
+ int i;
+ uiDrawBrush brush;
+ uiDrawStrokeParams sp;
+
+ sp.Dashes = NULL;
+ sp.NumDashes = 0;
+ sp.DashPhase = 0;
+
+ path = uiDrawNewPath(uiDrawFillModeWinding);
+
+ add = (2.0 * uiPi) / 12;
+
+ x = start + rad;
+ y = start + rad;
+ angle = 0;
+ for (i = 0; i < 13; i++) {
+ uiDrawPathNewFigureWithArc(path,
+ x, y,
+ rad,
+ 0, angle,
+ 0);
+ angle += add;
+ x += 2 * rad + step;
+ }
+
+ y += 2 * rad + step;
+ x = start + rad;
+ angle = 0;
+ for (i = 0; i < 13; i++) {
+ uiDrawPathNewFigure(path, x, y);
+ uiDrawPathArcTo(path,
+ x, y,
+ rad,
+ 0, angle,
+ 0);
+ angle += add;
+ x += 2 * rad + step;
+ }
+
+ y += 2 * rad + step;
+ x = start + rad;
+ angle = 0;
+ for (i = 0; i < 13; i++) {
+ uiDrawPathNewFigureWithArc(path,
+ x, y,
+ rad,
+ (uiPi / 4), angle,
+ 0);
+ angle += add;
+ x += 2 * rad + step;
+ }
+
+ y += 2 * rad + step;
+ x = start + rad;
+ angle = 0;
+ for (i = 0; i < 13; i++) {
+ uiDrawPathNewFigure(path, x, y);
+ uiDrawPathArcTo(path,
+ x, y,
+ rad,
+ (uiPi / 4), angle,
+ 0);
+ angle += add;
+ x += 2 * rad + step;
+ }
+
+ y += 2 * rad + step;
+ x = start + rad;
+ angle = 0;
+ for (i = 0; i < 13; i++) {
+ uiDrawPathNewFigureWithArc(path,
+ x, y,
+ rad,
+ uiPi + (uiPi / 5), angle,
+ 0);
+ angle += add;
+ x += 2 * rad + step;
+ }
+
+ y += 2 * rad + step;
+ x = start + rad;
+ angle = 0;
+ for (i = 0; i < 13; i++) {
+ uiDrawPathNewFigure(path, x, y);
+ uiDrawPathArcTo(path,
+ x, y,
+ rad,
+ uiPi + (uiPi / 5), angle,
+ 0);
+ angle += add;
+ x += 2 * rad + step;
+ }
+
+ uiDrawPathEnd(path);
+
+ brush.Type = uiDrawBrushTypeSolid;
+ brush.R = 0;
+ brush.G = 0;
+ brush.B = 0;
+ brush.A = 1;
+ sp.Cap = uiDrawLineCapFlat;
+ sp.Join = uiDrawLineJoinMiter;
+ sp.Thickness = 1;
+ sp.MiterLimit = uiDrawDefaultMiterLimit;
+ uiDrawStroke(p->Context, path, &brush, &sp);
+
+ uiDrawFreePath(path);
+}
+
+// Direct2D Documentation Code
+
+static void d2dColorToRGB(uint32_t color, double *r, double *g, double *b)
+{
+ uint8_t rr, gg, bb;
+
+ rr = (color & 0xFF0000) >> 16;
+ gg = (color & 0x00FF00) >> 8;
+ bb = color & 0x0000FF;
+ *r = ((double) rr) / 255.0;
+ *g = ((double) gg) / 255.0;
+ *b = ((double) bb) / 255.0;
+}
+#define d2dBlack 0x000000
+#define d2dLightSlateGray 0x778899
+#define d2dCornflowerBlue 0x6495ED
+#define d2dWhite 0xFFFFFF
+#define d2dYellowGreen 0x9ACD32
+#define d2dYellow 0xFFFF00
+#define d2dForestGreen 0x228B22
+#define d2dOliveDrab 0x6B8E23
+#define d2dLightSkyBlue 0x87CEFA
+
+static void d2dSolidBrush(uiDrawBrush *brush, uint32_t color, double alpha)
+{
+ brush->Type = uiDrawBrushTypeSolid;
+ d2dColorToRGB(color, &(brush->R), &(brush->G), &(brush->B));
+ brush->A = alpha;
+}
+
+static void d2dClear(uiAreaDrawParams *p, uint32_t color, double alpha)
+{
+ uiDrawPath *path;
+ uiDrawBrush brush;
+
+ d2dSolidBrush(&brush, color, alpha);
+ path = uiDrawNewPath(uiDrawFillModeWinding);
+ uiDrawPathAddRectangle(path, 0, 0, p->AreaWidth, p->AreaHeight);
+ uiDrawPathEnd(path);
+ uiDrawFill(p->Context, path, &brush);
+ uiDrawFreePath(path);
+}
+
+// from https://msdn.microsoft.com/en-us/library/windows/desktop/hh780340%28v=vs.85%29.aspx
+// also at https://msdn.microsoft.com/en-us/library/windows/desktop/dd535473%28v=vs.85%29.aspx
+static void drawD2DW8QS(uiAreaDrawParams *p)
+{
+ uiDrawPath *path;
+ uiDrawBrush brush;
+
+ d2dSolidBrush(&brush, d2dBlack, 1.0);
+ path = uiDrawNewPath(uiDrawFillModeWinding);
+ uiDrawPathAddRectangle(path,
+ 100,
+ 100,
+ (p->AreaWidth - 100) - 100,
+ (p->AreaHeight - 100) - 100);
+ uiDrawPathEnd(path);
+ uiDrawFill(p->Context, path, &brush);
+ uiDrawFreePath(path);
+}
+
+// from https://msdn.microsoft.com/en-us/library/windows/desktop/dd370994%28v=vs.85%29.aspx
+static void drawD2DSimpleApp(uiAreaDrawParams *p)
+{
+ uiDrawPath *path;
+ uiDrawBrush lightSlateGray;
+ uiDrawBrush cornflowerBlue;
+ uiDrawStrokeParams sp;
+ int x, y;
+
+ sp.Dashes = NULL;
+ sp.NumDashes = 0;
+ sp.DashPhase = 0;
+
+ d2dSolidBrush(&lightSlateGray, d2dLightSlateGray, 1.0);
+ d2dSolidBrush(&cornflowerBlue, d2dCornflowerBlue, 1.0);
+
+ d2dClear(p, d2dWhite, 1.0);
+
+ sp.Thickness = 0.5;
+ sp.Cap = uiDrawLineCapFlat;
+ sp.Join = uiDrawLineJoinMiter;
+ sp.MiterLimit = uiDrawDefaultMiterLimit;
+
+ for (x = 0; x < p->AreaWidth; x += 10) {
+ path = uiDrawNewPath(uiDrawFillModeWinding);
+ uiDrawPathNewFigure(path, x, 0);
+ uiDrawPathLineTo(path, x, p->AreaHeight);
+ uiDrawPathEnd(path);
+ uiDrawStroke(p->Context, path, &lightSlateGray, &sp);
+ uiDrawFreePath(path);
+ }
+
+ for (y = 0; y < p->AreaHeight; y += 10) {
+ path = uiDrawNewPath(uiDrawFillModeWinding);
+ uiDrawPathNewFigure(path, 0, y);
+ uiDrawPathLineTo(path, p->AreaWidth, y);
+ uiDrawPathEnd(path);
+ uiDrawStroke(p->Context, path, &lightSlateGray, &sp);
+ uiDrawFreePath(path);
+ }
+
+ double left, top, right, bottom;
+
+ left = p->AreaWidth / 2.0 - 50.0;
+ right = p->AreaWidth / 2.0 + 50.0;
+ top = p->AreaHeight / 2.0 - 50.0;
+ bottom = p->AreaHeight / 2.0 + 50.0;
+ path = uiDrawNewPath(uiDrawFillModeWinding);
+ uiDrawPathAddRectangle(path, left, top, right - left, bottom - top);
+ uiDrawPathEnd(path);
+ uiDrawFill(p->Context, path, &lightSlateGray);
+ uiDrawFreePath(path);
+
+ left = p->AreaWidth / 2.0 - 100.0;
+ right = p->AreaWidth / 2.0 + 100.0;
+ top = p->AreaHeight / 2.0 - 100.0;
+ bottom = p->AreaHeight / 2.0 + 100.0;
+ path = uiDrawNewPath(uiDrawFillModeWinding);
+ uiDrawPathAddRectangle(path, left, top, right - left, bottom - top);
+ uiDrawPathEnd(path);
+ sp.Thickness = 1.0;
+ uiDrawStroke(p->Context, path, &cornflowerBlue, &sp);
+ uiDrawFreePath(path);
+}
+
+// TODO? https://msdn.microsoft.com/en-us/library/windows/desktop/dd372260(v=vs.85).aspx
+
+// TODO https://msdn.microsoft.com/en-us/library/windows/desktop/dd756654%28v=vs.85%29.aspx
+
+// TODO? all subsections too? https://msdn.microsoft.com/en-us/library/windows/desktop/hh973240%28v=vs.85%29.aspx
+
+// TODO differing examples of? https://msdn.microsoft.com/en-us/library/windows/desktop/dd756651%28v=vs.85%29.aspx
+
+// from https://msdn.microsoft.com/en-us/library/windows/desktop/dd756680%28v=vs.85%29.aspx
+static void drawD2DSolidBrush(uiAreaDrawParams *p)
+{
+ uiDrawPath *path;
+ uiDrawBrush black;
+ uiDrawBrush yellowGreen;
+ uiDrawStrokeParams sp;
+
+ sp.Dashes = NULL;
+ sp.NumDashes = 0;
+ sp.DashPhase = 0;
+
+ d2dSolidBrush(&black, d2dBlack, 1.0);
+ d2dSolidBrush(&yellowGreen, d2dYellowGreen, 1.0);
+
+ path = uiDrawNewPath(uiDrawFillModeWinding);
+ // the example doesn't define a rectangle
+ // 150x150 seems to be right given the other examples though
+ uiDrawPathAddRectangle(path, 25, 25, 150, 150);
+ uiDrawPathEnd(path);
+
+ uiDrawFill(p->Context, path, &yellowGreen);
+ sp.Thickness = 1.0;
+ sp.Cap = uiDrawLineCapFlat;
+ sp.Join = uiDrawLineJoinMiter;
+ sp.MiterLimit = uiDrawDefaultMiterLimit;
+ uiDrawStroke(p->Context, path, &black, &sp);
+
+ uiDrawFreePath(path);
+}
+
+// from https://msdn.microsoft.com/en-us/library/windows/desktop/dd756678%28v=vs.85%29.aspx
+static void drawD2DLinearBrush(uiAreaDrawParams *p)
+{
+ uiDrawPath *path;
+ uiDrawBrush black;
+ uiDrawBrush gradient;
+ uiDrawBrushGradientStop stops[2];
+ uiDrawStrokeParams sp;
+
+ uiDrawMatrix m;
+
+ sp.Dashes = NULL;
+ sp.NumDashes = 0;
+ sp.DashPhase = 0;
+
+ // leave some room
+ uiDrawMatrixSetIdentity(&m);
+ uiDrawMatrixTranslate(&m, 25, 25);
+ uiDrawTransform(p->Context, &m);
+
+ gradient.Type = uiDrawBrushTypeLinearGradient;
+ gradient.X0 = 0;
+ gradient.Y0 = 0;
+ gradient.X1 = 150;
+ gradient.Y1 = 150;
+ stops[0].Pos = 0.0;
+ d2dColorToRGB(d2dYellow, &(stops[0].R), &(stops[0].G), &(stops[0].B));
+ stops[0].A = 1.0;
+ stops[1].Pos = 1.0;
+ d2dColorToRGB(d2dForestGreen, &(stops[1].R), &(stops[1].G), &(stops[1].B));
+ stops[1].A = 1.0;
+ gradient.Stops = stops;
+ gradient.NumStops = 2;
+
+ d2dSolidBrush(&black, d2dBlack, 1.0);
+
+ path = uiDrawNewPath(uiDrawFillModeWinding);
+ uiDrawPathAddRectangle(path, 0, 0, 150, 150);
+ uiDrawPathEnd(path);
+
+ uiDrawFill(p->Context, path, &gradient);
+ sp.Thickness = 1.0;
+ sp.Cap = uiDrawLineCapFlat;
+ sp.Join = uiDrawLineJoinMiter;
+ sp.MiterLimit = uiDrawDefaultMiterLimit;
+ uiDrawStroke(p->Context, path, &black, &sp);
+
+ uiDrawFreePath(path);
+}
+
+// from https://msdn.microsoft.com/en-us/library/windows/desktop/dd756679%28v=vs.85%29.aspx
+// TODO expand this to change the origin point with a mouse click (not in the original but useful to have)
+static void drawD2DRadialBrush(uiAreaDrawParams *p)
+{
+ uiDrawPath *path;
+ uiDrawBrush black;
+ uiDrawBrush gradient;
+ uiDrawBrushGradientStop stops[2];
+ uiDrawStrokeParams sp;
+
+ uiDrawMatrix m;
+
+ sp.Dashes = NULL;
+ sp.NumDashes = 0;
+ sp.DashPhase = 0;
+
+ // leave some room
+ uiDrawMatrixSetIdentity(&m);
+ uiDrawMatrixTranslate(&m, 25, 25);
+ uiDrawTransform(p->Context, &m);
+
+ gradient.Type = uiDrawBrushTypeRadialGradient;
+ gradient.X0 = 75;
+ gradient.Y0 = 75;
+ gradient.X1 = 75;
+ gradient.Y1 = 75;
+ gradient.OuterRadius = 75;
+ stops[0].Pos = 0.0;
+ d2dColorToRGB(d2dYellow, &(stops[0].R), &(stops[0].G), &(stops[0].B));
+ stops[0].A = 1.0;
+ stops[1].Pos = 1.0;
+ d2dColorToRGB(d2dForestGreen, &(stops[1].R), &(stops[1].G), &(stops[1].B));
+ stops[1].A = 1.0;
+ gradient.Stops = stops;
+ gradient.NumStops = 2;
+
+ d2dSolidBrush(&black, d2dBlack, 1.0);
+
+ path = uiDrawNewPath(uiDrawFillModeWinding);
+ uiDrawPathNewFigure(path, 150, 75);
+ uiDrawPathArcTo(path,
+ 75, 75,
+ 75,
+ 0,
+ 2 * uiPi,
+ 0);
+ uiDrawPathEnd(path);
+
+ uiDrawFill(p->Context, path, &gradient);
+ sp.Thickness = 1.0;
+ sp.Cap = uiDrawLineCapFlat;
+ sp.Join = uiDrawLineJoinMiter;
+ sp.MiterLimit = uiDrawDefaultMiterLimit;
+ uiDrawStroke(p->Context, path, &black, &sp);
+
+ uiDrawFreePath(path);
+}
+
+// TODO https://msdn.microsoft.com/en-us/library/windows/desktop/dd756677%28v=vs.85%29.aspx
+
+// TODO? other pages have some of these https://msdn.microsoft.com/en-us/library/windows/desktop/dd756653%28v=vs.85%29.aspx
+
+// from https://msdn.microsoft.com/en-us/library/windows/desktop/ee264309%28v=vs.85%29.aspx
+static void drawD2DPathGeometries(uiAreaDrawParams *p)
+{
+ uiDrawPath *leftMountain;
+ uiDrawPath *rightMountain;
+ uiDrawPath *sun;
+ uiDrawPath *sunRays;
+ uiDrawPath *river;
+ uiDrawBrush radial;
+ uiDrawBrush scene;
+ uiDrawStrokeParams sp;
+ uiDrawBrushGradientStop stops[2];
+
+ sp.Dashes = NULL;
+ sp.NumDashes = 0;
+ sp.DashPhase = 0;
+
+ // TODO this is definitely wrong but the example doesn't have the right brush in it
+ radial.Type = uiDrawBrushTypeRadialGradient;
+ radial.X0 = 75;
+ radial.Y0 = 75;
+ radial.X1 = 75;
+ radial.Y1 = 75;
+ radial.OuterRadius = 75;
+ stops[0].Pos = 0.0;
+ d2dColorToRGB(d2dYellow, &(stops[0].R), &(stops[0].G), &(stops[0].B));
+ stops[0].A = 1.0;
+ stops[1].Pos = 1.0;
+ d2dColorToRGB(d2dForestGreen, &(stops[1].R), &(stops[1].G), &(stops[1].B));
+ stops[1].A = 1.0;
+ radial.Stops = stops;
+ radial.NumStops = 2;
+
+ leftMountain = uiDrawNewPath(uiDrawFillModeWinding);
+ uiDrawPathNewFigure(leftMountain, 346, 255);
+ uiDrawPathLineTo(leftMountain, 267, 177);
+ uiDrawPathLineTo(leftMountain, 236, 192);
+ uiDrawPathLineTo(leftMountain, 212, 160);
+ uiDrawPathLineTo(leftMountain, 156, 255);
+ uiDrawPathLineTo(leftMountain, 346, 255);
+ uiDrawPathCloseFigure(leftMountain);
+ uiDrawPathEnd(leftMountain);
+
+ rightMountain = uiDrawNewPath(uiDrawFillModeWinding);
+ uiDrawPathNewFigure(rightMountain, 575, 263);
+ uiDrawPathLineTo(rightMountain, 481, 146);
+ uiDrawPathLineTo(rightMountain, 449, 181);
+ uiDrawPathLineTo(rightMountain, 433, 159);
+ uiDrawPathLineTo(rightMountain, 401, 214);
+ uiDrawPathLineTo(rightMountain, 381, 199);
+ uiDrawPathLineTo(rightMountain, 323, 263);
+ uiDrawPathLineTo(rightMountain, 575, 263);
+ uiDrawPathCloseFigure(rightMountain);
+ uiDrawPathEnd(rightMountain);
+
+ sun = uiDrawNewPath(uiDrawFillModeWinding);
+ uiDrawPathNewFigureWithArc(sun,
+ (440.0 - 270.0) / 2 + 270.0, 255,
+ 85,
+ uiPi, uiPi,
+ 0);
+ uiDrawPathCloseFigure(sun);
+ uiDrawPathEnd(sun);
+
+ // the original examples had these as hollow figures
+ // we don't support them, so we'll have to stroke it separately
+ sunRays = uiDrawNewPath(uiDrawFillModeWinding);
+ uiDrawPathNewFigure(sunRays, 299, 182);
+ uiDrawPathBezierTo(sunRays,
+ 299, 182,
+ 294, 176,
+ 285, 178);
+ uiDrawPathBezierTo(sunRays,
+ 276, 179,
+ 272, 173,
+ 272, 173);
+ uiDrawPathNewFigure(sunRays, 354, 156);
+ uiDrawPathBezierTo(sunRays,
+ 354, 156,
+ 358, 149,
+ 354, 142);
+ uiDrawPathBezierTo(sunRays,
+ 349, 134,
+ 354, 127,
+ 354, 127);
+ uiDrawPathNewFigure(sunRays, 322, 164);
+ uiDrawPathBezierTo(sunRays,
+ 322, 164,
+ 322, 156,
+ 314, 152);
+ uiDrawPathBezierTo(sunRays,
+ 306, 149,
+ 305, 141,
+ 305, 141);
+ uiDrawPathNewFigure(sunRays, 385, 164);
+ uiDrawPathBezierTo(sunRays,
+ 385, 164,
+ 392, 161,
+ 394, 152);
+ uiDrawPathBezierTo(sunRays,
+ 395, 144,
+ 402, 141,
+ 402, 142);
+ uiDrawPathNewFigure(sunRays, 408, 182);
+ uiDrawPathBezierTo(sunRays,
+ 408, 182,
+ 416, 184,
+ 422, 178);
+ uiDrawPathBezierTo(sunRays,
+ 428, 171,
+ 435, 173,
+ 435, 173);
+ uiDrawPathEnd(sunRays);
+
+ river = uiDrawNewPath(uiDrawFillModeWinding);
+ uiDrawPathNewFigure(river, 183, 392);
+ uiDrawPathBezierTo(river,
+ 238, 284,
+ 472, 345,
+ 356, 303);
+ uiDrawPathBezierTo(river,
+ 237, 261,
+ 333, 256,
+ 333, 256);
+ uiDrawPathBezierTo(river,
+ 335, 257,
+ 241, 261,
+ 411, 306);
+ uiDrawPathBezierTo(river,
+ 574, 350,
+ 288, 324,
+ 296, 392);
+ uiDrawPathEnd(river);
+
+ d2dClear(p, d2dWhite, 1.0);
+
+ // TODO draw the grid
+
+ uiDrawFill(p->Context, sun, &radial);
+
+ d2dSolidBrush(&scene, d2dBlack, 1.0);
+ sp.Thickness = 1.0;
+ sp.Cap = uiDrawLineCapFlat;
+ sp.Join = uiDrawLineJoinMiter;
+ sp.MiterLimit = uiDrawDefaultMiterLimit;
+ uiDrawStroke(p->Context, sun, &scene, &sp);
+ uiDrawStroke(p->Context, sunRays, &scene, &sp);
+
+ d2dSolidBrush(&scene, d2dOliveDrab, 1.0);
+ uiDrawFill(p->Context, leftMountain, &scene);
+
+ d2dSolidBrush(&scene, d2dBlack, 1.0);
+ uiDrawStroke(p->Context, leftMountain, &scene, &sp);
+
+ d2dSolidBrush(&scene, d2dLightSkyBlue, 1.0);
+ uiDrawFill(p->Context, river, &scene);
+
+ d2dSolidBrush(&scene, d2dBlack, 1.0);
+ uiDrawStroke(p->Context, river, &scene, &sp);
+
+ d2dSolidBrush(&scene, d2dYellowGreen, 1.0);
+ uiDrawFill(p->Context, rightMountain, &scene);
+
+ d2dSolidBrush(&scene, d2dBlack, 1.0);
+ uiDrawStroke(p->Context, rightMountain, &scene, &sp);
+
+ uiDrawFreePath(leftMountain);
+ uiDrawFreePath(rightMountain);
+ uiDrawFreePath(sun);
+ uiDrawFreePath(sunRays);
+ uiDrawFreePath(river);
+}
+
+// TODO https://msdn.microsoft.com/en-us/library/windows/desktop/dd756690%28v=vs.85%29.aspx
+
+// from https://msdn.microsoft.com/en-us/library/windows/desktop/dd756681%28v=vs.85%29.aspx
+static void drawD2DGeometryGroup(uiAreaDrawParams *p)
+{
+ uiDrawPath *alternate;
+ uiDrawPath *winding;
+ uiDrawBrush fill;
+ uiDrawBrush stroke;
+ uiDrawStrokeParams sp;
+ uiDrawMatrix m;
+
+ sp.Dashes = NULL;
+ sp.NumDashes = 0;
+ sp.DashPhase = 0;
+
+ alternate = uiDrawNewPath(uiDrawFillModeAlternate);
+ uiDrawPathNewFigureWithArc(alternate,
+ 105, 105,
+ 25,
+ 0, 2 * uiPi,
+ 0);
+ uiDrawPathNewFigureWithArc(alternate,
+ 105, 105,
+ 50,
+ 0, 2 * uiPi,
+ 0);
+ uiDrawPathNewFigureWithArc(alternate,
+ 105, 105,
+ 75,
+ 0, 2 * uiPi,
+ 0);
+ uiDrawPathNewFigureWithArc(alternate,
+ 105, 105,
+ 100,
+ 0, 2 * uiPi,
+ 0);
+ uiDrawPathEnd(alternate);
+
+ winding = uiDrawNewPath(uiDrawFillModeWinding);
+ uiDrawPathNewFigureWithArc(winding,
+ 105, 105,
+ 25,
+ 0, 2 * uiPi,
+ 0);
+ uiDrawPathNewFigureWithArc(winding,
+ 105, 105,
+ 50,
+ 0, 2 * uiPi,
+ 0);
+ uiDrawPathNewFigureWithArc(winding,
+ 105, 105,
+ 75,
+ 0, 2 * uiPi,
+ 0);
+ uiDrawPathNewFigureWithArc(winding,
+ 105, 105,
+ 100,
+ 0, 2 * uiPi,
+ 0);
+ uiDrawPathEnd(winding);
+
+ d2dClear(p, d2dWhite, 1.0);
+
+ // TODO grid
+
+ // TODO the example doesn't provide these
+ d2dSolidBrush(&fill, d2dForestGreen, 1.0);
+ d2dSolidBrush(&stroke, d2dCornflowerBlue, 1.0);
+
+ sp.Thickness = 1.0;
+ sp.Cap = uiDrawLineCapFlat;
+ sp.Join = uiDrawLineJoinMiter;
+ sp.MiterLimit = uiDrawDefaultMiterLimit;
+
+ uiDrawFill(p->Context, alternate, &fill);
+ uiDrawStroke(p->Context, alternate, &stroke, &sp);
+ // TODO text
+
+ uiDrawMatrixSetIdentity(&m);
+ uiDrawMatrixTranslate(&m, 300, 0);
+ uiDrawTransform(p->Context, &m);
+ uiDrawFill(p->Context, winding, &fill);
+ uiDrawStroke(p->Context, winding, &stroke, &sp);
+// // TODO text
+
+ uiDrawFreePath(winding);
+ uiDrawFreePath(alternate);
+}
+
+// TODO https://msdn.microsoft.com/en-us/library/windows/desktop/dd756676%28v=vs.85%29.aspx
+
+// TODO? https://msdn.microsoft.com/en-us/library/windows/desktop/dd370971%28v=vs.85%29.aspx
+
+// TODO are there even examples here? https://msdn.microsoft.com/en-us/library/windows/desktop/dd370966%28v=vs.85%29.aspx
+
+// from https://msdn.microsoft.com/en-us/library/windows/desktop/dd756687%28v=vs.85%29.aspx
+static void drawD2DRotate(uiAreaDrawParams *p)
+{
+ uiDrawPath *path;
+ uiDrawBrush original;
+ uiDrawBrush fill;
+ uiDrawBrush transform;
+ uiDrawStrokeParams originalsp;
+ uiDrawStrokeParams transformsp;
+ uiDrawMatrix m;
+
+ originalsp.Dashes = NULL;
+ originalsp.NumDashes = 0;
+ originalsp.DashPhase = 0;
+ transformsp.Dashes = NULL;
+ transformsp.NumDashes = 0;
+ transformsp.DashPhase = 0;
+
+ path = uiDrawNewPath(uiDrawFillModeWinding);
+ uiDrawPathAddRectangle(path, 438.0, 301.5, 498.0 - 438.0, 361.5 - 301.5);
+ uiDrawPathEnd(path);
+
+ // TODO the example doesn't specify what these should be
+ d2dSolidBrush(&original, d2dBlack, 1.0);
+ d2dSolidBrush(&fill, d2dWhite, 0.5);
+ d2dSolidBrush(&transform, d2dForestGreen, 1.0);
+ // TODO this needs to be dashed
+ originalsp.Thickness = 1.0;
+ originalsp.Cap = uiDrawLineCapFlat;
+ originalsp.Join = uiDrawLineJoinMiter;
+ originalsp.MiterLimit = uiDrawDefaultMiterLimit;
+ transformsp.Thickness = 1.0;
+ transformsp.Cap = uiDrawLineCapFlat;
+ transformsp.Join = uiDrawLineJoinMiter;
+ transformsp.MiterLimit = uiDrawDefaultMiterLimit;
+
+ // save for when we do the translated one
+ uiDrawSave(p->Context);
+
+ uiDrawStroke(p->Context, path, &original, &originalsp);
+
+ uiDrawMatrixSetIdentity(&m);
+ uiDrawMatrixRotate(&m,
+ 468.0, 331.5,
+ 45.0 * (uiPi / 180));
+ uiDrawTransform(p->Context, &m);
+
+ uiDrawFill(p->Context, path, &fill);
+ uiDrawStroke(p->Context, path, &transform, &transformsp);
+
+ uiDrawRestore(p->Context);
+
+ // translate to test the corner axis
+ uiDrawMatrixSetIdentity(&m);
+ uiDrawMatrixTranslate(&m, -200, -200);
+ uiDrawTransform(p->Context, &m);
+
+ uiDrawStroke(p->Context, path, &original, &originalsp);
+
+ uiDrawMatrixSetIdentity(&m);
+ uiDrawMatrixRotate(&m,
+ 438.0, 301.5,
+ 45.0 * (uiPi / 180));
+ uiDrawTransform(p->Context, &m);
+
+ uiDrawFill(p->Context, path, &fill);
+ uiDrawStroke(p->Context, path, &transform, &transformsp);
+
+ uiDrawFreePath(path);
+}
+
+// from https://msdn.microsoft.com/en-us/library/windows/desktop/dd756688%28v=vs.85%29.aspx
+static void drawD2DScale(uiAreaDrawParams *p)
+{
+ uiDrawPath *path;
+ uiDrawBrush original;
+ uiDrawBrush fill;
+ uiDrawBrush transform;
+ uiDrawStrokeParams originalsp;
+ uiDrawStrokeParams transformsp;
+ uiDrawMatrix m;
+
+ originalsp.Dashes = NULL;
+ originalsp.NumDashes = 0;
+ originalsp.DashPhase = 0;
+ transformsp.Dashes = NULL;
+ transformsp.NumDashes = 0;
+ transformsp.DashPhase = 0;
+
+ path = uiDrawNewPath(uiDrawFillModeWinding);
+ uiDrawPathAddRectangle(path, 438.0, 80.5, 498.0 - 438.0, 140.5 - 80.5);
+ uiDrawPathEnd(path);
+
+ // TODO the example doesn't specify what these should be
+ d2dSolidBrush(&original, d2dBlack, 1.0);
+ d2dSolidBrush(&fill, d2dWhite, 0.5);
+ d2dSolidBrush(&transform, d2dForestGreen, 1.0);
+ // TODO this needs to be dashed
+ originalsp.Thickness = 1.0;
+ originalsp.Cap = uiDrawLineCapFlat;
+ originalsp.Join = uiDrawLineJoinMiter;
+ originalsp.MiterLimit = uiDrawDefaultMiterLimit;
+ transformsp.Thickness = 1.0;
+ transformsp.Cap = uiDrawLineCapFlat;
+ transformsp.Join = uiDrawLineJoinMiter;
+ transformsp.MiterLimit = uiDrawDefaultMiterLimit;
+
+ // save for when we do the translated one
+ uiDrawSave(p->Context);
+
+ uiDrawStroke(p->Context, path, &original, &originalsp);
+
+ uiDrawMatrixSetIdentity(&m);
+ uiDrawMatrixScale(&m,
+ 438.0, 80.5,
+ 1.3, 1.3);
+ uiDrawTransform(p->Context, &m);
+
+ uiDrawFill(p->Context, path, &fill);
+ uiDrawStroke(p->Context, path, &transform, &transformsp);
+
+ uiDrawRestore(p->Context);
+
+ // for testing purposes, show what happens if we scale about (0, 0)
+ uiDrawMatrixSetIdentity(&m);
+ uiDrawMatrixTranslate(&m, -300, 50);
+ uiDrawTransform(p->Context, &m);
+
+ uiDrawStroke(p->Context, path, &original, &originalsp);
+
+ uiDrawMatrixSetIdentity(&m);
+ uiDrawMatrixScale(&m,
+ 0, 0,
+ 1.3, 1.3);
+ uiDrawTransform(p->Context, &m);
+
+ uiDrawFill(p->Context, path, &fill);
+ uiDrawStroke(p->Context, path, &transform, &transformsp);
+
+ uiDrawFreePath(path);
+}
+
+// from https://msdn.microsoft.com/en-us/library/windows/desktop/dd756689%28v=vs.85%29.aspx
+// TODO counterclockwise?!
+void drawD2DSkew(uiAreaDrawParams *p)
+{
+ uiDrawPath *path;
+ uiDrawBrush original;
+ uiDrawBrush fill;
+ uiDrawBrush transform;
+ uiDrawStrokeParams originalsp;
+ uiDrawStrokeParams transformsp;
+ uiDrawMatrix m;
+
+ originalsp.Dashes = NULL;
+ originalsp.NumDashes = 0;
+ originalsp.DashPhase = 0;
+ transformsp.Dashes = NULL;
+ transformsp.NumDashes = 0;
+ transformsp.DashPhase = 0;
+
+ path = uiDrawNewPath(uiDrawFillModeWinding);
+ uiDrawPathAddRectangle(path, 126.0, 301.5, 186.0 - 126.0, 361.5 - 301.5);
+ uiDrawPathEnd(path);
+
+ // TODO the example doesn't specify what these should be
+ d2dSolidBrush(&original, d2dBlack, 1.0);
+ d2dSolidBrush(&fill, d2dWhite, 0.5);
+ d2dSolidBrush(&transform, d2dForestGreen, 1.0);
+ // TODO this needs to be dashed
+ originalsp.Thickness = 1.0;
+ originalsp.Cap = uiDrawLineCapFlat;
+ originalsp.Join = uiDrawLineJoinMiter;
+ originalsp.MiterLimit = uiDrawDefaultMiterLimit;
+ transformsp.Thickness = 1.0;
+ transformsp.Cap = uiDrawLineCapFlat;
+ transformsp.Join = uiDrawLineJoinMiter;
+ transformsp.MiterLimit = uiDrawDefaultMiterLimit;
+
+ // save for when we do the translated one
+ uiDrawSave(p->Context);
+
+ uiDrawStroke(p->Context, path, &original, &originalsp);
+
+ uiDrawMatrixSetIdentity(&m);
+ uiDrawMatrixSkew(&m,
+ 126.0, 301.5,
+ 45.0 * (uiPi / 180), 0);
+ uiDrawTransform(p->Context, &m);
+
+ uiDrawFill(p->Context, path, &fill);
+ uiDrawStroke(p->Context, path, &transform, &transformsp);
+
+ uiDrawRestore(p->Context);
+
+ // for testing purposes, show what happens if we skew about (0, 0)
+ uiDrawMatrixSetIdentity(&m);
+ uiDrawMatrixTranslate(&m, 0, -200);
+ uiDrawTransform(p->Context, &m);
+
+ uiDrawStroke(p->Context, path, &original, &originalsp);
+
+ uiDrawMatrixSetIdentity(&m);
+ uiDrawMatrixSkew(&m,
+ 0, 0,
+ 45.0 * (uiPi / 180), 0);
+ uiDrawTransform(p->Context, &m);
+
+ uiDrawFill(p->Context, path, &fill);
+ uiDrawStroke(p->Context, path, &transform, &transformsp);
+
+ uiDrawFreePath(path);
+}
+
+// from https://msdn.microsoft.com/en-us/library/windows/desktop/dd756691%28v=vs.85%29.aspx
+static void drawD2DTranslate(uiAreaDrawParams *p)
+{
+ uiDrawPath *path;
+ uiDrawBrush original;
+ uiDrawBrush fill;
+ uiDrawBrush transform;
+ uiDrawStrokeParams originalsp;
+ uiDrawStrokeParams transformsp;
+ uiDrawMatrix m;
+
+ originalsp.Dashes = NULL;
+ originalsp.NumDashes = 0;
+ originalsp.DashPhase = 0;
+ transformsp.Dashes = NULL;
+ transformsp.NumDashes = 0;
+ transformsp.DashPhase = 0;
+
+ path = uiDrawNewPath(uiDrawFillModeWinding);
+ uiDrawPathAddRectangle(path, 126.0, 80.5, 186.0 - 126.0, 140.5 - 80.5);
+ uiDrawPathEnd(path);
+
+ // TODO the example doesn't specify what these should be
+ d2dSolidBrush(&original, d2dBlack, 1.0);
+ d2dSolidBrush(&fill, d2dWhite, 0.5);
+ d2dSolidBrush(&transform, d2dForestGreen, 1.0);
+ // TODO this needs to be dashed
+ originalsp.Thickness = 1.0;
+ originalsp.Cap = uiDrawLineCapFlat;
+ originalsp.Join = uiDrawLineJoinMiter;
+ originalsp.MiterLimit = uiDrawDefaultMiterLimit;
+ transformsp.Thickness = 1.0;
+ transformsp.Cap = uiDrawLineCapFlat;
+ transformsp.Join = uiDrawLineJoinMiter;
+ transformsp.MiterLimit = uiDrawDefaultMiterLimit;
+
+ uiDrawStroke(p->Context, path, &original, &originalsp);
+
+ uiDrawMatrixSetIdentity(&m);
+ uiDrawMatrixTranslate(&m, 20, 10);
+ uiDrawTransform(p->Context, &m);
+
+ uiDrawFill(p->Context, path, &fill);
+ uiDrawStroke(p->Context, path, &transform, &transformsp);
+
+ uiDrawFreePath(path);
+}
+
+// from https://msdn.microsoft.com/en-us/library/windows/desktop/dd756672%28v=vs.85%29.aspx
+// TODO the points seem off
+static void drawD2DMultiTransforms(uiAreaDrawParams *p)
+{
+ uiDrawPath *path;
+ uiDrawBrush original;
+ uiDrawBrush fill;
+ uiDrawBrush transform;
+ uiDrawStrokeParams originalsp;
+ uiDrawStrokeParams transformsp;
+ uiDrawMatrix mtranslate;
+ uiDrawMatrix mrotate;
+
+ originalsp.Dashes = NULL;
+ originalsp.NumDashes = 0;
+ originalsp.DashPhase = 0;
+ transformsp.Dashes = NULL;
+ transformsp.NumDashes = 0;
+ transformsp.DashPhase = 0;
+
+ path = uiDrawNewPath(uiDrawFillModeWinding);
+ uiDrawPathAddRectangle(path, 300.0, 40.0, 360.0 - 300.0, 100.0 - 40.0);
+ uiDrawPathEnd(path);
+
+ // TODO the example doesn't specify what these should be
+ d2dSolidBrush(&original, d2dBlack, 1.0);
+ d2dSolidBrush(&fill, d2dWhite, 0.5);
+ d2dSolidBrush(&transform, d2dForestGreen, 1.0);
+ // TODO this needs to be dashed
+ originalsp.Thickness = 1.0;
+ originalsp.Cap = uiDrawLineCapFlat;
+ originalsp.Join = uiDrawLineJoinMiter;
+ originalsp.MiterLimit = uiDrawDefaultMiterLimit;
+ transformsp.Thickness = 1.0;
+ transformsp.Cap = uiDrawLineCapFlat;
+ transformsp.Join = uiDrawLineJoinMiter;
+ transformsp.MiterLimit = uiDrawDefaultMiterLimit;
+
+ uiDrawMatrixSetIdentity(&mtranslate);
+ uiDrawMatrixTranslate(&mtranslate, 20.0, 10.0);
+ uiDrawMatrixSetIdentity(&mrotate);
+ uiDrawMatrixRotate(&mrotate,
+ 330.0, 70.0,
+ 45.0 * (uiPi / 180));
+
+ // save for when we do the opposite one
+ uiDrawSave(p->Context);
+
+ uiDrawStroke(p->Context, path, &original, &originalsp);
+
+ uiDrawTransform(p->Context, &mrotate);
+ uiDrawTransform(p->Context, &mtranslate);
+
+ uiDrawFill(p->Context, path, &fill);
+ uiDrawStroke(p->Context, path, &transform, &transformsp);
+
+ uiDrawRestore(p->Context);
+ uiDrawFreePath(path);
+
+ path = uiDrawNewPath(uiDrawFillModeWinding);
+ uiDrawPathAddRectangle(path, 40.0, 40.0, 100.0 - 40.0, 100.0 - 40.0);
+ uiDrawPathEnd(path);
+
+ uiDrawMatrixSetIdentity(&mtranslate);
+ uiDrawMatrixTranslate(&mtranslate, 20.0, 10.0);
+ uiDrawMatrixSetIdentity(&mrotate);
+ uiDrawMatrixRotate(&mrotate,
+ 70.0, 70.0,
+ 45.0 * (uiPi / 180));
+
+ uiDrawStroke(p->Context, path, &original, &originalsp);
+
+ uiDrawTransform(p->Context, &mtranslate);
+ uiDrawTransform(p->Context, &mrotate);
+
+ uiDrawFill(p->Context, path, &fill);
+ uiDrawStroke(p->Context, path, &transform, &transformsp);
+
+ uiDrawFreePath(path);
+}
+
+// TODO https://msdn.microsoft.com/en-us/library/windows/desktop/dd756675%28v=vs.85%29.aspx
+
+// TODO https://msdn.microsoft.com/en-us/library/windows/desktop/dd756673%28v=vs.85%29.aspx
+
+// TODO https://msdn.microsoft.com/en-us/library/windows/desktop/dd756684%28v=vs.85%29.aspx
+
+// TODO dashing https://msdn.microsoft.com/en-us/library/windows/desktop/dd756683%28v=vs.85%29.aspx
+
+// from https://msdn.microsoft.com/en-us/library/windows/desktop/dd756682%28v=vs.85%29.aspx
+static void drawD2DComplexShape(uiAreaDrawParams *p)
+{
+ uiDrawPath *path;
+ uiDrawBrush black;
+ uiDrawBrush gradient;
+ uiDrawBrushGradientStop stops[2];
+ uiDrawStrokeParams sp;
+ uiDrawMatrix m;
+
+ sp.Dashes = NULL;
+ sp.NumDashes = 0;
+ sp.DashPhase = 0;
+
+ path = uiDrawNewPath(uiDrawFillModeWinding);
+ uiDrawPathNewFigure(path, 0, 0);
+ uiDrawPathLineTo(path, 200, 0);
+ uiDrawPathBezierTo(path,
+ 150, 50,
+ 150, 150,
+ 200, 200);
+ uiDrawPathLineTo(path, 0, 200);
+ uiDrawPathBezierTo(path,
+ 50, 150,
+ 50, 50,
+ 0, 0);
+ uiDrawPathCloseFigure(path);
+ uiDrawPathEnd(path);
+
+ d2dSolidBrush(&black, d2dBlack, 1.0);
+
+ stops[0].Pos =0.0;
+ stops[0].R = 0.0;
+ stops[0].G = 1.0;
+ stops[0].B = 1.0;
+ stops[0].A = 0.25;
+ stops[1].Pos = 1.0;
+ stops[1].R = 0.0;
+ stops[1].G = 0.0;
+ stops[1].B = 1.0;
+ stops[1].A = 1.0;
+ gradient.Type = uiDrawBrushTypeLinearGradient;
+ gradient.X0 = 100;
+ gradient.Y0 = 0;
+ gradient.X1 = 100;
+ gradient.Y1 = 200;
+ gradient.Stops = stops;
+ gradient.NumStops = 2;
+
+ uiDrawMatrixSetIdentity(&m);
+ uiDrawMatrixTranslate(&m, 20, 20);
+ uiDrawTransform(p->Context, &m);
+
+ sp.Thickness = 10.0;
+ sp.Cap = uiDrawLineCapFlat;
+ sp.Join = uiDrawLineJoinMiter;
+ sp.MiterLimit = uiDrawDefaultMiterLimit;
+
+ uiDrawStroke(p->Context, path, &black, &sp);
+ uiDrawFill(p->Context, path, &gradient);
+
+ uiDrawFreePath(path);
+}
+
+// TODO https://msdn.microsoft.com/en-us/library/windows/desktop/dd756692%28v=vs.85%29.aspx
+
+// TODO https://msdn.microsoft.com/en-us/library/windows/desktop/dd756686%28v=vs.85%29.aspx
+
+// TODO https://msdn.microsoft.com/en-us/library/windows/desktop/dd756685%28v=vs.85%29.aspx
+
+// TODO https://msdn.microsoft.com/en-us/library/windows/desktop/dd756674%28v=vs.85%29.aspx
+
+// TODO? https://msdn.microsoft.com/en-us/library/windows/desktop/ee329947%28v=vs.85%29.aspx
+
+// TODO https://msdn.microsoft.com/en-us/library/windows/desktop/ff485857%28v=vs.85%29.aspx
+
+// TODO? https://msdn.microsoft.com/en-us/library/windows/desktop/dd756755%28v=vs.85%29.aspx
+
+// TODO go through the API reference and spot examples that aren't listed
+
+// TODO all of these https://msdn.microsoft.com/en-us/library/windows/desktop/dd368187%28v=vs.85%29.aspx
+
+// cairo Samples Page (http://cairographics.org/samples/)
+
+static void crsourcergba(uiDrawBrush *brush, double r, double g, double b, double a)
+{
+ brush->Type = uiDrawBrushTypeSolid;
+ brush->R = r;
+ brush->G = g;
+ brush->B = b;
+ brush->A = a;
+}
+
+// arc
+static void drawCSArc(uiAreaDrawParams *p)
+{
+ double xc = 128.0;
+ double yc = 128.0;
+ double radius = 100.0;
+ double angle1 = 45.0 * (uiPi / 180.0);
+ double angle2 = 180.0 * (uiPi / 180.0);
+ uiDrawBrush source;
+ uiDrawStrokeParams sp;
+ uiDrawPath *path;
+
+ crsourcergba(&source, 0, 0, 0, 1);
+ sp.Cap = uiDrawLineCapFlat;
+ sp.Join = uiDrawLineJoinMiter;
+ sp.MiterLimit = uiDrawDefaultMiterLimit;
+ sp.Dashes = NULL;
+ sp.NumDashes = 0;
+ sp.DashPhase = 0;
+
+ sp.Thickness = 10.0;
+ path = uiDrawNewPath(uiDrawFillModeWinding);
+ uiDrawPathNewFigureWithArc(path,
+ xc, yc,
+ radius,
+ angle1,
+ angle2 - angle1,
+ 0);
+ uiDrawPathEnd(path);
+ uiDrawStroke(p->Context, path, &source, &sp);
+ uiDrawFreePath(path);
+
+ crsourcergba(&source, 1, 0.2, 0.2, 0.6);
+ sp.Thickness = 6.0;
+
+ path = uiDrawNewPath(uiDrawFillModeWinding);
+ uiDrawPathNewFigureWithArc(path,
+ xc, yc,
+ 10.0,
+ 0, 2 * uiPi,
+ 0);
+ uiDrawPathEnd(path);
+ uiDrawFill(p->Context, path, &source);
+ uiDrawFreePath(path);
+
+ path = uiDrawNewPath(uiDrawFillModeWinding);
+ uiDrawPathNewFigureWithArc(path,
+ xc, yc,
+ radius,
+ angle1, 0,
+ 0);
+ uiDrawPathLineTo(path, xc, yc);
+ uiDrawPathNewFigureWithArc(path,
+ xc, yc,
+ radius,
+ angle2, 0,
+ 0);
+ uiDrawPathLineTo(path, xc, yc);
+ uiDrawPathEnd(path);
+ uiDrawStroke(p->Context, path, &source, &sp);
+ uiDrawFreePath(path);
+}
+
+// arc negative
+static void drawCSArcNegative(uiAreaDrawParams *p)
+{
+ double xc = 128.0;
+ double yc = 128.0;
+ double radius = 100.0;
+ double angle1 = 45.0 * (uiPi / 180.0);
+ double angle2 = 180.0 * (uiPi / 180.0);
+ uiDrawBrush source;
+ uiDrawStrokeParams sp;
+ uiDrawPath *path;
+
+ crsourcergba(&source, 0, 0, 0, 1);
+ sp.Cap = uiDrawLineCapFlat;
+ sp.Join = uiDrawLineJoinMiter;
+ sp.MiterLimit = uiDrawDefaultMiterLimit;
+ sp.Dashes = NULL;
+ sp.NumDashes = 0;
+ sp.DashPhase = 0;
+
+ sp.Thickness = 10.0;
+ path = uiDrawNewPath(uiDrawFillModeWinding);
+ uiDrawPathNewFigureWithArc(path,
+ xc, yc,
+ radius,
+ angle1,
+ angle2 - angle1,
+ 1);
+ uiDrawPathEnd(path);
+ uiDrawStroke(p->Context, path, &source, &sp);
+ uiDrawFreePath(path);
+
+ crsourcergba(&source, 1, 0.2, 0.2, 0.6);
+ sp.Thickness = 6.0;
+
+ path = uiDrawNewPath(uiDrawFillModeWinding);
+ uiDrawPathNewFigureWithArc(path,
+ xc, yc,
+ 10.0,
+ 0, 2 * uiPi,
+ 0);
+ uiDrawPathEnd(path);
+ uiDrawFill(p->Context, path, &source);
+ uiDrawFreePath(path);
+
+ path = uiDrawNewPath(uiDrawFillModeWinding);
+ uiDrawPathNewFigureWithArc(path,
+ xc, yc,
+ radius,
+ angle1, 0,
+ 0);
+ uiDrawPathLineTo(path, xc, yc);
+ uiDrawPathNewFigureWithArc(path,
+ xc, yc,
+ radius,
+ angle2, 0,
+ 0);
+ uiDrawPathLineTo(path, xc, yc);
+ uiDrawPathEnd(path);
+ uiDrawStroke(p->Context, path, &source, &sp);
+ uiDrawFreePath(path);
+}
+
+// clip
+static void drawCSClip(uiAreaDrawParams *p)
+{
+ uiDrawBrush source;
+ uiDrawStrokeParams sp;
+ uiDrawPath *path;
+
+ crsourcergba(&source, 0, 0, 0, 1);
+ sp.Cap = uiDrawLineCapFlat;
+ sp.Join = uiDrawLineJoinMiter;
+ sp.MiterLimit = uiDrawDefaultMiterLimit;
+ sp.Dashes = NULL;
+ sp.NumDashes = 0;
+ sp.DashPhase = 0;
+
+ path = uiDrawNewPath(uiDrawFillModeWinding);
+
+ uiDrawPathNewFigureWithArc(path,
+ 128.0, 128.0,
+ 76.8,
+ 0, 2 * uiPi,
+ 0);
+ uiDrawPathEnd(path);
+ uiDrawClip(p->Context, path);
+ uiDrawFreePath(path);
+
+ path = uiDrawNewPath(uiDrawFillModeWinding);
+ uiDrawPathAddRectangle(path, 0, 0, 256, 256);
+ uiDrawPathEnd(path);
+ uiDrawFill(p->Context, path, &source);
+ uiDrawFreePath(path);
+
+ crsourcergba(&source, 0, 1, 0, 1);
+ path = uiDrawNewPath(uiDrawFillModeWinding);
+ uiDrawPathNewFigure(path, 0, 0);
+ uiDrawPathLineTo(path, 256, 256);
+ uiDrawPathNewFigure(path, 256, 0);
+ uiDrawPathLineTo(path, 0, 256);
+ uiDrawPathEnd(path);
+ sp.Thickness = 10.0;
+ uiDrawStroke(p->Context, path, &source, &sp);
+ uiDrawFreePath(path);
+}
+
+// TODO clip image
+
+// curve rectangle
+static void drawCSCurveRectangle(uiAreaDrawParams *p)
+{
+ double x0 = 25.6, /* parameters like cairo_rectangle */
+ y0 = 25.6,
+ rect_width = 204.8,
+ rect_height = 204.8,
+ radius = 102.4; /* and an approximate curvature radius */
+
+ double x1,y1;
+
+ uiDrawBrush source;
+ uiDrawStrokeParams sp;
+ uiDrawPath *path;
+
+ crsourcergba(&source, 0, 0, 0, 1);
+ sp.Cap = uiDrawLineCapFlat;
+ sp.Join = uiDrawLineJoinMiter;
+ sp.MiterLimit = uiDrawDefaultMiterLimit;
+ sp.Dashes = NULL;
+ sp.NumDashes = 0;
+ sp.DashPhase = 0;
+
+ path = uiDrawNewPath(uiDrawFillModeWinding);
+
+ x1=x0+rect_width;
+ y1=y0+rect_height;
+ if (!rect_width || !rect_height)
+ return;
+ if (rect_width/2 < radius) {
+ if (rect_height/2<radius) {
+ uiDrawPathNewFigure(path, x0, (y0 + y1)/2);
+ uiDrawPathBezierTo(path, x0 ,y0, x0, y0, (x0 + x1)/2, y0);
+ uiDrawPathBezierTo(path, x1, y0, x1, y0, x1, (y0 + y1)/2);
+ uiDrawPathBezierTo(path, x1, y1, x1, y1, (x1 + x0)/2, y1);
+ uiDrawPathBezierTo(path, x0, y1, x0, y1, x0, (y0 + y1)/2);
+ } else {
+ uiDrawPathNewFigure(path, x0, y0 + radius);
+ uiDrawPathBezierTo(path, x0 ,y0, x0, y0, (x0 + x1)/2, y0);
+ uiDrawPathBezierTo(path, x1, y0, x1, y0, x1, y0 + radius);
+ uiDrawPathLineTo(path, x1 , y1 - radius);
+ uiDrawPathBezierTo(path, x1, y1, x1, y1, (x1 + x0)/2, y1);
+ uiDrawPathBezierTo(path, x0, y1, x0, y1, x0, y1- radius);
+ }
+ } else {
+ if (rect_height / 2 < radius) {
+ uiDrawPathNewFigure(path, x0, (y0 + y1)/2);
+ uiDrawPathBezierTo(path, x0 , y0, x0 , y0, x0 + radius, y0);
+ uiDrawPathLineTo(path, x1 - radius, y0);
+ uiDrawPathBezierTo(path, x1, y0, x1, y0, x1, (y0 + y1)/2);
+ uiDrawPathBezierTo(path, x1, y1, x1, y1, x1 - radius, y1);
+ uiDrawPathLineTo(path, x0 + radius, y1);
+ uiDrawPathBezierTo(path, x0, y1, x0, y1, x0, (y0 + y1)/2);
+ } else {
+ uiDrawPathNewFigure(path, x0, y0 + radius);
+ uiDrawPathBezierTo(path, x0 , y0, x0 , y0, x0 + radius, y0);
+ uiDrawPathLineTo(path, x1 - radius, y0);
+ uiDrawPathBezierTo(path, x1, y0, x1, y0, x1, y0 + radius);
+ uiDrawPathLineTo(path, x1 , y1 - radius);
+ uiDrawPathBezierTo(path, x1, y1, x1, y1, x1 - radius, y1);
+ uiDrawPathLineTo(path, x0 + radius, y1);
+ uiDrawPathBezierTo(path, x0, y1, x0, y1, x0, y1- radius);
+ }
+ }
+ uiDrawPathCloseFigure(path);
+ uiDrawPathEnd(path);
+
+ crsourcergba(&source, 0.5, 0.5, 1, 1.0);
+ uiDrawFill(p->Context, path, &source);
+ crsourcergba(&source, 0.5, 0, 0, 0.5);
+ sp.Thickness = 10.0;
+ uiDrawStroke(p->Context, path, &source, &sp);
+
+ uiDrawFreePath(path);
+}
+
+// curve to
+static void drawCSCurveTo(uiAreaDrawParams *p)
+{
+ double x=25.6, y=128.0;
+ double x1=102.4, y1=230.4,
+ x2=153.6, y2=25.6,
+ x3=230.4, y3=128.0;
+ uiDrawBrush source;
+ uiDrawStrokeParams sp;
+ uiDrawPath *path;
+
+ crsourcergba(&source, 0, 0, 0, 1);
+ sp.Cap = uiDrawLineCapFlat;
+ sp.Join = uiDrawLineJoinMiter;
+ sp.MiterLimit = uiDrawDefaultMiterLimit;
+ sp.Dashes = NULL;
+ sp.NumDashes = 0;
+ sp.DashPhase = 0;
+
+ path = uiDrawNewPath(uiDrawFillModeWinding);
+
+ uiDrawPathNewFigure(path, x, y);
+ uiDrawPathBezierTo(path, x1, y1, x2, y2, x3, y3);
+ uiDrawPathEnd(path);
+ sp.Thickness = 10.0;
+ uiDrawStroke(p->Context, path, &source, &sp);
+ uiDrawFreePath(path);
+
+ crsourcergba(&source, 1, 0.2, 0.2, 0.6);
+ sp.Thickness = 6.0;
+ path = uiDrawNewPath(uiDrawFillModeWinding);
+ uiDrawPathNewFigure(path, x, y);
+ uiDrawPathLineTo(path, x1, y1);
+ uiDrawPathNewFigure(path, x2, y2);
+ uiDrawPathLineTo(path, x3, y3);
+ uiDrawPathEnd(path);
+ uiDrawStroke(p->Context, path, &source, &sp);
+ uiDrawFreePath(path);
+}
+
+// dash
+static void drawCSDash(uiAreaDrawParams *p)
+{
+ double dashes[] = {
+ 50.0, /* ink */
+ 10.0, /* skip */
+ 10.0, /* ink */
+ 10.0 /* skip*/
+ };
+ int ndash = sizeof (dashes)/sizeof(dashes[0]);
+ double offset = -50.0;
+
+ uiDrawBrush source;
+ uiDrawStrokeParams sp;
+ uiDrawPath *path;
+
+ crsourcergba(&source, 0, 0, 0, 1);
+ sp.Cap = uiDrawLineCapFlat;
+ sp.Join = uiDrawLineJoinMiter;
+ sp.MiterLimit = uiDrawDefaultMiterLimit;
+ sp.Dashes = dashes;
+ sp.NumDashes = ndash;
+ sp.DashPhase = offset;
+ sp.Thickness = 10.0;
+
+ path = uiDrawNewPath(uiDrawFillModeWinding);
+ uiDrawPathNewFigure(path, 128.0, 25.6);
+ uiDrawPathLineTo(path, 230.4, 230.4);
+ uiDrawPathLineTo(path, 230.4 -102.4, 230.4 + 0.0);
+ uiDrawPathBezierTo(path,
+ 51.2, 230.4,
+ 51.2, 128.0,
+ 128.0, 128.0);
+ uiDrawPathEnd(path);
+
+ uiDrawStroke(p->Context, path, &source, &sp);
+ uiDrawFreePath(path);
+}
+
+// fill and stroke2
+static void drawCSFillAndStroke2(uiAreaDrawParams *p)
+{
+ uiDrawBrush source;
+ uiDrawStrokeParams sp;
+ uiDrawPath *path;
+
+ crsourcergba(&source, 0, 0, 0, 1);
+ sp.Cap = uiDrawLineCapFlat;
+ sp.Join = uiDrawLineJoinMiter;
+ sp.MiterLimit = uiDrawDefaultMiterLimit;
+ sp.Dashes = NULL;
+ sp.NumDashes = 0;
+ sp.DashPhase = 0;
+
+ path = uiDrawNewPath(uiDrawFillModeWinding);
+
+ uiDrawPathNewFigure(path, 128.0, 25.6);
+ uiDrawPathLineTo(path, 230.4, 230.4);
+ uiDrawPathLineTo(path, 230.4 - 102.4, 230.4 + 0.0);
+ uiDrawPathBezierTo(path, 51.2, 230.4, 51.2, 128.0, 128.0, 128.0);
+ uiDrawPathCloseFigure(path);
+
+ uiDrawPathNewFigure(path, 64.0, 25.6);
+ uiDrawPathLineTo(path, 64.0 + 51.2, 25.6 + 51.2);
+ uiDrawPathLineTo(path, 64.0 + 51.2 -51.2, 25.6 + 51.2 + 51.2);
+ uiDrawPathLineTo(path, 64.0 + 51.2 -51.2 -51.2, 25.6 + 51.2 + 51.2 -51.2);
+ uiDrawPathCloseFigure(path);
+
+ uiDrawPathEnd(path);
+
+ sp.Thickness = 10.0;
+ crsourcergba(&source, 0, 0, 1, 1);
+ uiDrawFill(p->Context, path, &source);
+ crsourcergba(&source, 0, 0, 0, 1);
+ uiDrawStroke(p->Context, path, &source, &sp);
+ uiDrawFreePath(path);
+}
+
+// fill style
+static void drawCSFillStyle(uiAreaDrawParams *p)
+{
+ uiDrawBrush source;
+ uiDrawStrokeParams sp;
+ uiDrawPath *path;
+ uiDrawMatrix m;
+
+ crsourcergba(&source, 0, 0, 0, 1);
+ sp.Cap = uiDrawLineCapFlat;
+ sp.Join = uiDrawLineJoinMiter;
+ sp.MiterLimit = uiDrawDefaultMiterLimit;
+ sp.Dashes = NULL;
+ sp.NumDashes = 0;
+ sp.DashPhase = 0;
+
+ sp.Thickness = 6;
+
+ path = uiDrawNewPath(uiDrawFillModeAlternate);
+ uiDrawPathAddRectangle(path, 12, 12, 232, 70);
+ uiDrawPathNewFigureWithArc(path,
+ 64, 64,
+ 40,
+ 0, 2*uiPi,
+ 0);
+ uiDrawPathNewFigureWithArc(path,
+ 192, 64,
+ 40,
+ 0, -2*uiPi,
+ 1);
+ uiDrawPathEnd(path);
+
+ crsourcergba(&source, 0, 0.7, 0, 1);
+ uiDrawFill(p->Context, path, &source);
+ crsourcergba(&source, 0, 0, 0, 1);
+ uiDrawStroke(p->Context, path, &source, &sp);
+ uiDrawFreePath(path);
+
+ uiDrawMatrixSetIdentity(&m);
+ uiDrawMatrixTranslate(&m, 0, 128);
+ uiDrawTransform(p->Context, &m);
+
+ path = uiDrawNewPath(uiDrawFillModeWinding);
+ uiDrawPathAddRectangle(path, 12, 12, 232, 70);
+ uiDrawPathNewFigureWithArc(path,
+ 64, 64,
+ 40,
+ 0, 2*uiPi,
+ 0);
+ uiDrawPathNewFigureWithArc(path,
+ 192, 64,
+ 40,
+ 0, -2*uiPi,
+ 1);
+ uiDrawPathEnd(path);
+
+ crsourcergba(&source, 0, 0, 0.9, 1);
+ uiDrawFill(p->Context, path, &source);
+ crsourcergba(&source, 0, 0, 0, 1);
+ uiDrawStroke(p->Context, path, &source, &sp);
+ uiDrawFreePath(path);
+}
+
+// TOOD gradient (radial gradient with two circles)
+
+// TODO image
+
+// TODO imagepattern
+
+// multi segment caps
+static void drawCSMultiCaps(uiAreaDrawParams *p)
+{
+ uiDrawBrush source;
+ uiDrawStrokeParams sp;
+ uiDrawPath *path;
+
+ crsourcergba(&source, 0, 0, 0, 1);
+ sp.Join = uiDrawLineJoinMiter;
+ sp.MiterLimit = uiDrawDefaultMiterLimit;
+ sp.Dashes = NULL;
+ sp.NumDashes = 0;
+ sp.DashPhase = 0;
+
+ path = uiDrawNewPath(uiDrawFillModeWinding);
+
+ uiDrawPathNewFigure(path, 50.0, 75.0);
+ uiDrawPathLineTo(path, 200.0, 75.0);
+
+ uiDrawPathNewFigure(path, 50.0, 125.0);
+ uiDrawPathLineTo(path, 200.0, 125.0);
+
+ uiDrawPathNewFigure(path, 50.0, 175.0);
+ uiDrawPathLineTo(path, 200.0, 175.0);
+ uiDrawPathEnd(path);
+
+ sp.Thickness = 30.0;
+ sp.Cap = uiDrawLineCapRound;
+ uiDrawStroke(p->Context, path, &source, &sp);
+ uiDrawFreePath(path);
+}
+
+// rounded rectangle
+static void drawCSRoundRect(uiAreaDrawParams *p)
+{
+ double x = 25.6, /* parameters like cairo_rectangle */
+ y = 25.6,
+ width = 204.8,
+ height = 204.8,
+ aspect = 1.0, /* aspect ratio */
+ corner_radius = height / 10.0; /* and corner curvature radius */
+
+ double radius = corner_radius / aspect;
+ double degrees = uiPi / 180.0;
+
+ uiDrawBrush source;
+ uiDrawStrokeParams sp;
+ uiDrawPath *path;
+
+ crsourcergba(&source, 0, 0, 0, 1);
+ sp.Cap = uiDrawLineCapFlat;
+ sp.Join = uiDrawLineJoinMiter;
+ sp.MiterLimit = uiDrawDefaultMiterLimit;
+ sp.Dashes = NULL;
+ sp.NumDashes = 0;
+ sp.DashPhase = 0;
+
+ path = uiDrawNewPath(uiDrawFillModeWinding);
+
+ // top right corner
+ uiDrawPathNewFigureWithArc(path,
+ x + width - radius, y + radius,
+ radius,
+ -90 * degrees, uiPi / 2,
+ 0);
+ // bottom right corner
+ uiDrawPathArcTo(path,
+ x + width - radius, y + height - radius,
+ radius,
+ 0 * degrees, uiPi / 2,
+ 0);
+ // bottom left corner
+ uiDrawPathArcTo(path,
+ x + radius, y + height - radius,
+ radius,
+ 90 * degrees, uiPi / 2,
+ 0);
+ // top left corner
+ uiDrawPathArcTo(path,
+ x + radius, y + radius,
+ radius,
+ 180 * degrees, uiPi / 2,
+ 0);
+ uiDrawPathCloseFigure(path);
+ uiDrawPathEnd(path);
+
+ crsourcergba(&source, 0.5, 0.5, 1, 1);
+ uiDrawFill(p->Context, path, &source);
+ crsourcergba(&source, 0.5, 0, 0, 0.5);
+ sp.Thickness = 10.0;
+ uiDrawStroke(p->Context, path, &source, &sp);
+ uiDrawFreePath(path);
+}
+
+// set line cap
+static void drawCSSetLineCap(uiAreaDrawParams *p)
+{
+ uiDrawBrush source;
+ uiDrawStrokeParams sp;
+ uiDrawPath *path;
+
+ crsourcergba(&source, 0, 0, 0, 1);
+ sp.Cap = uiDrawLineCapFlat;
+ sp.Join = uiDrawLineJoinMiter;
+ sp.MiterLimit = uiDrawDefaultMiterLimit;
+ sp.Dashes = NULL;
+ sp.NumDashes = 0;
+ sp.DashPhase = 0;
+
+ sp.Thickness = 30.0;
+
+ sp.Cap = uiDrawLineCapFlat;
+ path = uiDrawNewPath(uiDrawFillModeWinding);
+ uiDrawPathNewFigure(path, 64.0, 50.0);
+ uiDrawPathLineTo(path, 64.0, 200.0);
+ uiDrawPathEnd(path);
+ uiDrawStroke(p->Context, path, &source, &sp);
+ uiDrawFreePath(path);
+
+ sp.Cap = uiDrawLineCapRound;
+ path = uiDrawNewPath(uiDrawFillModeWinding);
+ uiDrawPathNewFigure(path, 128.0, 50.0);
+ uiDrawPathLineTo(path, 128.0, 200.0);
+ uiDrawPathEnd(path);
+ uiDrawStroke(p->Context, path, &source, &sp);
+ uiDrawFreePath(path);
+
+ sp.Cap = uiDrawLineCapSquare;
+ path = uiDrawNewPath(uiDrawFillModeWinding);
+ uiDrawPathNewFigure(path, 192.0, 50.0);
+ uiDrawPathLineTo(path, 192.0, 200.0);
+ uiDrawPathEnd(path);
+ uiDrawStroke(p->Context, path, &source, &sp);
+ uiDrawFreePath(path);
+
+ // draw helping lines
+ // keep the square cap to match the reference picture on the cairo website
+ crsourcergba(&source, 1, 0.2, 0.2, 1);
+ sp.Thickness = 2.56;
+ path = uiDrawNewPath(uiDrawFillModeWinding);
+ uiDrawPathNewFigure(path, 64.0, 50.0);
+ uiDrawPathLineTo(path, 64.0, 200.0);
+ uiDrawPathNewFigure(path, 128.0, 50.0);
+ uiDrawPathLineTo(path, 128.0, 200.0);
+ uiDrawPathNewFigure(path, 192.0, 50.0);
+ uiDrawPathLineTo(path, 192.0, 200.0);
+ uiDrawPathEnd(path);
+ uiDrawStroke(p->Context, path, &source, &sp);
+ uiDrawFreePath(path);
+}
+
+// set line join
+static void drawCSSetLineJoin(uiAreaDrawParams *p)
+{
+ uiDrawBrush source;
+ uiDrawStrokeParams sp;
+ uiDrawPath *path;
+
+ crsourcergba(&source, 0, 0, 0, 1);
+ sp.Cap = uiDrawLineCapFlat;
+ sp.Join = uiDrawLineJoinMiter;
+ sp.MiterLimit = uiDrawDefaultMiterLimit;
+ sp.Dashes = NULL;
+ sp.NumDashes = 0;
+ sp.DashPhase = 0;
+
+ sp.Thickness = 40.96;
+ path = uiDrawNewPath(uiDrawFillModeWinding);
+ uiDrawPathNewFigure(path, 76.8, 84.48);
+ uiDrawPathLineTo(path, 76.8 + 51.2, 84.48 -51.2);
+ uiDrawPathLineTo(path, 76.8 + 51.2 + 51.2, 84.48 - 51.2 + 51.2);
+ uiDrawPathEnd(path);
+ sp.Join = uiDrawLineJoinMiter;
+ uiDrawStroke(p->Context, path, &source, &sp);
+ uiDrawFreePath(path);
+
+ path = uiDrawNewPath(uiDrawFillModeWinding);
+ uiDrawPathNewFigure(path, 76.8, 161.28);
+ uiDrawPathLineTo(path, 76.8 + 51.2, 161.28 -51.2);
+ uiDrawPathLineTo(path, 76.8 + 51.2 + 51.2, 161.28 - 51.2 + 51.2);
+ uiDrawPathEnd(path);
+ sp.Join = uiDrawLineJoinBevel;
+ uiDrawStroke(p->Context, path, &source, &sp);
+ uiDrawFreePath(path);
+
+ path = uiDrawNewPath(uiDrawFillModeWinding);
+ uiDrawPathNewFigure(path, 76.8, 238.08);
+ uiDrawPathLineTo(path, 76.8 + 51.2, 238.08 -51.2);
+ uiDrawPathLineTo(path, 76.8 + 51.2 + 51.2, 238.08 - 51.2 + 51.2);
+ uiDrawPathEnd(path);
+ sp.Join = uiDrawLineJoinRound;
+ uiDrawStroke(p->Context, path, &source, &sp);
+ uiDrawFreePath(path);
+}
+
+// TODO text
+
+// TODO text align center
+
+// TODO text extents
+
+// Quartz 2D Programming Guide
+
+static void cgaddrect(uiDrawPath *path, uiAreaDrawParams *p, double x, double y, double width, double height)
+{
+ uiDrawPathAddRectangle(path,
+ x, p->AreaHeight - y - height,
+ width, height);
+}
+
+// Graphics Contexts > Creating a Window Graphics Context in Mac OS X
+static void drawQ2DCreateWindowGC(uiAreaDrawParams *p)
+{
+ uiDrawPath *path;
+ uiDrawBrush brush;
+
+ crsourcergba(&brush, 1, 0, 0, 1);
+ path = uiDrawNewPath(uiDrawFillModeWinding);
+ cgaddrect(path, p, 0, 0, 200, 100);
+ uiDrawPathEnd(path);
+ uiDrawFill(p->Context, path, &brush);
+ uiDrawFreePath(path);
+
+ crsourcergba(&brush, 0, 0, 1, .5);
+ path = uiDrawNewPath(uiDrawFillModeWinding);
+ cgaddrect(path, p, 0, 0, 100, 200);
+ uiDrawPathEnd(path);
+ uiDrawFill(p->Context, path, &brush);
+ uiDrawFreePath(path);
+}
+
+// TODO Patterns page?
+
+// TODO Shadows page?
+
+// TODO Gradients page (includes some circle-circle radial gradients)
+
+// TODO Transparency Layers page?
+
+// TODO Core Graphics Layer Drawing page?
+
+// Cocoa Drawing Guide
+
+// TODO Advanced Drawing Techniques page?
+
+// TODO Text page, if any?
+
+static const struct drawtest tests[] = {
+ { "Original uiArea test", drawOriginal },
+ { "Arc test", drawArcs },
+ { "Direct2D: Direct2D Quickstart for Windows 8", drawD2DW8QS },
+ { "Direct2D: Creating a Simple Direct2D Application", drawD2DSimpleApp },
+ { "Direct2D: How to Create a Solid Color Brush", drawD2DSolidBrush },
+ { "Direct2D: How to Create a Linear Gradient Brush", drawD2DLinearBrush },
+ { "Direct2D: How to Create a Radial Gradient Brush", drawD2DRadialBrush },
+ { "Direct2D: Path Geometries Overview", drawD2DPathGeometries },
+ { "Direct2D: How to Create Geometry Groups", drawD2DGeometryGroup },
+ { "Direct2D: How to Rotate an Object", drawD2DRotate },
+ { "Direct2D: How to Scale an Object", drawD2DScale },
+ { "Direct2D: How to Skew an Object", drawD2DSkew },
+ { "Direct2D: How to Translate an Object", drawD2DTranslate },
+ { "Direct2D: How to Apply Multiple Transforms to an Object", drawD2DMultiTransforms },
+ { "Direct2D: How to Draw and Fill a Complex Shape", drawD2DComplexShape },
+ { "cairo samples: arc", drawCSArc },
+ { "cairo samples: arc negative", drawCSArcNegative },
+ { "cairo samples: clip", drawCSClip },
+ { "cairo samples: curve rectangle", drawCSCurveRectangle },
+ { "cairo samples: curve to", drawCSCurveTo },
+ { "cairo samples: dash", drawCSDash },
+ { "cairo samples: fill and stroke2", drawCSFillAndStroke2 },
+ { "cairo samples: fill style", drawCSFillStyle },
+ { "cairo samples: multi segment caps", drawCSMultiCaps },
+ { "cairo samples: rounded rectangle", drawCSRoundRect },
+ { "cairo samples: set line cap", drawCSSetLineCap },
+ { "cairo samples: set line join", drawCSSetLineJoin },
+ { "Quartz 2D PG: Creating a Window Graphics Context in Mac OS X", drawQ2DCreateWindowGC },
+ { NULL, NULL },
+};
+
+void runDrawTest(int n, uiAreaDrawParams *p)
+{
+ (*(tests[n].draw))(p);
+}
+
+void populateComboboxWithTests(uiCombobox *c)
+{
+ size_t i;
+
+ for (i = 0; tests[i].name != NULL; i++)
+ uiComboboxAppend(c, tests[i].name);
+}
diff --git a/src/libui_sdl/libui/test/images/andlabs_16x16test_24june2016.png b/src/libui_sdl/libui/test/images/andlabs_16x16test_24june2016.png
new file mode 100644
index 0000000..a4c27d9
--- /dev/null
+++ b/src/libui_sdl/libui/test/images/andlabs_16x16test_24june2016.png
Binary files differ
diff --git a/src/libui_sdl/libui/test/images/andlabs_32x32test_24june2016.png b/src/libui_sdl/libui/test/images/andlabs_32x32test_24june2016.png
new file mode 100644
index 0000000..e1c33fc
--- /dev/null
+++ b/src/libui_sdl/libui/test/images/andlabs_32x32test_24june2016.png
Binary files differ
diff --git a/src/libui_sdl/libui/test/images/gen.go b/src/libui_sdl/libui/test/images/gen.go
new file mode 100644
index 0000000..910abc7
--- /dev/null
+++ b/src/libui_sdl/libui/test/images/gen.go
@@ -0,0 +1,98 @@
+// 25 june 2016
+package main
+
+import (
+ "fmt"
+ "os"
+ "image"
+ "image/draw"
+ _ "image/png"
+)
+
+type img struct {
+ filename string
+ data []byte
+ width int
+ height int
+ stride int
+}
+
+func main() {
+ if len(os.Args[1:]) == 0 {
+ panic("no files specified")
+ }
+
+ images := make([]*img, 0, len(os.Args[1:]))
+ for _, fn := range os.Args[1:] {
+ f, err := os.Open(fn)
+ if err != nil {
+ panic(err)
+ }
+ ii, _, err := image.Decode(f)
+ if err != nil {
+ panic(err)
+ }
+ f.Close()
+
+ i := image.NewRGBA(ii.Bounds())
+ draw.Draw(i, i.Rect, ii, ii.Bounds().Min, draw.Src)
+
+ im := &img{
+ filename: fn,
+ data: i.Pix,
+ width: i.Rect.Dx(),
+ height: i.Rect.Dy(),
+ stride: i.Stride,
+ }
+ images = append(images, im)
+ }
+
+ fmt.Println("// auto-generated by images/gen.go")
+ fmt.Println("#include \"test.h\"")
+ fmt.Println()
+ for i, im := range images {
+ fmt.Printf("static const uint32_t dat%d[] = {", i)
+ for j := 0; j < len(im.data); j += 4 {
+ if (j % (16 * 4)) == 0 {
+ fmt.Printf("\n\t")
+ } else {
+ fmt.Printf(" ")
+ }
+ d := uint32(im.data[j + 0]) << 16
+ d |= uint32(im.data[j + 1]) << 8
+ d |= uint32(im.data[j + 2])
+ d |= uint32(im.data[j + 3]) << 24
+ fmt.Printf("0x%08X,", d)
+
+ }
+ fmt.Println("\n};")
+ fmt.Println()
+ }
+ fmt.Println("static const struct {")
+ fmt.Println(" const char *name;")
+ fmt.Println(" void *data;")
+ fmt.Println(" int width;")
+ fmt.Println(" int height;")
+ fmt.Println(" int stride;")
+ fmt.Println("} files[] = {")
+ for i, im := range images {
+ fmt.Printf(" { %q, dat%d, %d, %d, %d },\n",
+ im.filename, i, im.width, im.height, im.stride)
+ }
+ fmt.Println("};")
+ fmt.Println()
+ fmt.Println("void appendImageNamed(uiImage *img, const char *name)")
+ fmt.Println("{")
+ fmt.Println(" int i;")
+ fmt.Println("")
+ fmt.Println(" i = 0;")
+ fmt.Println(" for (;;) {")
+ fmt.Println(" if (strcmp(name, files[i].name) == 0) {")
+ fmt.Println(" uiImageAppend(img, files[i].data, files[i].width, files[i].height, files[i].stride);")
+ fmt.Println(" return;")
+ fmt.Println(" }")
+ fmt.Println(" i++;")
+ fmt.Println(" }")
+ fmt.Println("}")
+ fmt.Println()
+}
diff --git a/src/libui_sdl/libui/test/images/tango-icon-theme-0.8.90_16x16_x-office-spreadsheet.png b/src/libui_sdl/libui/test/images/tango-icon-theme-0.8.90_16x16_x-office-spreadsheet.png
new file mode 100644
index 0000000..a6b1268
--- /dev/null
+++ b/src/libui_sdl/libui/test/images/tango-icon-theme-0.8.90_16x16_x-office-spreadsheet.png
Binary files differ
diff --git a/src/libui_sdl/libui/test/images/tango-icon-theme-0.8.90_32x32_x-office-spreadsheet.png b/src/libui_sdl/libui/test/images/tango-icon-theme-0.8.90_32x32_x-office-spreadsheet.png
new file mode 100644
index 0000000..c0ccb7a
--- /dev/null
+++ b/src/libui_sdl/libui/test/images/tango-icon-theme-0.8.90_32x32_x-office-spreadsheet.png
Binary files differ
diff --git a/src/libui_sdl/libui/test/main.c b/src/libui_sdl/libui/test/main.c
new file mode 100644
index 0000000..18774dc
--- /dev/null
+++ b/src/libui_sdl/libui/test/main.c
@@ -0,0 +1,180 @@
+// 22 april 2015
+#include "test.h"
+
+// TODOs
+// - blank page affects menus negatively on Windows
+
+void die(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ fprintf(stderr, "[test program] ");
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, "\n");
+ va_end(ap);
+ abort();
+}
+
+int onClosing(uiWindow *w, void *data)
+{
+ printf("in onClosing()\n");
+ uiQuit();
+ return 1;
+}
+
+int onShouldQuit(void *data)
+{
+ printf("in onShouldQuit()\n");
+ if (uiMenuItemChecked(shouldQuitItem)) {
+ uiControlDestroy(uiControl(data));
+ return 1;
+ }
+ return 0;
+}
+
+uiBox *mainBox;
+uiTab *mainTab;
+
+uiBox *(*newhbox)(void);
+uiBox *(*newvbox)(void);
+
+int main(int argc, char *argv[])
+{
+ uiInitOptions o;
+ int i;
+ const char *err;
+ uiWindow *w;
+ uiBox *page2, *page3, *page4, *page5;
+ uiBox *page6, *page7, *page8, *page9, *page10;
+ uiBox *page11, *page12, *page13;
+ uiTab *page14;
+ uiBox *page15;
+ uiBox *page16;
+ uiTab *outerTab;
+ uiTab *innerTab;
+ int nomenus = 0;
+ int startspaced = 0;
+ int steps = 0;
+
+ newhbox = uiNewHorizontalBox;
+ newvbox = uiNewVerticalBox;
+
+ memset(&o, 0, sizeof (uiInitOptions));
+ for (i = 1; i < argc; i++)
+ if (strcmp(argv[i], "nomenus") == 0)
+ nomenus = 1;
+ else if (strcmp(argv[i], "startspaced") == 0)
+ startspaced = 1;
+ else if (strcmp(argv[i], "swaphv") == 0) {
+ newhbox = uiNewVerticalBox;
+ newvbox = uiNewHorizontalBox;
+ } else if (strcmp(argv[i], "steps") == 0)
+ steps = 1;
+ else {
+ fprintf(stderr, "%s: unrecognized option %s\n", argv[0], argv[i]);
+ return 1;
+ }
+
+ err = uiInit(&o);
+ if (err != NULL) {
+ fprintf(stderr, "error initializing ui: %s\n", err);
+ uiFreeInitError(err);
+ return 1;
+ }
+
+ if (!nomenus)
+ initMenus();
+
+ w = newWindow("Main Window", 320, 240, 1);
+ uiWindowOnClosing(w, onClosing, NULL);
+ printf("main window %p\n", (void *) w);
+
+ uiOnShouldQuit(onShouldQuit, w);
+
+ mainBox = newHorizontalBox();
+ uiWindowSetChild(w, uiControl(mainBox));
+
+ outerTab = newTab();
+ uiBoxAppend(mainBox, uiControl(outerTab), 1);
+
+ mainTab = newTab();
+ uiTabAppend(outerTab, "Pages 1-5", uiControl(mainTab));
+
+ // page 1 uses page 2's uiGroup
+ page2 = makePage2();
+
+ makePage1(w);
+ uiTabAppend(mainTab, "Page 1", uiControl(page1));
+
+ uiTabAppend(mainTab, "Page 2", uiControl(page2));
+
+ uiTabAppend(mainTab, "Empty Page", uiControl(uiNewHorizontalBox()));
+
+ page3 = makePage3();
+ uiTabAppend(mainTab, "Page 3", uiControl(page3));
+
+ page4 = makePage4();
+ uiTabAppend(mainTab, "Page 4", uiControl(page4));
+
+ page5 = makePage5(w);
+ uiTabAppend(mainTab, "Page 5", uiControl(page5));
+
+ innerTab = newTab();
+ uiTabAppend(outerTab, "Pages 6-10", uiControl(innerTab));
+
+ page6 = makePage6();
+ uiTabAppend(innerTab, "Page 6", uiControl(page6));
+
+ page7 = makePage7();
+ uiTabAppend(innerTab, "Page 7", uiControl(page7));
+
+ page8 = makePage8();
+ uiTabAppend(innerTab, "Page 8", uiControl(page8));
+
+ page9 = makePage9();
+ uiTabAppend(innerTab, "Page 9", uiControl(page9));
+
+ page10 = makePage10();
+ uiTabAppend(innerTab, "Page 10", uiControl(page10));
+
+ innerTab = newTab();
+ uiTabAppend(outerTab, "Pages 11-15", uiControl(innerTab));
+
+// page11 = makePage11();
+// uiTabAppend(innerTab, "Page 11", uiControl(page11));
+
+ page12 = makePage12();
+ uiTabAppend(innerTab, "Page 12", uiControl(page12));
+
+ page13 = makePage13();
+ uiTabAppend(innerTab, "Page 13", uiControl(page13));
+
+ page14 = makePage14();
+ uiTabAppend(innerTab, "Page 14", uiControl(page14));
+
+ page15 = makePage15(w);
+ uiTabAppend(innerTab, "Page 15", uiControl(page15));
+
+ innerTab = newTab();
+ uiTabAppend(outerTab, "Pages 16-?", uiControl(innerTab));
+
+// page16 = makePage16();
+// uiTabAppend(innerTab, "Page 16", uiControl(page16));
+
+ if (startspaced)
+ setSpaced(1);
+
+ uiControlShow(uiControl(w));
+ if (!steps)
+ uiMain();
+ else {
+ uiMainSteps();
+ while (uiMainStep(1))
+ ;
+ }
+ printf("after uiMain()\n");
+ uiUninit();
+ printf("after uiUninit()\n");
+ return 0;
+}
diff --git a/src/libui_sdl/libui/test/menus.c b/src/libui_sdl/libui/test/menus.c
new file mode 100644
index 0000000..87ff80a
--- /dev/null
+++ b/src/libui_sdl/libui/test/menus.c
@@ -0,0 +1,112 @@
+// 23 april 2015
+#include "test.h"
+
+uiMenu *fileMenu;
+uiMenuItem *newItem;
+uiMenuItem *openItem;
+uiMenuItem *shouldQuitItem;
+uiMenuItem *quitItem;
+uiMenu *editMenu;
+uiMenuItem *undoItem;
+uiMenuItem *checkItem;
+uiMenuItem *accelItem;
+uiMenuItem *prefsItem;
+uiMenu *testMenu;
+uiMenuItem *enabledItem;
+uiMenuItem *enableThisItem;
+uiMenuItem *forceCheckedItem;
+uiMenuItem *forceUncheckedItem;
+uiMenuItem *whatWindowItem;
+uiMenu *moreTestsMenu;
+uiMenuItem *quitEnabledItem;
+uiMenuItem *prefsEnabledItem;
+uiMenuItem *aboutEnabledItem;
+uiMenuItem *checkEnabledItem;
+uiMenu *multiMenu;
+uiMenu *helpMenu;
+uiMenuItem *helpItem;
+uiMenuItem *aboutItem;
+
+static void enableItemTest(uiMenuItem *item, uiWindow *w, void *data)
+{
+ if (uiMenuItemChecked(item))
+ uiMenuItemEnable(uiMenuItem(data));
+ else
+ uiMenuItemDisable(uiMenuItem(data));
+}
+
+static void forceOn(uiMenuItem *item, uiWindow *w, void *data)
+{
+ uiMenuItemSetChecked(enabledItem, 1);
+}
+
+static void forceOff(uiMenuItem *item, uiWindow *w, void *data)
+{
+ uiMenuItemSetChecked(enabledItem, 0);
+}
+
+static void whatWindow(uiMenuItem *item, uiWindow *w, void *data)
+{
+ printf("menu item clicked on window %p\n", (void *) w);
+}
+
+void initMenus(void)
+{
+ fileMenu = uiNewMenu("File");
+ newItem = uiMenuAppendItem(fileMenu, "New");
+ openItem = uiMenuAppendItem(fileMenu, "Open");
+ uiMenuAppendSeparator(fileMenu);
+ shouldQuitItem = uiMenuAppendCheckItem(fileMenu, "Should Quit");
+ quitItem = uiMenuAppendQuitItem(fileMenu);
+
+ editMenu = uiNewMenu("Edit");
+ undoItem = uiMenuAppendItem(editMenu, "Undo");
+ uiMenuItemDisable(undoItem);
+ uiMenuAppendSeparator(editMenu);
+ checkItem = uiMenuAppendCheckItem(editMenu, "Check Me\tTest");
+ accelItem = uiMenuAppendItem(editMenu, "A&ccele&&rator T_es__t");
+ prefsItem = uiMenuAppendPreferencesItem(editMenu);
+
+ testMenu = uiNewMenu("Test");
+ enabledItem = uiMenuAppendCheckItem(testMenu, "Enable Below Item");
+ uiMenuItemSetChecked(enabledItem, 1);
+ enableThisItem = uiMenuAppendItem(testMenu, "This Will Be Enabled");
+ uiMenuItemOnClicked(enabledItem, enableItemTest, enableThisItem);
+ forceCheckedItem = uiMenuAppendItem(testMenu, "Force Above Checked");
+ uiMenuItemOnClicked(forceCheckedItem, forceOn, NULL);
+ forceUncheckedItem = uiMenuAppendItem(testMenu, "Force Above Unchecked");
+ uiMenuItemOnClicked(forceUncheckedItem, forceOff, NULL);
+ uiMenuAppendSeparator(testMenu);
+ whatWindowItem = uiMenuAppendItem(testMenu, "What Window?");
+ uiMenuItemOnClicked(whatWindowItem, whatWindow, NULL);
+
+ moreTestsMenu = uiNewMenu("More Tests");
+ quitEnabledItem = uiMenuAppendCheckItem(moreTestsMenu, "Quit Item Enabled");
+ uiMenuItemSetChecked(quitEnabledItem, 1);
+ prefsEnabledItem = uiMenuAppendCheckItem(moreTestsMenu, "Preferences Item Enabled");
+ uiMenuItemSetChecked(prefsEnabledItem, 1);
+ aboutEnabledItem = uiMenuAppendCheckItem(moreTestsMenu, "About Item Enabled");
+ uiMenuItemSetChecked(aboutEnabledItem, 1);
+ uiMenuAppendSeparator(moreTestsMenu);
+ checkEnabledItem = uiMenuAppendCheckItem(moreTestsMenu, "Check Me Item Enabled");
+ uiMenuItemSetChecked(checkEnabledItem, 1);
+
+ multiMenu = uiNewMenu("Multi");
+ uiMenuAppendSeparator(multiMenu);
+ uiMenuAppendSeparator(multiMenu);
+ uiMenuAppendItem(multiMenu, "Item && Item && Item");
+ uiMenuAppendSeparator(multiMenu);
+ uiMenuAppendSeparator(multiMenu);
+ uiMenuAppendItem(multiMenu, "Item __ Item __ Item");
+ uiMenuAppendSeparator(multiMenu);
+ uiMenuAppendSeparator(multiMenu);
+
+ helpMenu = uiNewMenu("Help");
+ helpItem = uiMenuAppendItem(helpMenu, "Help");
+ aboutItem = uiMenuAppendAboutItem(helpMenu);
+
+ uiMenuItemOnClicked(quitEnabledItem, enableItemTest, quitItem);
+ uiMenuItemOnClicked(prefsEnabledItem, enableItemTest, prefsItem);
+ uiMenuItemOnClicked(aboutEnabledItem, enableItemTest, aboutItem);
+ uiMenuItemOnClicked(checkEnabledItem, enableItemTest, checkItem);
+}
diff --git a/src/libui_sdl/libui/test/page1.c b/src/libui_sdl/libui/test/page1.c
new file mode 100644
index 0000000..2115ba2
--- /dev/null
+++ b/src/libui_sdl/libui/test/page1.c
@@ -0,0 +1,171 @@
+// 29 april 2015
+#include "test.h"
+
+static uiEntry *entry;
+static uiCheckbox *spaced;
+
+#define TEXT(name, type, getter, setter) \
+ static void get ## name ## Text(uiButton *b, void *data) \
+ { \
+ char *text; \
+ text = getter(type(data)); \
+ uiEntrySetText(entry, text); \
+ uiFreeText(text); \
+ } \
+ static void set ## name ## Text(uiButton *b, void *data) \
+ { \
+ char *text; \
+ text = uiEntryText(entry); \
+ setter(type(data), text); \
+ uiFreeText(text); \
+ }
+TEXT(Window, uiWindow, uiWindowTitle, uiWindowSetTitle)
+TEXT(Button, uiButton, uiButtonText, uiButtonSetText)
+TEXT(Checkbox, uiCheckbox, uiCheckboxText, uiCheckboxSetText)
+TEXT(Label, uiLabel, uiLabelText, uiLabelSetText)
+TEXT(Group, uiGroup, uiGroupTitle, uiGroupSetTitle)
+
+static void onChanged(uiEntry *e, void *data)
+{
+ printf("onChanged()\n");
+}
+
+static void toggleSpaced(uiCheckbox *c, void *data)
+{
+ setSpaced(uiCheckboxChecked(spaced));
+}
+
+static void forceSpaced(uiButton *b, void *data)
+{
+ uiCheckboxSetChecked(spaced, data != NULL);
+}
+
+static void showSpaced(uiButton *b, void *data)
+{
+ char s[12];
+
+ querySpaced(s);
+ uiEntrySetText(entry, s);
+}
+
+#define SHED(method, Method) \
+ static void method ## Control(uiButton *b, void *data) \
+ { \
+ uiControl ## Method(uiControl(data)); \
+ }
+SHED(show, Show)
+SHED(hide, Hide)
+SHED(enable, Enable)
+SHED(disable, Disable)
+
+uiBox *page1;
+
+void makePage1(uiWindow *w)
+{
+ uiButton *getButton, *setButton;
+ uiBox *hbox;
+ uiBox *testBox;
+ uiLabel *label;
+
+ page1 = newVerticalBox();
+
+ entry = uiNewEntry();
+ uiEntryOnChanged(entry, onChanged, NULL);
+ uiBoxAppend(page1, uiControl(entry), 0);
+
+ spaced = uiNewCheckbox("Spaced");
+ uiCheckboxOnToggled(spaced, toggleSpaced, NULL);
+ label = uiNewLabel("Label");
+
+ hbox = newHorizontalBox();
+ getButton = uiNewButton("Get Window Text");
+ uiButtonOnClicked(getButton, getWindowText, w);
+ setButton = uiNewButton("Set Window Text");
+ uiButtonOnClicked(setButton, setWindowText, w);
+ uiBoxAppend(hbox, uiControl(getButton), 1);
+ uiBoxAppend(hbox, uiControl(setButton), 1);
+ uiBoxAppend(page1, uiControl(hbox), 0);
+
+ hbox = newHorizontalBox();
+ getButton = uiNewButton("Get Button Text");
+ uiButtonOnClicked(getButton, getButtonText, getButton);
+ setButton = uiNewButton("Set Button Text");
+ uiButtonOnClicked(setButton, setButtonText, getButton);
+ uiBoxAppend(hbox, uiControl(getButton), 1);
+ uiBoxAppend(hbox, uiControl(setButton), 1);
+ uiBoxAppend(page1, uiControl(hbox), 0);
+
+ hbox = newHorizontalBox();
+ getButton = uiNewButton("Get Checkbox Text");
+ uiButtonOnClicked(getButton, getCheckboxText, spaced);
+ setButton = uiNewButton("Set Checkbox Text");
+ uiButtonOnClicked(setButton, setCheckboxText, spaced);
+ uiBoxAppend(hbox, uiControl(getButton), 1);
+ uiBoxAppend(hbox, uiControl(setButton), 1);
+ uiBoxAppend(page1, uiControl(hbox), 0);
+
+ hbox = newHorizontalBox();
+ getButton = uiNewButton("Get Label Text");
+ uiButtonOnClicked(getButton, getLabelText, label);
+ setButton = uiNewButton("Set Label Text");
+ uiButtonOnClicked(setButton, setLabelText, label);
+ uiBoxAppend(hbox, uiControl(getButton), 1);
+ uiBoxAppend(hbox, uiControl(setButton), 1);
+ uiBoxAppend(page1, uiControl(hbox), 0);
+
+ hbox = newHorizontalBox();
+ getButton = uiNewButton("Get Group Text");
+ uiButtonOnClicked(getButton, getGroupText, page2group);
+ setButton = uiNewButton("Set Group Text");
+ uiButtonOnClicked(setButton, setGroupText, page2group);
+ uiBoxAppend(hbox, uiControl(getButton), 1);
+ uiBoxAppend(hbox, uiControl(setButton), 1);
+ uiBoxAppend(page1, uiControl(hbox), 0);
+
+ hbox = newHorizontalBox();
+ uiBoxAppend(hbox, uiControl(spaced), 1);
+ getButton = uiNewButton("On");
+ uiButtonOnClicked(getButton, forceSpaced, getButton);
+ uiBoxAppend(hbox, uiControl(getButton), 0);
+ getButton = uiNewButton("Off");
+ uiButtonOnClicked(getButton, forceSpaced, NULL);
+ uiBoxAppend(hbox, uiControl(getButton), 0);
+ getButton = uiNewButton("Show");
+ uiButtonOnClicked(getButton, showSpaced, NULL);
+ uiBoxAppend(hbox, uiControl(getButton), 0);
+ uiBoxAppend(page1, uiControl(hbox), 0);
+
+ testBox = newHorizontalBox();
+ setButton = uiNewButton("Button");
+ uiBoxAppend(testBox, uiControl(setButton), 1);
+ getButton = uiNewButton("Show");
+ uiButtonOnClicked(getButton, showControl, setButton);
+ uiBoxAppend(testBox, uiControl(getButton), 0);
+ getButton = uiNewButton("Hide");
+ uiButtonOnClicked(getButton, hideControl, setButton);
+ uiBoxAppend(testBox, uiControl(getButton), 0);
+ getButton = uiNewButton("Enable");
+ uiButtonOnClicked(getButton, enableControl, setButton);
+ uiBoxAppend(testBox, uiControl(getButton), 0);
+ getButton = uiNewButton("Disable");
+ uiButtonOnClicked(getButton, disableControl, setButton);
+ uiBoxAppend(testBox, uiControl(getButton), 0);
+ uiBoxAppend(page1, uiControl(testBox), 0);
+
+ hbox = newHorizontalBox();
+ getButton = uiNewButton("Show Box");
+ uiButtonOnClicked(getButton, showControl, testBox);
+ uiBoxAppend(hbox, uiControl(getButton), 1);
+ getButton = uiNewButton("Hide Box");
+ uiButtonOnClicked(getButton, hideControl, testBox);
+ uiBoxAppend(hbox, uiControl(getButton), 1);
+ getButton = uiNewButton("Enable Box");
+ uiButtonOnClicked(getButton, enableControl, testBox);
+ uiBoxAppend(hbox, uiControl(getButton), 1);
+ getButton = uiNewButton("Disable Box");
+ uiButtonOnClicked(getButton, disableControl, testBox);
+ uiBoxAppend(hbox, uiControl(getButton), 1);
+ uiBoxAppend(page1, uiControl(hbox), 0);
+
+ uiBoxAppend(page1, uiControl(label), 0);
+}
diff --git a/src/libui_sdl/libui/test/page10.c b/src/libui_sdl/libui/test/page10.c
new file mode 100644
index 0000000..d7f26a7
--- /dev/null
+++ b/src/libui_sdl/libui/test/page10.c
@@ -0,0 +1,185 @@
+// 22 december 2015
+#include "test.h"
+
+static uiEntry *textString;
+static uiFontButton *textFontButton;
+static uiColorButton *textColorButton;
+static uiEntry *textWidth;
+static uiButton *textApply;
+static uiCheckbox *noZ;
+static uiArea *textArea;
+static uiAreaHandler textAreaHandler;
+
+static double entryDouble(uiEntry *e)
+{
+ char *s;
+ double d;
+
+ s = uiEntryText(e);
+ d = atof(s);
+ uiFreeText(s);
+ return d;
+}
+
+static void handlerDraw(uiAreaHandler *a, uiArea *area, uiAreaDrawParams *dp)
+{
+ uiDrawTextFont *font;
+ uiDrawTextLayout *layout;
+ double r, g, b, al;
+ char surrogates[1 + 4 + 1 + 1];
+ char composed[2 + 2 + 2 + 3 + 2 + 1];
+ double width, height;
+
+ font = uiFontButtonFont(textFontButton);
+
+ layout = uiDrawNewTextLayout("One two three four", font, -1);
+ uiDrawTextLayoutSetColor(layout,
+ 4, 7,
+ 1, 0, 0, 1);
+ uiDrawTextLayoutSetColor(layout,
+ 8, 14,
+ 1, 0, 0.5, 0.5);
+ uiColorButtonColor(textColorButton, &r, &g, &b, &al);
+ uiDrawTextLayoutSetColor(layout,
+ 14, 18,
+ r, g, b, al);
+ uiDrawText(dp->Context, 10, 10, layout);
+ uiDrawTextLayoutExtents(layout, &width, &height);
+ uiDrawFreeTextLayout(layout);
+
+ surrogates[0] = 'x';
+ surrogates[1] = 0xF0; // surrogates D800 DF08
+ surrogates[2] = 0x90;
+ surrogates[3] = 0x8C;
+ surrogates[4] = 0x88;
+ surrogates[5] = 'y';
+ surrogates[6] = '\0';
+
+ layout = uiDrawNewTextLayout(surrogates, font, -1);
+ uiDrawTextLayoutSetColor(layout,
+ 1, 2,
+ 1, 0, 0.5, 0.5);
+ uiDrawText(dp->Context, 10, 10 + height, layout);
+ uiDrawFreeTextLayout(layout);
+
+ composed[0] = 'z';
+ composed[1] = 'z';
+ composed[2] = 0xC3; // 2
+ composed[3] = 0xA9;
+ composed[4] = 'z';
+ composed[5] = 'z';
+ composed[6] = 0x65; // 5
+ composed[7] = 0xCC;
+ composed[8] = 0x81;
+ composed[9] = 'z';
+ composed[10] = 'z';
+ composed[11] = '\0';
+
+ layout = uiDrawNewTextLayout(composed, font, -1);
+ uiDrawTextLayoutSetColor(layout,
+ 2, 3,
+ 1, 0, 0.5, 0.5);
+ uiDrawTextLayoutSetColor(layout,
+ 5, 6,
+ 1, 0, 0.5, 0.5);
+ if (!uiCheckboxChecked(noZ))
+ uiDrawTextLayoutSetColor(layout,
+ 6, 7,
+ 0.5, 0, 1, 0.5);
+ uiDrawText(dp->Context, 10, 10 + height + height, layout);
+ uiDrawFreeTextLayout(layout);
+
+ uiDrawFreeTextFont(font);
+}
+
+static void handlerMouseEvent(uiAreaHandler *a, uiArea *area, uiAreaMouseEvent *e)
+{
+ // do nothing
+}
+
+static void handlerMouseCrossed(uiAreaHandler *ah, uiArea *a, int left)
+{
+ // do nothing
+}
+
+static void handlerDragBroken(uiAreaHandler *ah, uiArea *a)
+{
+ // do nothing
+}
+
+static int handlerKeyEvent(uiAreaHandler *ah, uiArea *a, uiAreaKeyEvent *e)
+{
+ // do nothing
+ return 0;
+}
+
+static void onFontChanged(uiFontButton *b, void *data)
+{
+ uiAreaQueueRedrawAll(textArea);
+}
+
+static void onColorChanged(uiColorButton *b, void *data)
+{
+ uiAreaQueueRedrawAll(textArea);
+}
+
+static void onNoZ(uiCheckbox *b, void *data)
+{
+ uiAreaQueueRedrawAll(textArea);
+}
+
+uiBox *makePage10(void)
+{
+ uiBox *page10;
+ uiBox *vbox;
+ uiBox *hbox;
+
+ page10 = newVerticalBox();
+ vbox = page10;
+
+ hbox = newHorizontalBox();
+ uiBoxAppend(vbox, uiControl(hbox), 0);
+
+ textString = uiNewEntry();
+ // TODO make it placeholder
+ uiEntrySetText(textString, "Enter text here");
+ uiBoxAppend(hbox, uiControl(textString), 1);
+
+ textFontButton = uiNewFontButton();
+ uiFontButtonOnChanged(textFontButton, onFontChanged, NULL);
+ uiBoxAppend(hbox, uiControl(textFontButton), 1);
+
+ textColorButton = uiNewColorButton();
+ uiColorButtonOnChanged(textColorButton, onColorChanged, NULL);
+ uiBoxAppend(hbox, uiControl(textColorButton), 1);
+
+ hbox = newHorizontalBox();
+ uiBoxAppend(vbox, uiControl(hbox), 0);
+
+ textApply = uiNewButton("Apply");
+ uiBoxAppend(hbox, uiControl(textApply), 1);
+
+ textWidth = uiNewEntry();
+ uiEntrySetText(textWidth, "-1");
+ uiBoxAppend(hbox, uiControl(textWidth), 1);
+
+ noZ = uiNewCheckbox("No Z Color");
+ uiCheckboxOnToggled(noZ, onNoZ, NULL);
+ uiBoxAppend(hbox, uiControl(noZ), 0);
+
+ textAreaHandler.Draw = handlerDraw;
+ textAreaHandler.MouseEvent = handlerMouseEvent;
+ textAreaHandler.MouseCrossed = handlerMouseCrossed;
+ textAreaHandler.DragBroken = handlerDragBroken;
+ textAreaHandler.KeyEvent = handlerKeyEvent;
+ textArea = uiNewArea(&textAreaHandler);
+ uiBoxAppend(vbox, uiControl(textArea), 1);
+
+ // dummy objects to test single-activation
+ hbox = newHorizontalBox();
+ uiBoxAppend(vbox, uiControl(hbox), 0);
+ uiBoxAppend(hbox, uiControl(uiNewFontButton()), 1);
+ uiBoxAppend(hbox, uiControl(uiNewColorButton()), 1);
+
+ return page10;
+}
diff --git a/src/libui_sdl/libui/test/page11.c b/src/libui_sdl/libui/test/page11.c
new file mode 100644
index 0000000..02ad213
--- /dev/null
+++ b/src/libui_sdl/libui/test/page11.c
@@ -0,0 +1,54 @@
+// 14 may 2016
+#include "test.h"
+
+// TODO add a test for childless windows
+// TODO add tests for contianers with all controls hidden
+
+static uiGroup *newg(const char *n, int s)
+{
+ uiGroup *g;
+
+ g = uiNewGroup(n);
+ if (s)
+ uiGroupSetChild(g, NULL);
+ return g;
+}
+
+static uiTab *newt(int tt)
+{
+ uiTab *t;
+
+ t = uiNewTab();
+ if (tt)
+ uiTabAppend(t, "Test", NULL);
+ return t;
+}
+
+uiBox *makePage11(void)
+{
+ uiBox *page11;
+ uiBox *ns;
+ uiBox *s;
+
+ page11 = newHorizontalBox();
+
+ ns = newVerticalBox();
+ uiBoxAppend(ns, uiControl(newg("", 0)), 0);
+ uiBoxAppend(ns, uiControl(newg("", 1)), 0);
+ uiBoxAppend(ns, uiControl(newg("Group", 0)), 0);
+ uiBoxAppend(ns, uiControl(newg("Group", 1)), 0);
+ uiBoxAppend(ns, uiControl(newt(0)), 0);
+ uiBoxAppend(ns, uiControl(newt(1)), 0);
+ uiBoxAppend(page11, uiControl(ns), 1);
+
+ s = newVerticalBox();
+ uiBoxAppend(s, uiControl(newg("", 0)), 1);
+ uiBoxAppend(s, uiControl(newg("", 1)), 1);
+ uiBoxAppend(s, uiControl(newg("Group", 0)), 1);
+ uiBoxAppend(s, uiControl(newg("Group", 1)), 1);
+ uiBoxAppend(s, uiControl(newt(0)), 1);
+ uiBoxAppend(s, uiControl(newt(1)), 1);
+ uiBoxAppend(page11, uiControl(s), 1);
+
+ return page11;
+}
diff --git a/src/libui_sdl/libui/test/page12.c b/src/libui_sdl/libui/test/page12.c
new file mode 100644
index 0000000..5a8e963
--- /dev/null
+++ b/src/libui_sdl/libui/test/page12.c
@@ -0,0 +1,60 @@
+// 22 may 2016
+#include "test.h"
+
+// TODO OS X: if the hboxes are empty, the text views don't show up
+
+static void meChanged(uiMultilineEntry *e, void *data)
+{
+ printf("%s changed\n", (char *) data);
+}
+
+static void setClicked(uiButton *b, void *data)
+{
+ uiMultilineEntrySetText(uiMultilineEntry(data), "set");
+}
+
+static void appendClicked(uiButton *b, void *data)
+{
+ uiMultilineEntryAppend(uiMultilineEntry(data), "append\n");
+}
+
+static uiBox *half(uiMultilineEntry *(*mk)(void), const char *which)
+{
+ uiBox *vbox, *hbox;
+ uiMultilineEntry *me;
+ uiButton *button;
+
+ vbox = newVerticalBox();
+
+ me = (*mk)();
+ uiMultilineEntryOnChanged(me, meChanged, (void *) which);
+ uiBoxAppend(vbox, uiControl(me), 1);
+
+ hbox = newHorizontalBox();
+ uiBoxAppend(vbox, uiControl(hbox), 0);
+
+ button = uiNewButton("Set");
+ uiButtonOnClicked(button, setClicked, me);
+ uiBoxAppend(hbox, uiControl(button), 0);
+
+ button = uiNewButton("Append");
+ uiButtonOnClicked(button, appendClicked, me);
+ uiBoxAppend(hbox, uiControl(button), 0);
+
+ return vbox;
+}
+
+uiBox *makePage12(void)
+{
+ uiBox *page12;
+ uiBox *b;
+
+ page12 = newHorizontalBox();
+
+ b = half(uiNewMultilineEntry, "wrap");
+ uiBoxAppend(page12, uiControl(b), 1);
+ b = half(uiNewNonWrappingMultilineEntry, "no wrap");
+ uiBoxAppend(page12, uiControl(b), 1);
+
+ return page12;
+}
diff --git a/src/libui_sdl/libui/test/page13.c b/src/libui_sdl/libui/test/page13.c
new file mode 100644
index 0000000..5e6fd52
--- /dev/null
+++ b/src/libui_sdl/libui/test/page13.c
@@ -0,0 +1,157 @@
+// 28 may 2016
+#include "test.h"
+
+static int winClose(uiWindow *w, void *data)
+{
+ return 1;
+}
+
+static void openTestWindow(uiBox *(*mkf)(void))
+{
+ uiWindow *w;
+ uiBox *b;
+ uiCombobox *c;
+ uiEditableCombobox *e;
+ uiRadioButtons *r;
+
+ w = uiNewWindow("Test", 100, 100, 0);
+ uiWindowOnClosing(w, winClose, NULL);
+ uiWindowSetMargined(w, 1);
+ b = (*mkf)();
+ uiWindowSetChild(w, uiControl(b));
+
+#define BA(x) uiBoxAppend(b, uiControl(x), 0)
+ BA(uiNewButton(""));
+ BA(uiNewCheckbox(""));
+ BA(uiNewEntry());
+ BA(uiNewLabel(""));
+ BA(uiNewSpinbox(0, 100));
+ BA(uiNewProgressBar());
+ BA(uiNewSlider(0, 100));
+ BA(uiNewHorizontalSeparator());
+ c = uiNewCombobox();
+ uiComboboxAppend(c, "");
+ BA(c);
+ e = uiNewEditableCombobox();
+ uiEditableComboboxAppend(e, "");
+ BA(e);
+ r = uiNewRadioButtons();
+ uiRadioButtonsAppend(r, "");
+ BA(r);
+ BA(uiNewDateTimePicker());
+ BA(uiNewDatePicker());
+ BA(uiNewTimePicker());
+ BA(uiNewMultilineEntry());
+ // TODO nonscrolling and scrolling areas?
+ BA(uiNewFontButton());
+ BA(uiNewColorButton());
+ BA(uiNewPasswordEntry());
+ BA(uiNewSearchEntry());
+ BA(uiNewVerticalSeparator());
+
+ uiControlShow(uiControl(w));
+}
+
+static void buttonClicked(uiButton *b, void *data)
+{
+ openTestWindow((uiBox *(*)(void)) data);
+}
+
+static void entryChanged(uiEntry *e, void *data)
+{
+ char *text;
+
+ text = uiEntryText(e);
+ printf("%s entry changed: %s\n", (const char *) data, text);
+ uiFreeText(text);
+}
+
+static void showHide(uiButton *b, void *data)
+{
+ uiControl *c = uiControl(data);
+
+ if (uiControlVisible(c))
+ uiControlHide(c);
+ else
+ uiControlShow(c);
+}
+
+static void setIndeterminate(uiButton *b, void *data)
+{
+ uiProgressBar *p = uiProgressBar(data);
+ int value;
+
+ value = uiProgressBarValue(p);
+ if (value == -1)
+ value = 50;
+ else
+ value = -1;
+ uiProgressBarSetValue(p, value);
+}
+
+static void deleteFirst(uiButton *b, void *data)
+{
+ uiForm *f = uiForm(data);
+
+ uiFormDelete(f, 0);
+}
+
+uiBox *makePage13(void)
+{
+ uiBox *page13;
+ uiRadioButtons *rb;
+ uiButton *b;
+ uiForm *f;
+ uiEntry *e;
+ uiProgressBar *p;
+
+ page13 = newVerticalBox();
+
+ rb = uiNewRadioButtons();
+ uiRadioButtonsAppend(rb, "Item 1");
+ uiRadioButtonsAppend(rb, "Item 2");
+ uiRadioButtonsAppend(rb, "Item 3");
+ uiBoxAppend(page13, uiControl(rb), 0);
+
+ rb = uiNewRadioButtons();
+ uiRadioButtonsAppend(rb, "Item A");
+ uiRadioButtonsAppend(rb, "Item B");
+ uiBoxAppend(page13, uiControl(rb), 0);
+
+ b = uiNewButton("Horizontal");
+ uiButtonOnClicked(b, buttonClicked, uiNewHorizontalBox);
+ uiBoxAppend(page13, uiControl(b), 0);
+
+ b = uiNewButton("Vertical");
+ uiButtonOnClicked(b, buttonClicked, uiNewVerticalBox);
+ uiBoxAppend(page13, uiControl(b), 0);
+
+ f = newForm();
+
+ e = uiNewPasswordEntry();
+ uiEntryOnChanged(e, entryChanged, "password");
+ uiFormAppend(f, "Password Entry", uiControl(e), 0);
+
+ e = uiNewSearchEntry();
+ uiEntryOnChanged(e, entryChanged, "search");
+ uiFormAppend(f, "Search Box", uiControl(e), 0);
+
+ uiFormAppend(f, "MLE", uiControl(uiNewMultilineEntry()), 1);
+
+ p = uiNewProgressBar();
+ uiProgressBarSetValue(p, 50);
+ uiBoxAppend(page13, uiControl(p), 0);
+ b = uiNewButton("Toggle Indeterminate");
+ uiButtonOnClicked(b, setIndeterminate, p);
+ uiBoxAppend(page13, uiControl(b), 0);
+
+ b = uiNewButton("Show/Hide");
+ uiButtonOnClicked(b, showHide, e);
+ uiBoxAppend(page13, uiControl(b), 0);
+ b = uiNewButton("Delete First");
+ uiButtonOnClicked(b, deleteFirst, f);
+ uiBoxAppend(page13, uiControl(b), 0);
+ uiBoxAppend(page13, uiControl(f), 1);
+
+ return page13;
+}
diff --git a/src/libui_sdl/libui/test/page14.c b/src/libui_sdl/libui/test/page14.c
new file mode 100644
index 0000000..880534c
--- /dev/null
+++ b/src/libui_sdl/libui/test/page14.c
@@ -0,0 +1,350 @@
+// 9 june 2016
+#include "test.h"
+
+// TODOs:
+// - GTK+ - make all expanding controls the same size, to match the other OSs? will they match the other OSs?
+
+enum {
+ red,
+ green,
+ blue,
+ yellow,
+ white,
+ magenta,
+ orange,
+ purple,
+ cyan,
+};
+
+static const struct {
+ double r;
+ double g;
+ double b;
+} colors[] = {
+ { 1, 0, 0 },
+ { 0, 0.5, 0 },
+ { 0, 0, 1 },
+ { 1, 1, 0 },
+ { 1, 1, 1 },
+ { 1, 0, 1 },
+ { 1, 0.65, 0 },
+ { 0.5, 0, 0.5 },
+ { 0, 1, 1 },
+};
+
+static uiControl *testControl(const char *label, int color)
+{
+ uiColorButton *b;
+
+ b = uiNewColorButton();
+ uiColorButtonSetColor(b, colors[color].r, colors[color].g, colors[color].b, 1.0);
+ return uiControl(b);
+}
+
+static uiControl *simpleGrid(void)
+{
+ uiGrid *g;
+ uiControl *t4;
+
+ g = newGrid();
+ uiGridAppend(g, testControl("1", red),
+ 0, 0, 1, 1,
+ 0, uiAlignFill, 0, uiAlignFill);
+ uiGridAppend(g, testControl("2", green),
+ 1, 0, 1, 1,
+ 0, uiAlignFill, 0, uiAlignFill);
+ uiGridAppend(g, testControl("3", blue),
+ 2, 0, 1, 1,
+ 0, uiAlignFill, 0, uiAlignFill);
+ t4 = testControl("4", green);
+ uiGridAppend(g, t4,
+ 0, 1, 1, 1,
+ 0, uiAlignFill, 1, uiAlignFill);
+ uiGridInsertAt(g, testControl("5", blue),
+ t4, uiAtTrailing, 2, 1,
+ 0, uiAlignFill, 0, uiAlignFill);
+ uiGridAppend(g, testControl("6", yellow),
+ -1, 0, 1, 2,
+ 1, uiAlignFill, 0, uiAlignFill);
+ return uiControl(g);
+}
+
+static uiControl *boxComparison(void)
+{
+ uiBox *vbox;
+ uiGrid *g;
+ uiBox *hbox;
+
+ vbox = newVerticalBox();
+ uiBoxAppend(vbox, uiControl(uiNewLabel("Above")), 0);
+ uiBoxAppend(vbox, uiControl(uiNewHorizontalSeparator()), 0);
+
+ hbox = newHorizontalBox();
+ uiBoxAppend(vbox, uiControl(hbox), 0);
+ uiBoxAppend(hbox, testControl("1", white), 0);
+ uiBoxAppend(hbox, uiControl(uiNewLabel("A label")), 1);
+ uiBoxAppend(hbox, testControl("2", green), 0);
+ uiBoxAppend(hbox, uiControl(uiNewLabel("Another label")), 1);
+ uiBoxAppend(hbox, testControl("3", red), 0);
+
+ uiBoxAppend(vbox, uiControl(uiNewHorizontalSeparator()), 0);
+
+ g = newGrid();
+ uiBoxAppend(vbox, uiControl(g), 0);
+ uiGridAppend(g, testControl("1", white),
+ 0, 0, 1, 1,
+ 0, uiAlignFill, 0, uiAlignFill);
+ uiGridAppend(g, uiControl(uiNewLabel("A label")),
+ 1, 0, 1, 1,
+ 1, uiAlignFill, 0, uiAlignFill);
+ uiGridAppend(g, testControl("2", green),
+ 2, 0, 1, 1,
+ 0, uiAlignFill, 0, uiAlignFill);
+ uiGridAppend(g, uiControl(uiNewLabel("Another label")),
+ 3, 0, 1, 1,
+ 1, uiAlignFill, 0, uiAlignFill);
+ uiGridAppend(g, testControl("3", red),
+ 4, 0, 1, 1,
+ 0, uiAlignFill, 0, uiAlignFill);
+
+ uiBoxAppend(vbox, uiControl(uiNewHorizontalSeparator()), 0);
+ uiBoxAppend(vbox, uiControl(uiNewLabel("Below")), 0);
+ return uiControl(vbox);
+}
+
+static uiControl *emptyLine(void)
+{
+ uiGrid *g;
+
+ g = newGrid();
+ uiGridAppend(g, testControl("(0, 0)", red),
+ 0, 0, 1, 1,
+ 1, uiAlignFill, 1, uiAlignFill);
+ uiGridAppend(g, testControl("(0, 1)", blue),
+ 0, 1, 1, 1,
+ 0, uiAlignFill, 0, uiAlignFill);
+ uiGridAppend(g, testControl("(10, 0)", green),
+ 10, 0, 1, 1,
+ 0, uiAlignFill, 0, uiAlignFill);
+ uiGridAppend(g, testControl("(10, 1)", magenta),
+ 10, 1, 1, 1,
+ 0, uiAlignFill, 0, uiAlignFill);
+ return uiControl(g);
+}
+
+static uiControl *emptyGrid(void)
+{
+ uiGrid *g;
+ uiControl *t;
+
+ g = newGrid();
+ t = testControl("(0, 0)", red);
+ uiGridAppend(g, t,
+ 0, 0, 1, 1,
+ 1, uiAlignFill, 1, uiAlignFill);
+ uiControlHide(t);
+ return uiControl(g);
+}
+
+// TODO insert (need specialized insert/delete)
+
+static uiControl *spanningGrid(void)
+{
+ uiGrid *g;
+
+ g = newGrid();
+ uiGridAppend(g, testControl("0", blue),
+ 0, 4, 4, 1,
+ 1, uiAlignFill, 0, uiAlignFill);
+ uiGridAppend(g, testControl("1", green),
+ 4, 0, 1, 4,
+ 0, uiAlignFill, 1, uiAlignFill);
+ uiGridAppend(g, testControl("2", red),
+ 3, 3, 1, 1,
+ 1, uiAlignFill, 1, uiAlignFill);
+ uiGridAppend(g, testControl("3", yellow),
+ 0, 3, 2, 1,
+ 0, uiAlignFill, 0, uiAlignFill);
+ uiGridAppend(g, testControl("4", orange),
+ 3, 0, 1, 2,
+ 0, uiAlignFill, 0, uiAlignFill);
+ uiGridAppend(g, testControl("5", purple),
+ 1, 1, 1, 1,
+ 0, uiAlignFill, 0, uiAlignFill);
+ uiGridAppend(g, testControl("6", white),
+ 0, 1, 1, 1,
+ 0, uiAlignFill, 0, uiAlignFill);
+ uiGridAppend(g, testControl("7", cyan),
+ 1, 0, 1, 1,
+ 0, uiAlignFill, 0, uiAlignFill);
+ return uiControl(g);
+}
+
+// TODO make non-global
+static uiButton *hideOne, *one, *showOne;
+
+static void onHideOne(uiButton *b, void *data)
+{
+ uiControlHide(uiControl(one));
+}
+
+static void onShowOne(uiButton *b, void *data)
+{
+ uiControlShow(uiControl(one));
+}
+
+static void onHideAll(uiButton *b, void *data)
+{
+ uiControlHide(uiControl(hideOne));
+ uiControlHide(uiControl(one));
+ uiControlHide(uiControl(showOne));
+}
+
+static void onShowAll(uiButton *b, void *data)
+{
+ uiControlShow(uiControl(hideOne));
+ uiControlShow(uiControl(one));
+ uiControlShow(uiControl(showOne));
+}
+
+#define AT(x) static void onInsert ## x(uiButton *b, void *data) \
+ { \
+ uiGrid *g = uiGrid(data); \
+ uiGridInsertAt(g, uiControl(uiNewButton("Button")), \
+ uiControl(b), uiAt ## x, 1, 1, \
+ 0, uiAlignFill, 0, uiAlignFill); \
+ }
+AT(Leading)
+AT(Top)
+AT(Trailing)
+AT(Bottom)
+
+static uiControl *assorted(void)
+{
+ uiGrid *outergrid;
+ uiGrid *innergrid;
+ uiButton *b;
+
+ outergrid = newGrid();
+
+ innergrid = newGrid();
+ one = uiNewButton("Test");
+ uiGridAppend(innergrid, uiControl(one),
+ 1, 1, 1, 1,
+ 0, uiAlignFill, 0, uiAlignFill);
+ hideOne = uiNewButton("Hide One");
+ uiButtonOnClicked(hideOne, onHideOne, NULL);
+ uiGridAppend(innergrid, uiControl(hideOne),
+ 0, 1, 1, 1,
+ 0, uiAlignFill, 0, uiAlignFill);
+ showOne = uiNewButton("Show One");
+ uiButtonOnClicked(showOne, onShowOne, NULL);
+ uiGridAppend(innergrid, uiControl(showOne),
+ 2, 1, 1, 1,
+ 0, uiAlignFill, 0, uiAlignFill);
+ b = uiNewButton("Hide All");
+ uiButtonOnClicked(b, onHideAll, NULL);
+ uiGridAppend(innergrid, uiControl(b),
+ 1, 0, 1, 1,
+ 0, uiAlignFill, 0, uiAlignFill);
+ b = uiNewButton("Show All");
+ uiButtonOnClicked(b, onShowAll, NULL);
+ uiGridAppend(innergrid, uiControl(b),
+ 1, 2, 1, 1,
+ 0, uiAlignFill, 0, uiAlignFill);
+ uiGridAppend(outergrid, uiControl(innergrid),
+ 0, 0, 1, 1,
+ 1, uiAlignFill, 1, uiAlignFill);
+
+ innergrid = newGrid();
+ b = uiNewButton("Insert Trailing");
+ uiButtonOnClicked(b, onInsertTrailing, innergrid);
+ uiGridAppend(innergrid, uiControl(b),
+ 0, 0, 1, 1,
+ 1, uiAlignFill, 0, uiAlignFill);
+ b = uiNewButton("Insert Bottom");
+ uiButtonOnClicked(b, onInsertBottom, innergrid);
+ uiGridAppend(innergrid, uiControl(b),
+ 1, 0, 1, 1,
+ 1, uiAlignFill, 0, uiAlignFill);
+ b = uiNewButton("Insert Leading");
+ uiButtonOnClicked(b, onInsertLeading, innergrid);
+ uiGridAppend(innergrid, uiControl(b),
+ 1, 1, 1, 1,
+ 1, uiAlignFill, 0, uiAlignFill);
+ b = uiNewButton("Insert Top");
+ uiButtonOnClicked(b, onInsertTop, innergrid);
+ uiGridAppend(innergrid, uiControl(b),
+ 0, 1, 1, 1,
+ 1, uiAlignFill, 0, uiAlignFill);
+ uiGridAppend(outergrid, uiControl(innergrid),
+ 1, 0, 1, 1,
+ 1, uiAlignFill, 1, uiAlignFill);
+
+ innergrid = newGrid();
+ uiGridAppend(innergrid, uiControl(uiNewColorButton()),
+ 0, 0, 1, 1,
+ 1, uiAlignFill, 0, uiAlignFill);
+ uiGridAppend(innergrid, uiControl(uiNewColorButton()),
+ 0, 1, 1, 1,
+ 1, uiAlignStart, 0, uiAlignFill);
+ uiGridAppend(innergrid, uiControl(uiNewColorButton()),
+ 0, 2, 1, 1,
+ 1, uiAlignCenter, 0, uiAlignFill);
+ uiGridAppend(innergrid, uiControl(uiNewColorButton()),
+ 0, 3, 1, 1,
+ 1, uiAlignEnd, 0, uiAlignFill);
+ uiGridAppend(outergrid, uiControl(innergrid),
+ 0, 1, 1, 1,
+ 1, uiAlignFill, 1, uiAlignFill);
+
+ // TODO with only this, wrong size on OS X — expand sizing thing?
+ innergrid = newGrid();
+ uiGridAppend(innergrid, uiControl(uiNewColorButton()),
+ 0, 0, 1, 1,
+ 0, uiAlignFill, 1, uiAlignFill);
+ uiGridAppend(innergrid, uiControl(uiNewColorButton()),
+ 1, 0, 1, 1,
+ 0, uiAlignFill, 1, uiAlignStart);
+ uiGridAppend(innergrid, uiControl(uiNewColorButton()),
+ 2, 0, 1, 1,
+ 0, uiAlignFill, 1, uiAlignCenter);
+ uiGridAppend(innergrid, uiControl(uiNewColorButton()),
+ 3, 0, 1, 1,
+ 0, uiAlignFill, 1, uiAlignEnd);
+ uiGridAppend(outergrid, uiControl(innergrid),
+ 1, 1, 1, 1,
+ 1, uiAlignFill, 1, uiAlignFill);
+
+ return uiControl(outergrid);
+}
+
+static const struct {
+ const char *name;
+ uiControl *(*f)(void);
+} pages[] = {
+ // based on GTK+ test/testgrid.c
+ { "Simple Grid", simpleGrid },
+ { "Box Comparison", boxComparison },
+ { "Empty Line", emptyLine },
+ { "Empty Grid", emptyGrid },
+ { "Spanning Grid", spanningGrid },
+ // my own
+ { "Assorted", assorted },
+ { NULL, NULL },
+};
+
+uiTab *makePage14(void)
+{
+ uiTab *page14;
+ int i;
+
+ page14 = newTab();
+
+ for (i = 0; pages[i].name != NULL; i++)
+ uiTabAppend(page14,
+ pages[i].name,
+ (*(pages[i].f))());
+
+ return page14;
+}
diff --git a/src/libui_sdl/libui/test/page15.c b/src/libui_sdl/libui/test/page15.c
new file mode 100644
index 0000000..e703bee
--- /dev/null
+++ b/src/libui_sdl/libui/test/page15.c
@@ -0,0 +1,260 @@
+// 15 june 2016
+#include "test.h"
+
+static uiAreaHandler borderAH;
+static int borderAHInit = 0;
+static double lastx = -1, lasty = -1;
+
+struct trect {
+ double left;
+ double top;
+ double right;
+ double bottom;
+ int in;
+};
+
+#define tsetrect(re, l, t, r, b) re.left = l; re.top = t; re.right = r; re.bottom = b; re.in = lastx >= re.left && lastx < re.right && lasty >= re.top && lasty < re.bottom
+
+struct tareas {
+ struct trect move;
+ struct trect alsomove;
+ struct trect leftresize;
+ struct trect topresize;
+ struct trect rightresize;
+ struct trect bottomresize;
+ struct trect topleftresize;
+ struct trect toprightresize;
+ struct trect bottomleftresize;
+ struct trect bottomrightresize;
+ struct trect close;
+};
+
+static void filltareas(double awid, double aht, struct tareas *ta)
+{
+ tsetrect(ta->move, 20, 20, awid - 20, 20 + 30);
+ tsetrect(ta->alsomove, 30, 200, 100, 270);
+ tsetrect(ta->leftresize, 5, 20, 15, aht - 20);
+ tsetrect(ta->topresize, 20, 5, awid - 20, 15);
+ tsetrect(ta->rightresize, awid - 15, 20, awid - 5, aht - 20);
+ tsetrect(ta->bottomresize, 20, aht - 15, awid - 20, aht - 5);
+ tsetrect(ta->topleftresize, 5, 5, 15, 15);
+ tsetrect(ta->toprightresize, awid - 15, 5, awid - 5, 15);
+ tsetrect(ta->bottomleftresize, 5, aht - 15, 15, aht - 5);
+ tsetrect(ta->bottomrightresize, awid - 15, aht - 15, awid - 5, aht - 5);
+ tsetrect(ta->close, 130, 200, 200, 270);
+}
+
+static void drawtrect(uiDrawContext *c, struct trect tr, double r, double g, double bl)
+{
+ uiDrawPath *p;
+ uiDrawBrush b;
+
+ memset(&b, 0, sizeof (uiDrawBrush));
+ b.Type = uiDrawBrushTypeSolid;
+ b.R = r;
+ b.G = g;
+ b.B = bl;
+ b.A = 1.0;
+ if (tr.in) {
+ b.R += b.R * 0.75;
+ b.G += b.G * 0.75;
+ b.B += b.B * 0.75;
+ }
+ p = uiDrawNewPath(uiDrawFillModeWinding);
+ uiDrawPathAddRectangle(p,
+ tr.left,
+ tr.top,
+ tr.right - tr.left,
+ tr.bottom - tr.top);
+ uiDrawPathEnd(p);
+ uiDrawFill(c, p, &b);
+ uiDrawFreePath(p);
+}
+
+static void handlerDraw(uiAreaHandler *a, uiArea *area, uiAreaDrawParams *p)
+{
+ struct tareas ta;
+
+ filltareas(p->AreaWidth, p->AreaHeight, &ta);
+ drawtrect(p->Context, ta.move, 0, 0.5, 0);
+ drawtrect(p->Context, ta.alsomove, 0, 0.5, 0);
+ drawtrect(p->Context, ta.leftresize, 0, 0, 0.5);
+ drawtrect(p->Context, ta.topresize, 0, 0, 0.5);
+ drawtrect(p->Context, ta.rightresize, 0, 0, 0.5);
+ drawtrect(p->Context, ta.bottomresize, 0, 0, 0.5);
+ drawtrect(p->Context, ta.topleftresize, 0, 0.5, 0.5);
+ drawtrect(p->Context, ta.toprightresize, 0, 0.5, 0.5);
+ drawtrect(p->Context, ta.bottomleftresize, 0, 0.5, 0.5);
+ drawtrect(p->Context, ta.bottomrightresize, 0, 0.5, 0.5);
+ drawtrect(p->Context, ta.close, 0.5, 0, 0);
+
+ // TODO add current position prints here
+}
+
+static void handlerMouseEvent(uiAreaHandler *a, uiArea *area, uiAreaMouseEvent *e)
+{
+ struct tareas ta;
+
+ lastx = e->X;
+ lasty = e->Y;
+ filltareas(e->AreaWidth, e->AreaHeight, &ta);
+ // redraw our highlighted rect
+ uiAreaQueueRedrawAll(area);
+ if (e->Down != 1)
+ return;
+ if (ta.move.in || ta.alsomove.in) {
+ uiAreaBeginUserWindowMove(area);
+ return;
+ }
+#define resize(cond, edge) if (cond) { uiAreaBeginUserWindowResize(area, edge); return; }
+ resize(ta.leftresize.in, uiWindowResizeEdgeLeft)
+ resize(ta.topresize.in, uiWindowResizeEdgeTop)
+ resize(ta.rightresize.in, uiWindowResizeEdgeRight)
+ resize(ta.bottomresize.in, uiWindowResizeEdgeBottom)
+ resize(ta.topleftresize.in, uiWindowResizeEdgeTopLeft)
+ resize(ta.toprightresize.in, uiWindowResizeEdgeTopRight)
+ resize(ta.bottomleftresize.in, uiWindowResizeEdgeBottomLeft)
+ resize(ta.bottomrightresize.in, uiWindowResizeEdgeBottomRight)
+ if (ta.close.in) {
+ // TODO
+ return;
+ }
+}
+
+static void handlerMouseCrossed(uiAreaHandler *ah, uiArea *a, int left)
+{
+}
+
+static void handlerDragBroken(uiAreaHandler *ah, uiArea *a)
+{
+}
+
+static int handlerKeyEvent(uiAreaHandler *ah, uiArea *a, uiAreaKeyEvent *e)
+{
+ return 0;
+}
+
+static void borderWindowOpen(uiButton *b, void *data)
+{
+ uiWindow *w;
+ uiArea *a;
+
+ if (!borderAHInit) {
+ borderAH.Draw = handlerDraw;
+ borderAH.MouseEvent = handlerMouseEvent;
+ borderAH.MouseCrossed = handlerMouseCrossed;
+ borderAH.DragBroken = handlerDragBroken;
+ borderAH.KeyEvent = handlerKeyEvent;
+ borderAHInit = 1;
+ }
+
+ w = uiNewWindow("Border Resize Test", 300, 500, 0);
+ uiWindowSetBorderless(w, 1);
+
+ a = uiNewArea(&borderAH);
+// uiWindowSetChild(w, uiControl(a));
+{uiBox *b;
+b=uiNewHorizontalBox();
+uiBoxAppend(b,uiControl(a),1);
+uiWindowSetChild(w,uiControl(b));}
+//TODO why is this hack needed? GTK+ issue
+
+ uiControlShow(uiControl(w));
+}
+
+static uiSpinbox *width, *height;
+static uiCheckbox *fullscreen;
+
+static void sizeWidth(uiSpinbox *s, void *data)
+{
+ uiWindow *w = uiWindow(data);
+ int xp, yp;
+
+ uiWindowContentSize(w, &xp, &yp);
+ xp = uiSpinboxValue(width);
+ uiWindowSetContentSize(w, xp, yp);
+}
+
+static void sizeHeight(uiSpinbox *s, void *data)
+{
+ uiWindow *w = uiWindow(data);
+ int xp, yp;
+
+ uiWindowContentSize(w, &xp, &yp);
+ yp = uiSpinboxValue(height);
+ uiWindowSetContentSize(w, xp, yp);
+}
+
+static void updatesize(uiWindow *w)
+{
+ int xp, yp;
+
+ uiWindowContentSize(w, &xp, &yp);
+ uiSpinboxSetValue(width, xp);
+ uiSpinboxSetValue(height, yp);
+ // TODO on OS X this is updated AFTER sending the size change, not before
+ uiCheckboxSetChecked(fullscreen, uiWindowFullscreen(w));
+}
+
+void onSize(uiWindow *w, void *data)
+{
+ printf("size\n");
+ updatesize(w);
+}
+
+void setFullscreen(uiCheckbox *cb, void *data)
+{
+ uiWindow *w = uiWindow(data);
+
+ uiWindowSetFullscreen(w, uiCheckboxChecked(fullscreen));
+ updatesize(w);
+}
+
+static void borderless(uiCheckbox *c, void *data)
+{
+ uiWindow *w = uiWindow(data);
+
+ uiWindowSetBorderless(w, uiCheckboxChecked(c));
+}
+
+uiBox *makePage15(uiWindow *w)
+{
+ uiBox *page15;
+ uiBox *hbox;
+ uiButton *button;
+ uiCheckbox *checkbox;
+
+ page15 = newVerticalBox();
+
+ hbox = newHorizontalBox();
+ uiBoxAppend(page15, uiControl(hbox), 0);
+
+ uiBoxAppend(hbox, uiControl(uiNewLabel("Size")), 0);
+ width = uiNewSpinbox(INT_MIN, INT_MAX);
+ uiBoxAppend(hbox, uiControl(width), 1);
+ height = uiNewSpinbox(INT_MIN, INT_MAX);
+ uiBoxAppend(hbox, uiControl(height), 1);
+ fullscreen = uiNewCheckbox("Fullscreen");
+ uiBoxAppend(hbox, uiControl(fullscreen), 0);
+
+ uiSpinboxOnChanged(width, sizeWidth, w);
+ uiSpinboxOnChanged(height, sizeHeight, w);
+ uiCheckboxOnToggled(fullscreen, setFullscreen, w);
+ uiWindowOnContentSizeChanged(w, onSize, NULL);
+ updatesize(w);
+
+ checkbox = uiNewCheckbox("Borderless");
+ uiCheckboxOnToggled(checkbox, borderless, w);
+ uiBoxAppend(page15, uiControl(checkbox), 0);
+
+ button = uiNewButton("Borderless Resizes");
+ uiButtonOnClicked(button, borderWindowOpen, NULL);
+ uiBoxAppend(page15, uiControl(button), 0);
+
+ hbox = newHorizontalBox();
+ uiBoxAppend(page15, uiControl(hbox), 1);
+
+ uiBoxAppend(hbox, uiControl(uiNewVerticalSeparator()), 0);
+
+ return page15;
+}
diff --git a/src/libui_sdl/libui/test/page2.c b/src/libui_sdl/libui/test/page2.c
new file mode 100644
index 0000000..abb0648
--- /dev/null
+++ b/src/libui_sdl/libui/test/page2.c
@@ -0,0 +1,215 @@
+// 29 april 2015
+#include "test.h"
+
+uiGroup *page2group;
+
+static uiLabel *movingLabel;
+static uiBox *movingBoxes[2];
+static int movingCurrent;
+
+static void moveLabel(uiButton *b, void *data)
+{
+ int from, to;
+
+ from = movingCurrent;
+ to = 0;
+ if (from == 0)
+ to = 1;
+ uiBoxDelete(movingBoxes[from], 0);
+ uiBoxAppend(movingBoxes[to], uiControl(movingLabel), 0);
+ movingCurrent = to;
+}
+
+static int moveBack;
+#define moveOutText "Move Page 1 Out"
+#define moveBackText "Move Page 1 Back"
+
+static void movePage1(uiButton *b, void *data)
+{
+ if (moveBack) {
+ uiBoxDelete(mainBox, 1);
+ uiTabInsertAt(mainTab, "Page 1", 0, uiControl(page1));
+ uiButtonSetText(b, moveOutText);
+ moveBack = 0;
+ return;
+ }
+ uiTabDelete(mainTab, 0);
+ uiBoxAppend(mainBox, uiControl(page1), 1);
+ uiButtonSetText(b, moveBackText);
+ moveBack = 1;
+}
+
+static void openAnotherWindow(uiButton *bb, void *data)
+{
+ uiWindow *w;
+ uiBox *b;
+
+ w = uiNewWindow("Another Window", 100, 100, data != NULL);
+ if (data != NULL) {
+ b = uiNewVerticalBox();
+ uiBoxAppend(b, uiControl(uiNewEntry()), 0);
+ uiBoxAppend(b, uiControl(uiNewButton("Button")), 0);
+ uiBoxSetPadded(b, 1);
+ uiWindowSetChild(w, uiControl(b));
+ } else
+ uiWindowSetChild(w, uiControl(makePage6()));
+ uiWindowSetMargined(w, 1);
+ uiControlShow(uiControl(w));
+}
+
+static void openAnotherDisabledWindow(uiButton *b, void *data)
+{
+ uiWindow *w;
+
+ w = uiNewWindow("Another Window", 100, 100, data != NULL);
+ uiControlDisable(uiControl(w));
+ uiControlShow(uiControl(w));
+}
+
+#define SHED(method, Method) \
+ static void method ## Control(uiButton *b, void *data) \
+ { \
+ uiControl ## Method(uiControl(data)); \
+ }
+SHED(show, Show)
+SHED(enable, Enable)
+SHED(disable, Disable)
+
+static void echoReadOnlyText(uiEntry *e, void *data)
+{
+ char *text;
+
+ text = uiEntryText(e);
+ uiEntrySetText(uiEntry(data), text);
+ uiFreeText(text);
+}
+
+uiBox *makePage2(void)
+{
+ uiBox *page2;
+ uiBox *hbox;
+ uiGroup *group;
+ uiBox *vbox;
+ uiButton *button;
+ uiBox *nestedBox;
+ uiBox *innerhbox;
+ uiBox *innerhbox2;
+ uiBox *innerhbox3;
+ uiTab *disabledTab;
+ uiEntry *entry;
+ uiEntry *readonly;
+ uiButton *button2;
+
+ page2 = newVerticalBox();
+
+ group = newGroup("Moving Label");
+ page2group = group;
+ uiBoxAppend(page2, uiControl(group), 0);
+ vbox = newVerticalBox();
+ uiGroupSetChild(group, uiControl(vbox));
+
+ hbox = newHorizontalBox();
+ button = uiNewButton("Move the Label!");
+ uiButtonOnClicked(button, moveLabel, NULL);
+ uiBoxAppend(hbox, uiControl(button), 1);
+ // have a blank label for space
+ uiBoxAppend(hbox, uiControl(uiNewLabel("")), 1);
+ uiBoxAppend(vbox, uiControl(hbox), 0);
+
+ hbox = newHorizontalBox();
+ movingBoxes[0] = newVerticalBox();
+ uiBoxAppend(hbox, uiControl(movingBoxes[0]), 1);
+ movingBoxes[1] = newVerticalBox();
+ uiBoxAppend(hbox, uiControl(movingBoxes[1]), 1);
+ uiBoxAppend(vbox, uiControl(hbox), 0);
+
+ movingCurrent = 0;
+ movingLabel = uiNewLabel("This label moves!");
+ uiBoxAppend(movingBoxes[movingCurrent], uiControl(movingLabel), 0);
+
+ hbox = newHorizontalBox();
+ button = uiNewButton(moveOutText);
+ uiButtonOnClicked(button, movePage1, NULL);
+ uiBoxAppend(hbox, uiControl(button), 0);
+ uiBoxAppend(page2, uiControl(hbox), 0);
+ moveBack = 0;
+
+ hbox = newHorizontalBox();
+ uiBoxAppend(hbox, uiControl(uiNewLabel("Label Alignment Test")), 0);
+ button = uiNewButton("Open Menued Window");
+ uiButtonOnClicked(button, openAnotherWindow, button);
+ uiBoxAppend(hbox, uiControl(button), 0);
+ button = uiNewButton("Open Menuless Window");
+ uiButtonOnClicked(button, openAnotherWindow, NULL);
+ uiBoxAppend(hbox, uiControl(button), 0);
+ button = uiNewButton("Disabled Menued");
+ uiButtonOnClicked(button, openAnotherDisabledWindow, button);
+ uiBoxAppend(hbox, uiControl(button), 0);
+ button = uiNewButton("Disabled Menuless");
+ uiButtonOnClicked(button, openAnotherDisabledWindow, NULL);
+ uiBoxAppend(hbox, uiControl(button), 0);
+ uiBoxAppend(page2, uiControl(hbox), 0);
+
+ nestedBox = newHorizontalBox();
+ innerhbox = newHorizontalBox();
+ uiBoxAppend(innerhbox, uiControl(uiNewButton("These")), 0);
+ button = uiNewButton("buttons");
+ uiControlDisable(uiControl(button));
+ uiBoxAppend(innerhbox, uiControl(button), 0);
+ uiBoxAppend(nestedBox, uiControl(innerhbox), 0);
+ innerhbox = newHorizontalBox();
+ uiBoxAppend(innerhbox, uiControl(uiNewButton("are")), 0);
+ innerhbox2 = newHorizontalBox();
+ button = uiNewButton("in");
+ uiControlDisable(uiControl(button));
+ uiBoxAppend(innerhbox2, uiControl(button), 0);
+ uiBoxAppend(innerhbox, uiControl(innerhbox2), 0);
+ uiBoxAppend(nestedBox, uiControl(innerhbox), 0);
+ innerhbox = newHorizontalBox();
+ innerhbox2 = newHorizontalBox();
+ uiBoxAppend(innerhbox2, uiControl(uiNewButton("nested")), 0);
+ innerhbox3 = newHorizontalBox();
+ button = uiNewButton("boxes");
+ uiControlDisable(uiControl(button));
+ uiBoxAppend(innerhbox3, uiControl(button), 0);
+ uiBoxAppend(innerhbox2, uiControl(innerhbox3), 0);
+ uiBoxAppend(innerhbox, uiControl(innerhbox2), 0);
+ uiBoxAppend(nestedBox, uiControl(innerhbox), 0);
+ uiBoxAppend(page2, uiControl(nestedBox), 0);
+
+ hbox = newHorizontalBox();
+ button = uiNewButton("Enable Nested Box");
+ uiButtonOnClicked(button, enableControl, nestedBox);
+ uiBoxAppend(hbox, uiControl(button), 0);
+ button = uiNewButton("Disable Nested Box");
+ uiButtonOnClicked(button, disableControl, nestedBox);
+ uiBoxAppend(hbox, uiControl(button), 0);
+ uiBoxAppend(page2, uiControl(hbox), 0);
+
+ disabledTab = newTab();
+ uiTabAppend(disabledTab, "Disabled", uiControl(uiNewButton("Button")));
+ uiTabAppend(disabledTab, "Tab", uiControl(uiNewLabel("Label")));
+ uiControlDisable(uiControl(disabledTab));
+ uiBoxAppend(page2, uiControl(disabledTab), 1);
+
+ entry = uiNewEntry();
+ readonly = uiNewEntry();
+ uiEntryOnChanged(entry, echoReadOnlyText, readonly);
+ uiEntrySetText(readonly, "If you can see this, uiEntryReadOnly() isn't working properly.");
+ uiEntrySetReadOnly(readonly, 1);
+ if (uiEntryReadOnly(readonly))
+ uiEntrySetText(readonly, "");
+ uiBoxAppend(page2, uiControl(entry), 0);
+ uiBoxAppend(page2, uiControl(readonly), 0);
+
+ hbox = newHorizontalBox();
+ button = uiNewButton("Show Button 2");
+ button2 = uiNewButton("Button 2");
+ uiButtonOnClicked(button, showControl, button2);
+ uiControlHide(uiControl(button2));
+ uiBoxAppend(hbox, uiControl(button), 1);
+ uiBoxAppend(hbox, uiControl(button2), 0);
+ uiBoxAppend(page2, uiControl(hbox), 0);
+
+ return page2;
+}
diff --git a/src/libui_sdl/libui/test/page3.c b/src/libui_sdl/libui/test/page3.c
new file mode 100644
index 0000000..1f229e9
--- /dev/null
+++ b/src/libui_sdl/libui/test/page3.c
@@ -0,0 +1,69 @@
+// 7 may 2015
+#include "test.h"
+
+static uiBox *makeSet(int omit, int hidden, int stretch)
+{
+ uiBox *hbox;
+ uiButton *buttons[4];
+
+ // don't use newHorizontalBox()
+ // the point of this test is to test hidden controls and padded
+ hbox = (*newhbox)();
+ uiBoxSetPadded(hbox, 1);
+ if (omit != 0) {
+ buttons[0] = uiNewButton("First");
+ uiBoxAppend(hbox, uiControl(buttons[0]), stretch);
+ }
+ if (omit != 1) {
+ buttons[1] = uiNewButton("Second");
+ uiBoxAppend(hbox, uiControl(buttons[1]), stretch);
+ }
+ if (omit != 2) {
+ buttons[2] = uiNewButton("Third");
+ uiBoxAppend(hbox, uiControl(buttons[2]), stretch);
+ }
+ if (omit != 3) {
+ buttons[3] = uiNewButton("Fourth");
+ uiBoxAppend(hbox, uiControl(buttons[3]), stretch);
+ }
+ if (hidden != -1)
+ uiControlHide(uiControl(buttons[hidden]));
+ return hbox;
+}
+
+uiBox *makePage3(void)
+{
+ uiBox *page3;
+ uiBox *hbox;
+ uiBox *hbox2;
+ uiBox *vbox;
+ int hidden;
+
+ page3 = newVerticalBox();
+
+ // first the non-stretchy type
+ for (hidden = 0; hidden < 4; hidden++) {
+ // these two must stay unpadded as well, otherwise the test isn't meaningful
+ hbox2 = (*newhbox)();
+ vbox = (*newvbox)();
+ // reference set
+ hbox = makeSet(hidden, -1, 0);
+ uiBoxAppend(vbox, uiControl(hbox), 0);
+ // real thing
+ hbox = makeSet(-1, hidden, 0);
+ uiBoxAppend(vbox, uiControl(hbox), 0);
+ // pack vbox in
+ uiBoxAppend(hbox2, uiControl(vbox), 0);
+ // and have a button in there for showing right margins
+ uiBoxAppend(hbox2, uiControl(uiNewButton("Right Margin Test")), 1);
+ uiBoxAppend(page3, uiControl(hbox2), 0);
+ }
+
+ // then the stretchy type
+ for (hidden = 0; hidden < 4; hidden++) {
+ hbox = makeSet(-1, hidden, 1);
+ uiBoxAppend(page3, uiControl(hbox), 0);
+ }
+
+ return page3;
+}
diff --git a/src/libui_sdl/libui/test/page4.c b/src/libui_sdl/libui/test/page4.c
new file mode 100644
index 0000000..ce4a6af
--- /dev/null
+++ b/src/libui_sdl/libui/test/page4.c
@@ -0,0 +1,165 @@
+// 19 may 2015
+#include "test.h"
+
+static uiSpinbox *spinbox;
+static uiSlider *slider;
+static uiProgressBar *pbar;
+
+#define CHANGED(what) \
+ static void on ## what ## Changed(ui ## what *this, void *data) \
+ { \
+ int value; \
+ printf("on %s changed\n", #what); \
+ value = ui ## what ## Value(this); \
+ uiSpinboxSetValue(spinbox, value); \
+ uiSliderSetValue(slider, value); \
+ uiProgressBarSetValue(pbar, value); \
+ }
+CHANGED(Spinbox)
+CHANGED(Slider)
+
+#define SETTOO(what, name, n) \
+ static void set ## what ## Too ## name(uiButton *this, void *data) \
+ { \
+ ui ## what ## SetValue(ui ## what(data), n); \
+ }
+SETTOO(Spinbox, Low, -80)
+SETTOO(Spinbox, High, 80)
+SETTOO(Slider, Low, -80)
+SETTOO(Slider, High, 80)
+
+static uiCombobox *cbox;
+static uiEditableCombobox *editable;
+static uiRadioButtons *rb;
+
+static void appendCBRB(uiButton *b, void *data)
+{
+ uiComboboxAppend(cbox, "New Item");
+ uiEditableComboboxAppend(editable, "New Item");
+ uiRadioButtonsAppend(rb, "New Item");
+}
+
+static void onCBChanged(uiCombobox *c, void *data)
+{
+ printf("%s combobox changed to %d\n",
+ (char *) data,
+ (int) uiComboboxSelected(c));
+ uiEditableComboboxSetText(editable, "changed");
+}
+
+static void onECBChanged(uiEditableCombobox *c, void *data)
+{
+ char *t;
+
+ t = uiEditableComboboxText(c);
+ printf("%s combobox changed to %s\n",
+ (char *) data,
+ t);
+ uiFreeText(t);
+}
+
+static void onRBSelected(uiRadioButtons *r, void *data)
+{
+ printf("radio buttons %d\n", uiRadioButtonsSelected(r));
+}
+
+static void selectSecond(uiButton *b, void *data)
+{
+ // TODO combobox, editable
+ uiRadioButtonsSetSelected(rb, 1);
+}
+
+static void selectNone(uiButton *b, void *data)
+{
+ // TODO combobox, editable
+ uiRadioButtonsSetSelected(rb, -1);
+}
+
+uiBox *makePage4(void)
+{
+ uiBox *page4;
+ uiBox *hbox;
+ uiSpinbox *xsb;
+ uiButton *b;
+ uiSlider *xsl;
+
+ page4 = newVerticalBox();
+
+ spinbox = uiNewSpinbox(0, 100);
+ uiSpinboxOnChanged(spinbox, onSpinboxChanged, NULL);
+ uiBoxAppend(page4, uiControl(spinbox), 0);
+
+ slider = uiNewSlider(0, 100);
+ uiSliderOnChanged(slider, onSliderChanged, NULL);
+ uiBoxAppend(page4, uiControl(slider), 0);
+
+ pbar = uiNewProgressBar();
+ uiBoxAppend(page4, uiControl(pbar), 0);
+
+ uiBoxAppend(page4, uiControl(uiNewHorizontalSeparator()), 0);
+
+ hbox = newHorizontalBox();
+ xsb = uiNewSpinbox(-40, 40);
+ uiBoxAppend(hbox, uiControl(xsb), 0);
+ b = uiNewButton("Bad Low");
+ uiButtonOnClicked(b, setSpinboxTooLow, xsb);
+ uiBoxAppend(hbox, uiControl(b), 0);
+ b = uiNewButton("Bad High");
+ uiButtonOnClicked(b, setSpinboxTooHigh, xsb);
+ uiBoxAppend(hbox, uiControl(b), 0);
+ uiBoxAppend(page4, uiControl(hbox), 0);
+
+ hbox = newHorizontalBox();
+ xsl = uiNewSlider(-40, 40);
+ uiBoxAppend(hbox, uiControl(xsl), 0);
+ b = uiNewButton("Bad Low");
+ uiButtonOnClicked(b, setSliderTooLow, xsl);
+ uiBoxAppend(hbox, uiControl(b), 0);
+ b = uiNewButton("Bad High");
+ uiButtonOnClicked(b, setSliderTooHigh, xsl);
+ uiBoxAppend(hbox, uiControl(b), 0);
+ uiBoxAppend(page4, uiControl(hbox), 0);
+
+ uiBoxAppend(page4, uiControl(uiNewHorizontalSeparator()), 0);
+
+ cbox = uiNewCombobox();
+ uiComboboxAppend(cbox, "Item 1");
+ uiComboboxAppend(cbox, "Item 2");
+ uiComboboxAppend(cbox, "Item 3");
+ uiComboboxOnSelected(cbox, onCBChanged, "noneditable");
+ uiBoxAppend(page4, uiControl(cbox), 0);
+
+ editable = uiNewEditableCombobox();
+ uiEditableComboboxAppend(editable, "Editable Item 1");
+ uiEditableComboboxAppend(editable, "Editable Item 2");
+ uiEditableComboboxAppend(editable, "Editable Item 3");
+ uiEditableComboboxOnChanged(editable, onECBChanged, "editable");
+ uiBoxAppend(page4, uiControl(editable), 0);
+
+ rb = uiNewRadioButtons();
+ uiRadioButtonsAppend(rb, "Item 1");
+ uiRadioButtonsAppend(rb, "Item 2");
+ uiRadioButtonsAppend(rb, "Item 3");
+ uiRadioButtonsOnSelected(rb, onRBSelected, NULL);
+ uiBoxAppend(page4, uiControl(rb), 0);
+
+ hbox = newHorizontalBox();
+ b = uiNewButton("Append");
+ uiButtonOnClicked(b, appendCBRB, NULL);
+ uiBoxAppend(hbox, uiControl(b), 0);
+ b = uiNewButton("Second");
+ uiButtonOnClicked(b, selectSecond, NULL);
+ uiBoxAppend(hbox, uiControl(b), 0);
+ b = uiNewButton("None");
+ uiButtonOnClicked(b, selectNone, NULL);
+ uiBoxAppend(hbox, uiControl(b), 0);
+ uiBoxAppend(page4, uiControl(hbox), 0);
+
+ uiBoxAppend(page4, uiControl(uiNewHorizontalSeparator()), 0);
+
+ uiBoxAppend(page4, uiControl(uiNewDateTimePicker()), 0);
+ uiBoxAppend(page4, uiControl(uiNewDatePicker()), 0);
+ uiBoxAppend(page4, uiControl(uiNewTimePicker()), 0);
+
+ return page4;
+}
diff --git a/src/libui_sdl/libui/test/page5.c b/src/libui_sdl/libui/test/page5.c
new file mode 100644
index 0000000..9bc1105
--- /dev/null
+++ b/src/libui_sdl/libui/test/page5.c
@@ -0,0 +1,99 @@
+// 22 may 2015
+#include "test.h"
+
+static uiWindow *parent;
+
+static void openFile(uiButton *b, void *data)
+{
+ char *fn;
+
+ fn = uiOpenFile(parent);
+ if (fn == NULL)
+ uiLabelSetText(uiLabel(data), "(cancelled)");
+ else {
+ uiLabelSetText(uiLabel(data), fn);
+ uiFreeText(fn);
+ }
+}
+
+static void saveFile(uiButton *b, void *data)
+{
+ char *fn;
+
+ fn = uiSaveFile(parent);
+ if (fn == NULL)
+ uiLabelSetText(uiLabel(data), "(cancelled)");
+ else {
+ uiLabelSetText(uiLabel(data), fn);
+ uiFreeText(fn);
+ }
+}
+
+static uiEntry *title, *description;
+
+static void msgBox(uiButton *b, void *data)
+{
+ char *t, *d;
+
+ t = uiEntryText(title);
+ d = uiEntryText(description);
+ uiMsgBox(parent, t, d);
+ uiFreeText(d);
+ uiFreeText(t);
+}
+
+static void msgBoxError(uiButton *b, void *data)
+{
+ char *t, *d;
+
+ t = uiEntryText(title);
+ d = uiEntryText(description);
+ uiMsgBoxError(parent, t, d);
+ uiFreeText(d);
+ uiFreeText(t);
+}
+
+uiBox *makePage5(uiWindow *pw)
+{
+ uiBox *page5;
+ uiBox *hbox;
+ uiButton *button;
+ uiLabel *label;
+
+ parent = pw;
+
+ page5 = newVerticalBox();
+
+#define D(n, f) \
+ hbox = newHorizontalBox(); \
+ button = uiNewButton(n); \
+ label = uiNewLabel(""); \
+ uiButtonOnClicked(button, f, label); \
+ uiBoxAppend(hbox, uiControl(button), 0); \
+ uiBoxAppend(hbox, uiControl(label), 0); \
+ uiBoxAppend(page5, uiControl(hbox), 0);
+
+ D("Open File", openFile);
+ D("Save File", saveFile);
+
+ title = uiNewEntry();
+ uiEntrySetText(title, "Title");
+ description = uiNewEntry();
+ uiEntrySetText(description, "Description");
+
+ hbox = newHorizontalBox();
+ button = uiNewButton("Message Box");
+ uiButtonOnClicked(button, msgBox, NULL);
+ uiBoxAppend(hbox, uiControl(button), 0);
+ uiBoxAppend(hbox, uiControl(title), 0);
+ uiBoxAppend(page5, uiControl(hbox), 0);
+
+ hbox = newHorizontalBox();
+ button = uiNewButton("Error Box");
+ uiButtonOnClicked(button, msgBoxError, NULL);
+ uiBoxAppend(hbox, uiControl(button), 0);
+ uiBoxAppend(hbox, uiControl(description), 0);
+ uiBoxAppend(page5, uiControl(hbox), 0);
+
+ return page5;
+}
diff --git a/src/libui_sdl/libui/test/page6.c b/src/libui_sdl/libui/test/page6.c
new file mode 100644
index 0000000..896b3d5
--- /dev/null
+++ b/src/libui_sdl/libui/test/page6.c
@@ -0,0 +1,126 @@
+// 8 october 2015
+#include <inttypes.h>
+#include "test.h"
+
+static uiArea *area;
+static uiCombobox *which;
+static uiCheckbox *swallowKeys;
+
+struct handler {
+ uiAreaHandler ah;
+};
+
+static struct handler handler;
+
+static void handlerDraw(uiAreaHandler *a, uiArea *area, uiAreaDrawParams *p)
+{
+ runDrawTest(uiComboboxSelected(which), p);
+}
+
+static void handlerMouseEvent(uiAreaHandler *a, uiArea *area, uiAreaMouseEvent *e)
+{
+ printf("mouse (%g,%g):(%g,%g) down:%d up:%d count:%d mods:%x held:0x%" PRIX64 "\n",
+ e->X,
+ e->Y,
+ e->AreaWidth,
+ e->AreaHeight,
+ (int) e->Down,
+ (int) e->Up,
+ (int) e->Count,
+ (uint32_t) e->Modifiers,
+ e->Held1To64);
+}
+
+static void handlerMouseCrossed(uiAreaHandler *ah, uiArea *a, int left)
+{
+ printf("mouse crossed %d\n", left);
+}
+
+static void handlerDragBroken(uiAreaHandler *ah, uiArea *a)
+{
+ printf("drag broken\n");
+}
+
+static int handlerKeyEvent(uiAreaHandler *ah, uiArea *a, uiAreaKeyEvent *e)
+{
+ char k[4];
+
+ k[0] = '\'';
+ k[1] = e->Key;
+ k[2] = '\'';
+ k[3] = '\0';
+ if (e->Key == 0) {
+ k[0] = '0';
+ k[1] = '\0';
+ }
+ printf("key key:%s extkey:%d mod:%d mods:%d up:%d\n",
+ k,
+ (int) e->ExtKey,
+ (int) e->Modifier,
+ (int) e->Modifiers,
+ e->Up);
+ return uiCheckboxChecked(swallowKeys);
+}
+
+static void shouldntHappen(uiCombobox *c, void *data)
+{
+ fprintf(stderr, "YOU SHOULD NOT SEE THIS. If you do, uiComboboxSetSelected() is triggering uiComboboxOnSelected(), which it should not.\n");
+}
+
+static void redraw(uiCombobox *c, void *data)
+{
+ uiAreaQueueRedrawAll(area);
+}
+
+static void enableArea(uiButton *b, void *data)
+{
+ if (data != NULL)
+ uiControlEnable(uiControl(area));
+ else
+ uiControlDisable(uiControl(area));
+}
+
+uiBox *makePage6(void)
+{
+ uiBox *page6;
+ uiBox *hbox;
+ uiButton *button;
+
+ handler.ah.Draw = handlerDraw;
+ handler.ah.MouseEvent = handlerMouseEvent;
+ handler.ah.MouseCrossed = handlerMouseCrossed;
+ handler.ah.DragBroken = handlerDragBroken;
+ handler.ah.KeyEvent = handlerKeyEvent;
+
+ page6 = newVerticalBox();
+
+ hbox = newHorizontalBox();
+ uiBoxAppend(page6, uiControl(hbox), 0);
+
+ which = uiNewCombobox();
+ populateComboboxWithTests(which);
+ // this is to make sure that uiComboboxOnSelected() doesn't trigger with uiComboboxSetSelected()
+ uiComboboxOnSelected(which, shouldntHappen, NULL);
+ uiComboboxSetSelected(which, 0);
+ uiComboboxOnSelected(which, redraw, NULL);
+ uiBoxAppend(hbox, uiControl(which), 0);
+
+ area = uiNewArea((uiAreaHandler *) (&handler));
+ uiBoxAppend(page6, uiControl(area), 1);
+
+ hbox = newHorizontalBox();
+ uiBoxAppend(page6, uiControl(hbox), 0);
+
+ swallowKeys = uiNewCheckbox("Consider key events handled");
+ uiBoxAppend(hbox, uiControl(swallowKeys), 1);
+
+ button = uiNewButton("Enable");
+ uiButtonOnClicked(button, enableArea, button);
+ uiBoxAppend(hbox, uiControl(button), 0);
+
+ button = uiNewButton("Disable");
+ uiButtonOnClicked(button, enableArea, NULL);
+ uiBoxAppend(hbox, uiControl(button), 0);
+
+ return page6;
+}
diff --git a/src/libui_sdl/libui/test/page7.c b/src/libui_sdl/libui/test/page7.c
new file mode 100644
index 0000000..5cc9114
--- /dev/null
+++ b/src/libui_sdl/libui/test/page7.c
@@ -0,0 +1,25 @@
+// 13 october 2015
+#include "test.h"
+
+uiBox *makePage7(void)
+{
+ uiBox *page7;
+ uiGroup *group;
+ uiBox *box2;
+
+ page7 = newHorizontalBox();
+
+ group = makePage7a();
+ uiBoxAppend(page7, uiControl(group), 1);
+
+ box2 = newVerticalBox();
+ uiBoxAppend(page7, uiControl(box2), 1);
+
+ group = makePage7b();
+ uiBoxAppend(box2, uiControl(group), 1);
+
+ group = makePage7c();
+ uiBoxAppend(box2, uiControl(group), 1);
+
+ return page7;
+}
diff --git a/src/libui_sdl/libui/test/page7a.c b/src/libui_sdl/libui/test/page7a.c
new file mode 100644
index 0000000..72e0321
--- /dev/null
+++ b/src/libui_sdl/libui/test/page7a.c
@@ -0,0 +1,139 @@
+// 13 october 2015
+#include "test.h"
+
+static uiArea *area;
+static uiEntry *startAngle;
+static uiEntry *sweep;
+static uiCheckbox *negative;
+static uiCheckbox *radians;
+
+struct handler {
+ uiAreaHandler ah;
+};
+
+static struct handler handler;
+
+// based on the cairo arc sample
+static void handlerDraw(uiAreaHandler *a, uiArea *area, uiAreaDrawParams *p)
+{
+ double xc = 128.0;
+ double yc = 128.0;
+ double radius = 100.0;
+ uiDrawBrush source;
+ uiDrawStrokeParams sp;
+ uiDrawPath *path;
+ char *startText;
+ char *sweepText;
+ double factor;
+
+ source.Type = uiDrawBrushTypeSolid;
+ source.R = 0;
+ source.G = 0;
+ source.B = 0;
+ source.A = 1;
+ sp.Cap = uiDrawLineCapFlat;
+ sp.Join = uiDrawLineJoinMiter;
+ sp.MiterLimit = uiDrawDefaultMiterLimit;
+ sp.Dashes = NULL;
+ sp.NumDashes = 0;
+ sp.DashPhase = 0;
+
+ startText = uiEntryText(startAngle);
+ sweepText = uiEntryText(sweep);
+
+ factor = uiPi / 180;
+ if (uiCheckboxChecked(radians))
+ factor = 1;
+
+ sp.Thickness = 10.0;
+ path = uiDrawNewPath(uiDrawFillModeWinding);
+ uiDrawPathNewFigure(path, xc, yc);
+ uiDrawPathArcTo(path,
+ xc, yc,
+ radius,
+ atof(startText) * factor,
+ atof(sweepText) * factor,
+ uiCheckboxChecked(negative));
+ uiDrawPathEnd(path);
+ uiDrawStroke(p->Context, path, &source, &sp);
+ uiDrawFreePath(path);
+
+ uiFreeText(startText);
+ uiFreeText(sweepText);
+}
+
+static void handlerMouseEvent(uiAreaHandler *a, uiArea *area, uiAreaMouseEvent *e)
+{
+ // do nothing
+}
+
+static void handlerMouseCrossed(uiAreaHandler *ah, uiArea *a, int left)
+{
+ // do nothing
+}
+
+static void handlerDragBroken(uiAreaHandler *ah, uiArea *a)
+{
+ // do nothing
+}
+
+static int handlerKeyEvent(uiAreaHandler *ah, uiArea *a, uiAreaKeyEvent *e)
+{
+ return 0;
+}
+
+static void entryChanged(uiEntry *e, void *data)
+{
+ uiAreaQueueRedrawAll(area);
+}
+
+static void checkboxToggled(uiCheckbox *c, void *data)
+{
+ uiAreaQueueRedrawAll(area);
+}
+
+uiGroup *makePage7a(void)
+{
+ uiGroup *group;
+ uiBox *box, *box2;
+
+ handler.ah.Draw = handlerDraw;
+ handler.ah.MouseEvent = handlerMouseEvent;
+ handler.ah.MouseCrossed = handlerMouseCrossed;
+ handler.ah.DragBroken = handlerDragBroken;
+ handler.ah.KeyEvent = handlerKeyEvent;
+
+ group = newGroup("Arc Test");
+
+ box = newVerticalBox();
+ uiGroupSetChild(group, uiControl(box));
+
+ area = uiNewArea((uiAreaHandler *) (&handler));
+ uiBoxAppend(box, uiControl(area), 1);
+
+ box2 = newHorizontalBox();
+ uiBoxAppend(box, uiControl(box2), 0);
+
+ uiBoxAppend(box2, uiControl(uiNewLabel("Start Angle")), 0);
+ startAngle = uiNewEntry();
+ uiEntryOnChanged(startAngle, entryChanged, NULL);
+ uiBoxAppend(box2, uiControl(startAngle), 1);
+
+ box2 = newHorizontalBox();
+ uiBoxAppend(box, uiControl(box2), 0);
+
+ uiBoxAppend(box2, uiControl(uiNewLabel("Sweep")), 0);
+ sweep = uiNewEntry();
+ uiEntryOnChanged(sweep, entryChanged, NULL);
+ uiBoxAppend(box2, uiControl(sweep), 1);
+
+ negative = uiNewCheckbox("Negative");
+ uiCheckboxOnToggled(negative, checkboxToggled, NULL);
+ uiBoxAppend(box, uiControl(negative), 0);
+
+ radians = uiNewCheckbox("Radians");
+ uiCheckboxOnToggled(radians, checkboxToggled, NULL);
+ uiBoxAppend(box, uiControl(radians), 0);
+
+ return group;
+}
diff --git a/src/libui_sdl/libui/test/page7b.c b/src/libui_sdl/libui/test/page7b.c
new file mode 100644
index 0000000..d1f98a7
--- /dev/null
+++ b/src/libui_sdl/libui/test/page7b.c
@@ -0,0 +1,71 @@
+// 13 october 2015
+#include "test.h"
+
+static uiArea *area;
+static uiCheckbox *label;
+
+struct handler {
+ uiAreaHandler ah;
+};
+
+static struct handler handler;
+
+static void handlerDraw(uiAreaHandler *a, uiArea *area, uiAreaDrawParams *p)
+{
+ // do nothing
+}
+
+static void handlerMouseEvent(uiAreaHandler *a, uiArea *area, uiAreaMouseEvent *e)
+{
+ char pos[128];
+
+ // wonderful, vanilla snprintf() isn't in visual studio 2013 - http://blogs.msdn.com/b/vcblog/archive/2013/07/19/c99-library-support-in-visual-studio-2013.aspx
+ // we can't use _snprintf() in the test suite because that's msvc-only, so oops. sprintf() it is.
+ sprintf(pos, "X %g Y %g", e->X, e->Y);
+ uiCheckboxSetText(label, pos);
+}
+
+static void handlerMouseCrossed(uiAreaHandler *ah, uiArea *a, int left)
+{
+printf("%d %d\n", left, !left);
+ uiCheckboxSetChecked(label, !left);
+}
+
+static void handlerDragBroken(uiAreaHandler *ah, uiArea *a)
+{
+ // do nothing
+}
+
+static int handlerKeyEvent(uiAreaHandler *ah, uiArea *a, uiAreaKeyEvent *e)
+{
+ if (e->Key == 'h' && !e->Up) {
+ // TODO hide the widget momentarily on the h key
+ return 1;
+ }
+ return 0;
+}
+
+uiGroup *makePage7b(void)
+{
+ uiGroup *group;
+ uiBox *box;
+
+ handler.ah.Draw = handlerDraw;
+ handler.ah.MouseEvent = handlerMouseEvent;
+ handler.ah.MouseCrossed = handlerMouseCrossed;
+ handler.ah.DragBroken = handlerDragBroken;
+ handler.ah.KeyEvent = handlerKeyEvent;
+
+ group = newGroup("Scrolling Mouse Test");
+
+ box = newVerticalBox();
+ uiGroupSetChild(group, uiControl(box));
+
+ area = uiNewScrollingArea((uiAreaHandler *) (&handler), 5000, 5000);
+ uiBoxAppend(box, uiControl(area), 1);
+
+ label = uiNewCheckbox("");
+ uiBoxAppend(box, uiControl(label), 0);
+
+ return group;
+}
diff --git a/src/libui_sdl/libui/test/page7c.c b/src/libui_sdl/libui/test/page7c.c
new file mode 100644
index 0000000..ac6a316
--- /dev/null
+++ b/src/libui_sdl/libui/test/page7c.c
@@ -0,0 +1,133 @@
+// 13 october 2015
+#include "test.h"
+
+static uiArea *area;
+
+struct handler {
+ uiAreaHandler ah;
+};
+
+static struct handler handler;
+
+#define areaSize 250
+#define borderThickness 1
+#define padding 30
+#define circleRadius ((areaSize - padding) / 2)
+
+static void handlerDraw(uiAreaHandler *a, uiArea *area, uiAreaDrawParams *dp)
+{
+ uiDrawPath *path;
+ uiDrawBrush brush;
+ uiDrawStrokeParams sp;
+ uiDrawBrushGradientStop stops[2];
+
+ memset(&brush, 0, sizeof (uiDrawBrush));
+ memset(&sp, 0, sizeof (uiDrawStrokeParams));
+
+ // add some buffering to detect scrolls that aren't on the dot and draws that are outside the scroll area on Windows
+ path = uiDrawNewPath(uiDrawFillModeWinding);
+ uiDrawPathAddRectangle(path,
+ -50, -50,
+ areaSize + 100, areaSize + 100);
+ uiDrawPathEnd(path);
+ brush.Type = uiDrawBrushTypeSolid;
+ brush.R = 0;
+ brush.G = 1;
+ brush.B = 0;
+ brush.A = 1;
+ uiDrawFill(dp->Context, path, &brush);
+ uiDrawFreePath(path);
+
+ path = uiDrawNewPath(uiDrawFillModeWinding);
+ uiDrawPathAddRectangle(path,
+ 0, 0,
+ areaSize, areaSize);
+ uiDrawPathEnd(path);
+ brush.Type = uiDrawBrushTypeSolid;
+ brush.R = 1;
+ brush.G = 1;
+ brush.B = 1;
+ brush.A = 1;
+ uiDrawFill(dp->Context, path, &brush);
+ brush.Type = uiDrawBrushTypeSolid;
+ brush.R = 1;
+ brush.G = 0;
+ brush.B = 0;
+ brush.A = 1;
+ sp.Cap = uiDrawLineCapFlat;
+ sp.Join = uiDrawLineJoinMiter;
+ sp.Thickness = 1;
+ sp.MiterLimit = uiDrawDefaultMiterLimit;
+ uiDrawStroke(dp->Context, path, &brush, &sp);
+ uiDrawFreePath(path);
+
+ path = uiDrawNewPath(uiDrawFillModeWinding);
+ uiDrawPathNewFigureWithArc(path,
+ areaSize / 2, areaSize / 2,
+ circleRadius,
+ 0, 2 * uiPi,
+ 0);
+ uiDrawPathEnd(path);
+ stops[0].Pos =0.0;
+ stops[0].R = 0.0;
+ stops[0].G = 1.0;
+ stops[0].B = 1.0;
+ stops[0].A = 1.0;
+ stops[1].Pos = 1.0;
+ stops[1].R = 0.0;
+ stops[1].G = 0.0;
+ stops[1].B = 1.0;
+ stops[1].A = 1.0;
+ brush.Type = uiDrawBrushTypeLinearGradient;
+ brush.X0 = areaSize / 2;
+ brush.Y0 = padding;
+ brush.X1 = areaSize / 2;
+ brush.Y1 = areaSize - padding;
+ brush.Stops = stops;
+ brush.NumStops = 2;
+ uiDrawFill(dp->Context, path, &brush);
+ uiDrawFreePath(path);
+}
+
+static void handlerMouseEvent(uiAreaHandler *a, uiArea *area, uiAreaMouseEvent *e)
+{
+ // do nothing
+}
+
+static void handlerMouseCrossed(uiAreaHandler *ah, uiArea *a, int left)
+{
+ // do nothing
+}
+
+static void handlerDragBroken(uiAreaHandler *ah, uiArea *a)
+{
+ // do nothing
+}
+
+static int handlerKeyEvent(uiAreaHandler *ah, uiArea *a, uiAreaKeyEvent *e)
+{
+ if (e->Key == 'h' && !e->Up) {
+ // TODO hide the widget momentarily on the h key
+ return 1;
+ }
+ return 0;
+}
+
+uiGroup *makePage7c(void)
+{
+ uiGroup *group;
+
+ handler.ah.Draw = handlerDraw;
+ handler.ah.MouseEvent = handlerMouseEvent;
+ handler.ah.MouseCrossed = handlerMouseCrossed;
+ handler.ah.DragBroken = handlerDragBroken;
+ handler.ah.KeyEvent = handlerKeyEvent;
+
+ group = newGroup("Scrolling Drawing Test");
+
+ area = uiNewScrollingArea((uiAreaHandler *) (&handler),
+ areaSize, areaSize);
+ uiGroupSetChild(group, uiControl(area));
+
+ return group;
+}
diff --git a/src/libui_sdl/libui/test/page8.c b/src/libui_sdl/libui/test/page8.c
new file mode 100644
index 0000000..7d85556
--- /dev/null
+++ b/src/libui_sdl/libui/test/page8.c
@@ -0,0 +1,46 @@
+// 22 december 2015
+#include "test.h"
+
+static void onListFonts(uiButton *b, void *data)
+{
+ uiDrawFontFamilies *ff;
+ char *this;
+ int i, n;
+
+ uiMultilineEntrySetText(uiMultilineEntry(data), "");
+ ff = uiDrawListFontFamilies();
+ n = uiDrawFontFamiliesNumFamilies(ff);
+ for (i = 0; i < n; i++) {
+ this = uiDrawFontFamiliesFamily(ff, i);
+ uiMultilineEntryAppend(uiMultilineEntry(data), this);
+ uiMultilineEntryAppend(uiMultilineEntry(data), "\n");
+ uiFreeText(this);
+ }
+ uiDrawFreeFontFamilies(ff);
+}
+
+uiBox *makePage8(void)
+{
+ uiBox *page8;
+ uiGroup *group;
+ uiBox *vbox;
+ uiMultilineEntry *me;
+ uiButton *button;
+
+ page8 = newHorizontalBox();
+
+ group = newGroup("Font Families");
+ uiBoxAppend(page8, uiControl(group), 1);
+
+ vbox = newVerticalBox();
+ uiGroupSetChild(group, uiControl(vbox));
+
+ me = uiNewMultilineEntry();
+ uiBoxAppend(vbox, uiControl(me), 1);
+
+ button = uiNewButton("List Font Families");
+ uiButtonOnClicked(button, onListFonts, me);
+ uiBoxAppend(vbox, uiControl(button), 0);
+
+ return page8;
+}
diff --git a/src/libui_sdl/libui/test/page9.c b/src/libui_sdl/libui/test/page9.c
new file mode 100644
index 0000000..65b2d3a
--- /dev/null
+++ b/src/libui_sdl/libui/test/page9.c
@@ -0,0 +1,289 @@
+// 22 december 2015
+#include "test.h"
+
+static uiEntry *textString;
+static uiEntry *textFont;
+static uiEntry *textSize;
+static uiCombobox *textWeight;
+static uiCombobox *textItalic;
+static uiCheckbox *textSmallCaps;
+static uiCombobox *textStretch;
+static uiEntry *textWidth;
+static uiButton *textApply;
+static uiCheckbox *addLeading;
+static uiArea *textArea;
+static uiAreaHandler textAreaHandler;
+
+static double entryDouble(uiEntry *e)
+{
+ char *s;
+ double d;
+
+ s = uiEntryText(e);
+ d = atof(s);
+ uiFreeText(s);
+ return d;
+}
+
+static void drawGuides(uiDrawContext *c, uiDrawTextFontMetrics *m)
+{
+ uiDrawPath *p;
+ uiDrawBrush b;
+ uiDrawStrokeParams sp;
+ double leading;
+ double y;
+
+ leading = 0;
+ if (uiCheckboxChecked(addLeading))
+ leading = m->Leading;
+
+ memset(&b, 0, sizeof (uiDrawBrush));
+ b.Type = uiDrawBrushTypeSolid;
+ memset(&sp, 0, sizeof (uiDrawStrokeParams));
+ sp.Cap = uiDrawLineCapFlat;
+ sp.Join = uiDrawLineJoinMiter;
+ sp.MiterLimit = uiDrawDefaultMiterLimit;
+ sp.Thickness = 2;
+
+ uiDrawSave(c);
+
+ p = uiDrawNewPath(uiDrawFillModeWinding);
+ y = 10;
+ uiDrawPathNewFigure(p, 8, y);
+ y += m->Ascent;
+ uiDrawPathLineTo(p, 8, y);
+ uiDrawPathEnd(p);
+ b.R = 0.94;
+ b.G = 0.5;
+ b.B = 0.5;
+ b.A = 1.0;
+ uiDrawStroke(c, p, &b, &sp);
+ uiDrawFreePath(p);
+
+ p = uiDrawNewPath(uiDrawFillModeWinding);
+ uiDrawPathNewFigure(p, 8, y);
+ y += m->Descent;
+ uiDrawPathLineTo(p, 8, y);
+ uiDrawPathEnd(p);
+ b.R = 0.12;
+ b.G = 0.56;
+ b.B = 1.0;
+ b.A = 1.0;
+ uiDrawStroke(c, p, &b, &sp);
+ uiDrawFreePath(p);
+
+ // and again for the second line
+ p = uiDrawNewPath(uiDrawFillModeWinding);
+ y += leading;
+ uiDrawPathNewFigure(p, 8, y);
+ y += m->Ascent;
+ uiDrawPathLineTo(p, 8, y);
+ uiDrawPathEnd(p);
+ b.R = 0.94;
+ b.G = 0.5;
+ b.B = 0.5;
+ b.A = 0.75;
+ uiDrawStroke(c, p, &b, &sp);
+ uiDrawFreePath(p);
+
+ p = uiDrawNewPath(uiDrawFillModeWinding);
+ uiDrawPathNewFigure(p, 8, y);
+ y += m->Descent;
+ uiDrawPathLineTo(p, 8, y);
+ uiDrawPathEnd(p);
+ b.R = 0.12;
+ b.G = 0.56;
+ b.B = 1.0;
+ b.A = 0.75;
+ uiDrawStroke(c, p, &b, &sp);
+ uiDrawFreePath(p);
+
+ // and a box to text layout top-left corners
+ p = uiDrawNewPath(uiDrawFillModeWinding);
+ uiDrawPathAddRectangle(p, 0, 0, 10, 10);
+ uiDrawPathEnd(p);
+ uiDrawClip(c, p);
+ b.R = 0.85;
+ b.G = 0.65;
+ b.B = 0.13;
+ b.A = 1.0;
+ uiDrawStroke(c, p, &b, &sp);
+ uiDrawFreePath(p);
+
+ uiDrawRestore(c);
+}
+
+static void handlerDraw(uiAreaHandler *a, uiArea *area, uiAreaDrawParams *dp)
+{
+ uiDrawTextFontDescriptor desc;
+ uiDrawTextFont *font;
+ char *s;
+ char *family; // make compiler happy
+ uiDrawTextLayout *layout;
+ uiDrawTextFontMetrics metrics;
+ double ypos;
+ double width;
+ double height;
+
+ memset(&desc, 0, sizeof (uiDrawTextFontDescriptor));
+ family = uiEntryText(textFont);
+ desc.Family = family;
+ desc.Size = entryDouble(textSize);
+ desc.Weight = uiComboboxSelected(textWeight);
+ desc.Italic = uiComboboxSelected(textItalic);
+ desc.Stretch = uiComboboxSelected(textStretch);
+ font = uiDrawLoadClosestFont(&desc);
+ uiFreeText(family);
+ uiDrawTextFontGetMetrics(font, &metrics);
+
+ width = entryDouble(textWidth);
+
+ drawGuides(dp->Context, &metrics);
+
+ s = uiEntryText(textString);
+ layout = uiDrawNewTextLayout(s, font, width);
+ uiFreeText(s);
+ if (uiCheckboxChecked(textSmallCaps))
+ ; // TODO
+ ypos = 10;
+ uiDrawText(dp->Context, 10, ypos, layout);
+ // TODO make these optional?
+ uiDrawTextLayoutExtents(layout, &width, &height);
+ uiDrawFreeTextLayout(layout);
+
+ layout = uiDrawNewTextLayout("This is a second line", font, -1);
+ if (/*TODO reuse width*/entryDouble(textWidth) < 0) {
+ double ad;
+
+ ad = metrics.Ascent + metrics.Descent;
+ printf("ad:%g extent:%g\n", ad, height);
+ }
+ ypos += height;
+ if (uiCheckboxChecked(addLeading))
+ ypos += metrics.Leading;
+ uiDrawText(dp->Context, 10, ypos, layout);
+ uiDrawFreeTextLayout(layout);
+
+ uiDrawFreeTextFont(font);
+}
+
+static void handlerMouseEvent(uiAreaHandler *a, uiArea *area, uiAreaMouseEvent *e)
+{
+ // do nothing
+}
+
+static void handlerMouseCrossed(uiAreaHandler *ah, uiArea *a, int left)
+{
+ // do nothing
+}
+
+static void handlerDragBroken(uiAreaHandler *ah, uiArea *a)
+{
+ // do nothing
+}
+
+static int handlerKeyEvent(uiAreaHandler *ah, uiArea *a, uiAreaKeyEvent *e)
+{
+ // do nothing
+ return 0;
+}
+
+static void onTextApply(uiButton *b, void *data)
+{
+ uiAreaQueueRedrawAll(textArea);
+}
+
+uiBox *makePage9(void)
+{
+ uiBox *page9;
+ uiBox *vbox;
+ uiBox *hbox;
+
+ page9 = newVerticalBox();
+ vbox = page9;
+
+ hbox = newHorizontalBox();
+ uiBoxAppend(vbox, uiControl(hbox), 0);
+
+ textString = uiNewEntry();
+ // TODO make it placeholder
+ uiEntrySetText(textString, "Enter text here");
+ uiBoxAppend(hbox, uiControl(textString), 1);
+
+ textFont = uiNewEntry();
+ uiEntrySetText(textFont, "Arial");
+ uiBoxAppend(hbox, uiControl(textFont), 1);
+
+ textSize = uiNewEntry();
+ uiEntrySetText(textSize, "10");
+ uiBoxAppend(hbox, uiControl(textSize), 1);
+
+ hbox = newHorizontalBox();
+ uiBoxAppend(vbox, uiControl(hbox), 0);
+
+ textWeight = uiNewCombobox();
+ uiComboboxAppend(textWeight, "Thin");
+ uiComboboxAppend(textWeight, "Ultra Light");
+ uiComboboxAppend(textWeight, "Light");
+ uiComboboxAppend(textWeight, "Book");
+ uiComboboxAppend(textWeight, "Normal");
+ uiComboboxAppend(textWeight, "Medium");
+ uiComboboxAppend(textWeight, "Semi Bold");
+ uiComboboxAppend(textWeight, "Bold");
+ uiComboboxAppend(textWeight, "Ultra Bold");
+ uiComboboxAppend(textWeight, "Heavy");
+ uiComboboxAppend(textWeight, "Ultra Heavy");
+ uiComboboxSetSelected(textWeight, uiDrawTextWeightNormal);
+ uiBoxAppend(hbox, uiControl(textWeight), 1);
+
+ textItalic = uiNewCombobox();
+ uiComboboxAppend(textItalic, "Normal");
+ uiComboboxAppend(textItalic, "Oblique");
+ uiComboboxAppend(textItalic, "Italic");
+ uiComboboxSetSelected(textItalic, uiDrawTextItalicNormal);
+ uiBoxAppend(hbox, uiControl(textItalic), 1);
+
+ textSmallCaps = uiNewCheckbox("Small Caps");
+ uiBoxAppend(hbox, uiControl(textSmallCaps), 1);
+
+ hbox = newHorizontalBox();
+ uiBoxAppend(vbox, uiControl(hbox), 0);
+
+ textStretch = uiNewCombobox();
+ uiComboboxAppend(textStretch, "Ultra Condensed");
+ uiComboboxAppend(textStretch, "Extra Condensed");
+ uiComboboxAppend(textStretch, "Condensed");
+ uiComboboxAppend(textStretch, "Semi Condensed");
+ uiComboboxAppend(textStretch, "Normal");
+ uiComboboxAppend(textStretch, "Semi Expanded");
+ uiComboboxAppend(textStretch, "Expanded");
+ uiComboboxAppend(textStretch, "Extra Expanded");
+ uiComboboxAppend(textStretch, "Ultra Expanded");
+ uiComboboxSetSelected(textStretch, uiDrawTextStretchNormal);
+ uiBoxAppend(hbox, uiControl(textStretch), 1);
+
+ textWidth = uiNewEntry();
+ uiEntrySetText(textWidth, "-1");
+ uiBoxAppend(hbox, uiControl(textWidth), 1);
+
+ hbox = newHorizontalBox();
+ uiBoxAppend(vbox, uiControl(hbox), 0);
+
+ textApply = uiNewButton("Apply");
+ uiButtonOnClicked(textApply, onTextApply, NULL);
+ uiBoxAppend(hbox, uiControl(textApply), 1);
+
+ addLeading = uiNewCheckbox("Add Leading");
+ uiCheckboxSetChecked(addLeading, 1);
+ uiBoxAppend(hbox, uiControl(addLeading), 0);
+
+ textAreaHandler.Draw = handlerDraw;
+ textAreaHandler.MouseEvent = handlerMouseEvent;
+ textAreaHandler.MouseCrossed = handlerMouseCrossed;
+ textAreaHandler.DragBroken = handlerDragBroken;
+ textAreaHandler.KeyEvent = handlerKeyEvent;
+ textArea = uiNewArea(&textAreaHandler);
+ uiBoxAppend(vbox, uiControl(textArea), 1);
+
+ return page9;
+}
diff --git a/src/libui_sdl/libui/test/resources.rc b/src/libui_sdl/libui/test/resources.rc
new file mode 100644
index 0000000..ebc5d6e
--- /dev/null
+++ b/src/libui_sdl/libui/test/resources.rc
@@ -0,0 +1,13 @@
+// 30 may 2015
+
+// this is a UTF-8 file
+#pragma code_page(65001)
+
+// this is the Common Controls 6 manifest
+// TODO set up the string values here
+// 1 is the value of CREATEPROCESS_MANIFEST_RESOURCE_ID and 24 is the value of RT_MANIFEST; we use it directly to avoid needing to share winapi.h with the tests and examples
+#ifndef _UI_STATIC
+1 24 "test.manifest"
+#else
+1 24 "test.static.manifest"
+#endif
diff --git a/src/libui_sdl/libui/test/spaced.c b/src/libui_sdl/libui/test/spaced.c
new file mode 100644
index 0000000..02db99a
--- /dev/null
+++ b/src/libui_sdl/libui/test/spaced.c
@@ -0,0 +1,177 @@
+// 22 april 2015
+#include "test.h"
+
+struct thing {
+ void *ptr;
+ int type;
+};
+
+static struct thing *things = NULL;
+static size_t len = 0;
+static size_t cap = 0;
+
+#define grow 32
+
+static void *append(void *thing, int type)
+{
+ if (len >= cap) {
+ cap += grow;
+ things = (struct thing *) realloc(things, cap * sizeof (struct thing));
+ if (things == NULL)
+ die("reallocating things array in test/spaced.c append()");
+ }
+ things[len].ptr = thing;
+ things[len].type = type;
+ len++;
+ return things[len - 1].ptr;
+}
+
+enum types {
+ window,
+ box,
+ tab,
+ group,
+ form,
+ grid,
+};
+
+void setSpaced(int spaced)
+{
+ size_t i;
+ void *p;
+ size_t j, n;
+
+ for (i = 0; i < len; i++) {
+ p = things[i].ptr;
+ switch (things[i].type) {
+ case window:
+ uiWindowSetMargined(uiWindow(p), spaced);
+ break;
+ case box:
+ uiBoxSetPadded(uiBox(p), spaced);
+ break;
+ case tab:
+ n = uiTabNumPages(uiTab(p));
+ for (j = 0; j < n; j++)
+ uiTabSetMargined(uiTab(p), j, spaced);
+ break;
+ case group:
+ uiGroupSetMargined(uiGroup(p), spaced);
+ break;
+ case form:
+ uiFormSetPadded(uiForm(p), spaced);
+ break;
+ case grid:
+ uiGridSetPadded(uiGrid(p), spaced);
+ break;
+ }
+ }
+}
+
+void querySpaced(char out[12]) // more than enough
+{
+ int m = 0;
+ int p = 0;
+ size_t i;
+ void *pp;
+ size_t j, n;
+
+ for (i = 0; i < len; i++) {
+ pp = things[i].ptr;
+ switch (things[i].type) {
+ case window:
+ if (uiWindowMargined(uiWindow(pp)))
+ m++;
+ break;
+ case box:
+ p = uiBoxPadded(uiBox(pp));
+ break;
+ case tab:
+ n = uiTabNumPages(uiTab(pp));
+ for (j = 0; j < n; j++)
+ if (uiTabMargined(uiTab(pp), j))
+ m++;
+ break;
+ case group:
+ if (uiGroupMargined(uiGroup(pp)))
+ m++;
+ break;
+ // TODO form
+ // TODO grid
+ }
+ }
+
+ out[0] = 'm';
+ out[1] = ' ';
+ out[2] = '0' + m;
+ out[3] = ' ';
+ out[4] = 'p';
+ out[5] = ' ';
+ out[6] = '0';
+ if (p)
+ out[6] = '1';
+ out[7] = '\0';
+}
+
+uiWindow *newWindow(const char *title, int width, int height, int hasMenubar)
+{
+ uiWindow *w;
+
+ w = uiNewWindow(title, width, height, hasMenubar);
+ append(w, window);
+ return w;
+}
+
+uiBox *newHorizontalBox(void)
+{
+ uiBox *b;
+
+ b = (*newhbox)();
+ append(b, box);
+ return b;
+}
+
+uiBox *newVerticalBox(void)
+{
+ uiBox *b;
+
+ b = (*newvbox)();
+ append(b, box);
+ return b;
+}
+
+uiTab *newTab(void)
+{
+ uiTab *t;
+
+ t = uiNewTab();
+ append(t, tab);
+ return t;
+}
+
+uiGroup *newGroup(const char *text)
+{
+ uiGroup *g;
+
+ g = uiNewGroup(text);
+ append(g, group);
+ return g;
+}
+
+uiForm *newForm(void)
+{
+ uiForm *f;
+
+ f = uiNewForm();
+ append(f, form);
+ return f;
+}
+
+uiGrid *newGrid(void)
+{
+ uiGrid *g;
+
+ g = uiNewGrid();
+ append(g, grid);
+ return g;
+}
diff --git a/src/libui_sdl/libui/test/test.h b/src/libui_sdl/libui/test/test.h
new file mode 100644
index 0000000..66b1baa
--- /dev/null
+++ b/src/libui_sdl/libui/test/test.h
@@ -0,0 +1,91 @@
+// 22 april 2015
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <string.h>
+#include <math.h>
+#include <limits.h>
+#include "../ui.h"
+
+// main.c
+extern void die(const char *, ...);
+extern uiBox *mainBox;
+extern uiTab *mainTab;
+extern uiBox *(*newhbox)(void);
+extern uiBox *(*newvbox)(void);
+
+// spaced.c
+extern void setSpaced(int);
+extern void querySpaced(char[12]);
+extern uiWindow *newWindow(const char *title, int width, int height, int hasMenubar);
+extern uiBox *newHorizontalBox(void);
+extern uiBox *newVerticalBox(void);
+extern uiTab *newTab(void);
+extern uiGroup *newGroup(const char *);
+extern uiForm *newForm(void);
+extern uiGrid *newGrid(void);
+
+// menus.c
+extern uiMenuItem *shouldQuitItem;
+extern void initMenus(void);
+
+// page1.c
+extern uiBox *page1;
+extern void makePage1(uiWindow *);
+
+// page2.c
+extern uiGroup *page2group;
+extern uiBox *makePage2(void);
+
+// page3.c
+extern uiBox *makePage3(void);
+
+// page4.c
+extern uiBox *makePage4(void);
+
+// page5.c
+extern uiBox *makePage5(uiWindow *);
+
+// page6.c
+extern uiBox *makePage6(void);
+
+// drawtests.c
+extern void runDrawTest(int, uiAreaDrawParams *);
+extern void populateComboboxWithTests(uiCombobox *);
+
+// page7.c
+extern uiBox *makePage7(void);
+
+// page7a.c
+extern uiGroup *makePage7a(void);
+
+// page7b.c
+extern uiGroup *makePage7b(void);
+
+// page7c.c
+extern uiGroup *makePage7c(void);
+
+// page8.c
+extern uiBox *makePage8(void);
+
+// page9.c
+extern uiBox *makePage9(void);
+
+// page10.c
+extern uiBox *makePage10(void);
+
+// page11.c
+extern uiBox *makePage11(void);
+
+// page12.c
+extern uiBox *makePage12(void);
+
+// page13.c
+extern uiBox *makePage13(void);
+
+// page14.c
+extern uiTab *makePage14(void);
+
+// page15.c
+extern uiBox *makePage15(uiWindow *);
diff --git a/src/libui_sdl/libui/test/test.manifest b/src/libui_sdl/libui/test/test.manifest
new file mode 100644
index 0000000..41e7c9c
--- /dev/null
+++ b/src/libui_sdl/libui/test/test.manifest
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+<assemblyIdentity
+ version="1.0.0.0"
+ processorArchitecture="*"
+ name="CompanyName.ProductName.YourApplication"
+ type="win32"
+/>
+<description>Your application description here.</description>
+<!-- do NOT include the comctl6 dependency here; this lets us find bugs related to theming -->
+<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
+ <application>
+ <!--The ID below indicates application support for Windows Vista -->
+ <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
+ <!--The ID below indicates application support for Windows 7 -->
+ <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
+ </application>
+</compatibility>
+</assembly>
+
diff --git a/src/libui_sdl/libui/test/test.static.manifest b/src/libui_sdl/libui/test/test.static.manifest
new file mode 100644
index 0000000..d8e83a8
--- /dev/null
+++ b/src/libui_sdl/libui/test/test.static.manifest
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+<assemblyIdentity
+ version="1.0.0.0"
+ processorArchitecture="*"
+ name="CompanyName.ProductName.YourApplication"
+ type="win32"
+/>
+<description>Your application description here.</description>
+<!-- we DO need comctl6 in the static case -->
+<dependency>
+ <dependentAssembly>
+ <assemblyIdentity
+ type="win32"
+ name="Microsoft.Windows.Common-Controls"
+ version="6.0.0.0"
+ processorArchitecture="*"
+ publicKeyToken="6595b64144ccf1df"
+ language="*"
+ />
+ </dependentAssembly>
+</dependency>
+<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
+ <application>
+ <!--The ID below indicates application support for Windows Vista -->
+ <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
+ <!--The ID below indicates application support for Windows 7 -->
+ <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
+ </application>
+</compatibility>
+</assembly>
+