diff --git a/docs/media/UiArea.png b/docs/media/UiArea.png index 880af97..653e002 100644 Binary files a/docs/media/UiArea.png and b/docs/media/UiArea.png differ diff --git a/examples/area-adv.js b/examples/area-adv.js index ae5f7fe..de4c848 100644 --- a/examples/area-adv.js +++ b/examples/area-adv.js @@ -2,9 +2,19 @@ /* eslint-disable unicorn/number-literal-case */ const libui = require('..'); -const solidBrush = new libui.DrawBrush(); -solidBrush.type = libui.brushType.solid; -solidBrush.color = new libui.Color(1, 0, 0, 1); +const RESIZE_HANDLE_WIDTH = 8; + +const redBrush = new libui.DrawBrush(); +redBrush.type = libui.brushType.solid; +redBrush.color = new libui.Color(1, 0, 0, 1); + +const greyBrush = new libui.DrawBrush(); +greyBrush.type = libui.brushType.solid; +greyBrush.color = new libui.Color(0.6, 0.6, 0.6, 1); + +const blueBrush = new libui.DrawBrush(); +blueBrush.type = libui.brushType.solid; +blueBrush.color = new libui.Color(0, 0, 1, 1); const dashedStroke = new libui.DrawStrokeParams(); dashedStroke.thickness = 6; @@ -13,14 +23,14 @@ console.log(dashedStroke.dashes); const linearBrush = new libui.DrawBrush(); linearBrush.type = libui.brushType.linearGradient; -linearBrush.start = new libui.Point(0, 0); +linearBrush.start = new libui.Point(50, 50); linearBrush.end = new libui.Point(200, 200); linearBrush.setStops([new libui.BrushGradientStop(0, new libui.Color(1, 0, 0, 1)), new libui.BrushGradientStop(1, new libui.Color(0, 1, 0, 1))]); const radialBrush = new libui.DrawBrush(); radialBrush.type = libui.brushType.radialGradient; -radialBrush.start = new libui.Point(250, 300); -radialBrush.end = new libui.Point(250, 300); +radialBrush.start = new libui.Point(300, 330); +radialBrush.end = new libui.Point(300, 330); radialBrush.outerRadius = 40; radialBrush.setStops([new libui.BrushGradientStop(0, new libui.Color(0, 0, 1, 1)), new libui.BrushGradientStop(1, new libui.Color(0.5, 0.5, 1, 1))]); console.log(radialBrush.getStops()); @@ -29,48 +39,114 @@ const matrix = new libui.UiDrawMatrix(); matrix.setIdentity(); matrix.rotate(70, 280, (Math.PI / 180) * 45) +const onCloseHandle = (x, y, p) => (3 <= x && x <= 19 && 2 <= y && y <= 18); +const onMoveHandle = (x, y, p) => (0 <= x && x <= p.getAreaWidth() && 0 <= y && y <= 20); +const onResizeBottomHandle = (x, y, p) => ((p.getAreaHeight() - RESIZE_HANDLE_WIDTH) <= y && y <= p.getAreaHeight()); +const onResizeRightHandle = (x, y, p) => (p.getAreaWidth() - RESIZE_HANDLE_WIDTH <= x && x <= p.getAreaWidth() && 20 < y); +const onResizeLeftHandle = (x, y, p) => (0 <= x && x <= RESIZE_HANDLE_WIDTH && 20 < y); + function handlerDraw(area, p) { let path = new libui.UiDrawPath(libui.fillMode.winding); - path.addRectangle(0, 0, 200, 200); + path.addRectangle(50, 50, 200, 200); path.end(); p.getContext().fill(path, linearBrush); path.freePath(); // ------ + // Circle path = new libui.UiDrawPath(libui.fillMode.winding); - path.newFigure(0, 0); - path.arcTo(250, 300, 50, 0, 2 * Math.PI, false); + path.newFigureWithArc(300, 330, 50, 0, 2 * Math.PI, false); path.end(); p.getContext().fill(path, radialBrush); path.freePath(); + // Dashed line + path = new libui.UiDrawPath(libui.fillMode.winding); + path.newFigure(300, 50); + path.lineTo(350, 250); + path.end(); + p.getContext().stroke(path, redBrush, dashedStroke); + path.freePath(); + + // Move handle path = new libui.UiDrawPath(libui.fillMode.winding); - path.newFigure(250, 20); - path.lineTo(300, 150); + path.addRectangle(0, 0, p.getAreaWidth(), 20); path.end(); - p.getContext().stroke(path, solidBrush, dashedStroke); + p.getContext().fill(path, greyBrush); path.freePath(); + // Close button + path = new libui.UiDrawPath(libui.fillMode.winding); + path.addRectangle(3, 2, 16, 16); + path.end(); + p.getContext().fill(path, redBrush); + path.freePath(); + + p.getContext().save(); + // Rotated square path = new libui.UiDrawPath(libui.fillMode.winding); p.getContext().transform(matrix); - path.addRectangle(20, 230, 100, 100); + path.addRectangle(90, 240, 100, 100); path.end(); - p.getContext().fill(path, solidBrush); + p.getContext().fill(path, redBrush); path.freePath(); + p.getContext().restore(); + + // Resize handle + path = new libui.UiDrawPath(libui.fillMode.winding); + // bottom + path.addRectangle(0, p.getAreaHeight() - RESIZE_HANDLE_WIDTH, p.getAreaWidth(), RESIZE_HANDLE_WIDTH); + // right + path.addRectangle(p.getAreaWidth() - RESIZE_HANDLE_WIDTH, 20, RESIZE_HANDLE_WIDTH, p.getAreaHeight()); + // left + path.addRectangle(0, 20, RESIZE_HANDLE_WIDTH, p.getAreaHeight()); + path.end(); + p.getContext().fill(path, blueBrush); + path.freePath(); +} + +function mouseEvent(area, evt) { + const x = evt.getX(), y = evt.getY(); + + if (evt.getDown() === 1) { + if (onCloseHandle(x, y, evt)) { + mainwin.close(); + libui.stopLoop(); + } else if (onMoveHandle(x, y, evt)) { + area.beginWindowMove(); + } else { + const left = onResizeLeftHandle(x, y, evt); + const right = onResizeRightHandle(x, y, evt); + const bottom = onResizeBottomHandle(x, y, evt); + if (bottom && right) { + area.beginWindowResize(libui.resizeEdge.bottomRight); + } else if (bottom && left) { + area.beginWindowResize(libui.resizeEdge.bottomLeft); + } else if (right) { + area.beginWindowResize(libui.resizeEdge.right); + } else if (left) { + area.beginWindowResize(libui.resizeEdge.left); + } else if (bottom) { + area.beginWindowResize(libui.resizeEdge.bottom); + } + } + } } function noop() {} +let mainwin; + function main() { - const mainwin = new libui.UiWindow('libui textDrawArea Example', 400, 400, 1); - mainwin.margined = true; + mainwin = new libui.UiWindow('libui textDrawArea Example', 400, 430, 1); + mainwin.borderless = true; mainwin.onClosing(() => { mainwin.close(); libui.stopLoop(); }); - const textDrawArea = new libui.UiArea(handlerDraw, noop, noop, noop, noop); + const textDrawArea = new libui.UiArea(handlerDraw, mouseEvent, noop, noop, noop); const wrapper = new libui.UiVerticalBox(); wrapper.append(textDrawArea, true); mainwin.setChild(wrapper); diff --git a/index.js b/index.js index 12b140d..0604907 100644 --- a/index.js +++ b/index.js @@ -417,6 +417,17 @@ const extKeys = { nDivide: 39 }; +const resizeEdge = { + left: 0, + top: 1, + right: 2, + bottom: 3, + topLeft: 4, + topRight: 5, + bottomLeft: 6, + bottomRight: 7 +}; + module.exports.textStretch = textStretch; module.exports.textItalic = textItalic; module.exports.textWeight = textWeight; @@ -439,6 +450,7 @@ module.exports.lineJoin = lineJoin; module.exports.fillMode = fillMode; module.exports.modifierKeys = modifierKeys; module.exports.extKeys = extKeys; +module.exports.resizeEdge = resizeEdge; module.exports.startLoop = startLoop; module.exports.stopLoop = stopLoop; module.exports.onShouldQuit = binding.lib.Ui.onShouldQuit; diff --git a/src/UiArea/UiArea.cc b/src/UiArea/UiArea.cc index ab62f09..c6f867d 100644 --- a/src/UiArea/UiArea.cc +++ b/src/UiArea/UiArea.cc @@ -2,18 +2,6 @@ #include "control.h" #include "ui.h" -void UiArea::setSize(int width, int height) { - uiAreaSetSize((uiArea *)getHandle(), width, height); -} - -void UiArea::queueRedrawAll() { - uiAreaQueueRedrawAll((uiArea *)getHandle()); -} - -void UiArea::scrollTo(double x, double y, double width, double height) { - uiAreaScrollTo((uiArea *)getHandle(), x, y, width, height); -} - UiArea::UiArea(nbind::cbFunction &drawCb, nbind::cbFunction &mouseEventCb, nbind::cbFunction &mouseCrossedCb, nbind::cbFunction &dragBrokenCb, nbind::cbFunction &keyEventCb) @@ -31,6 +19,26 @@ UiArea::UiArea(nbind::cbFunction &drawCb, nbind::cbFunction &mouseEventCb, drawCb, mouseEventCb, mouseCrossedCb, dragBrokenCb, keyEventCb), width, height)) {} +void UiArea::setSize(int width, int height) { + uiAreaSetSize((uiArea *)getHandle(), width, height); +} + +void UiArea::queueRedrawAll() { + uiAreaQueueRedrawAll((uiArea *)getHandle()); +} + +void UiArea::scrollTo(double x, double y, double width, double height) { + uiAreaScrollTo((uiArea *)getHandle(), x, y, width, height); +} + +void UiArea::beginWindowMove() { + uiAreaBeginUserWindowMove((uiArea *)getHandle()); +} + +void UiArea::beginWindowResize(int resizeEdge) { + uiAreaBeginUserWindowResize((uiArea *)getHandle(), resizeEdge); +} + #include "nbind/api.h" NBIND_CLASS(UiArea) { @@ -42,4 +50,6 @@ NBIND_CLASS(UiArea) { method(setSize); method(queueRedrawAll); method(scrollTo); + method(beginWindowMove); + method(beginWindowResize); } diff --git a/src/UiArea/UiAreaDrawParams.cc b/src/UiArea/UiAreaDrawParams.cc index 490d535..5cf602b 100644 --- a/src/UiArea/UiAreaDrawParams.cc +++ b/src/UiArea/UiAreaDrawParams.cc @@ -9,9 +9,6 @@ UiDrawContext *UiAreaDrawParams::getContext() { return new UiDrawContext(p->Context); } -// TODO: make readony properties -// - double UiAreaDrawParams::getAreaWidth() { return p->AreaWidth; } @@ -38,6 +35,13 @@ double UiAreaDrawParams::getClipHeight() { NBIND_CLASS(UiAreaDrawParams) { construct(); + getter(getContext); + getter(getAreaWidth); + getter(getAreaHeight); + getter(getClipX); + getter(getClipY); + getter(getClipWidth); + getter(getClipHeight); method(getContext); method(getAreaWidth); method(getAreaHeight); diff --git a/src/UiArea/UiAreaHandler.cc b/src/UiArea/UiAreaHandler.cc index 2287601..d3d745b 100644 --- a/src/UiArea/UiAreaHandler.cc +++ b/src/UiArea/UiAreaHandler.cc @@ -3,25 +3,26 @@ void Draw(UiAreaHandler *self, uiArea *area, uiAreaDrawParams *params) { UiAreaDrawParams *pp = new UiAreaDrawParams(params); - (*self->draw)(controlsMap[uiControl(area)], pp); + (*self->draw)((UiArea *)controlsMap[uiControl(area)], pp); } void MouseEvent(UiAreaHandler *self, uiArea *area, uiAreaMouseEvent *event) { UiAreaMouseEvent *ev = new UiAreaMouseEvent(event); - (*(self->mouseEvent))(controlsMap[uiControl(area)], ev); + (*(self->mouseEvent))((UiArea *)controlsMap[uiControl(area)], ev); } void MouseCrossed(UiAreaHandler *self, uiArea *area, int left) { - (*(self->mouseCrossed))(controlsMap[uiControl(area)], left); + (*(self->mouseCrossed))((UiArea *)controlsMap[uiControl(area)], left); } void DragBroken(UiAreaHandler *self, uiArea *area) { - (*(self->dragBroken))(controlsMap[uiControl(area)]); + (*(self->dragBroken))((UiArea *)controlsMap[uiControl(area)]); } int KeyEvent(UiAreaHandler *self, uiArea *area, uiAreaKeyEvent *event) { UiAreaKeyEvent *ev = new UiAreaKeyEvent(event); - return (self->keyEvent)->call(controlsMap[uiControl(area)], ev); + return (self->keyEvent) + ->call((UiArea *)controlsMap[uiControl(area)], ev); } UiAreaHandler *UiAreaHandlerFactory::build(nbind::cbFunction &drawCb, diff --git a/src/includes/area.h b/src/includes/area.h index b3da3b5..fb789cd 100644 --- a/src/includes/area.h +++ b/src/includes/area.h @@ -20,6 +20,8 @@ class UiArea : public UiControl { void setSize(int width, int height); void queueRedrawAll(); void scrollTo(double x, double y, double width, double height); + void beginWindowMove(); + void beginWindowResize(int resizeEdge); }; class DrawStrokeParams {