├── .gitmodules ├── autogypi.json ├── docs ├── media │ ├── UiTab.png │ ├── UiArea.png │ ├── UiEntry.png │ ├── UiForm.png │ ├── UiGrid.png │ ├── UiGroup.png │ ├── UiLabel.png │ ├── UiButton.png │ ├── UiCheckbox.png │ ├── UiCombobox.png │ ├── UiSlider.png │ ├── UiSpinbox.png │ ├── Pick_a_Color.png │ ├── UiDatePicker.png │ ├── UiFontButton.png │ ├── UiTimePicker.png │ ├── Window-Linux.png │ ├── Window-macOS.png │ ├── UiColorButton.png │ ├── UiHorizontalBox.png │ ├── UiProgressBar.png │ ├── UiRadioButtons.png │ ├── UiVerticalBox.png │ ├── Window-Windows.png │ ├── UiDateTimePicker.png │ ├── UiMultilineEntry.png │ ├── UiEditableCombobox.png │ ├── UiVerticalSeparator.png │ └── UiHorizontalSeparator.png ├── events.md ├── properties.md ├── initialization.md ├── containers.md ├── fontbutton.md ├── colorbutton.md ├── datepicker.md ├── timepicker.md ├── datetimepicker.md ├── verticalseparator.md ├── horizontalseparator.md ├── label.md ├── grid.md ├── progressbar.md ├── button.md ├── slider.md ├── spinbox.md ├── combobox.md ├── radiobuttons.md ├── verticalbox.md ├── editablecombobox.md ├── horizontalbox.md ├── form.md ├── checkbox.md ├── entry.md ├── readme.md ├── searchentry.md ├── group.md ├── passwordentry.md ├── multilineentry.md ├── tab.md └── window.md ├── .editorconfig ├── src ├── includes │ ├── event-loop-linux.h │ ├── event-loop-darwin.h │ ├── event-loop.h │ ├── timer.h │ ├── values.h │ ├── event-loop-windows.h │ └── control.h ├── timer-common.cc ├── Size.cc ├── Point.cc ├── UiSeparator.cc ├── UiProgressBar.cc ├── SizeDouble.cc ├── UiArea │ ├── UiAreaKeyEvent.cc │ ├── BrushGradientStop.cc │ ├── DrawTextLayout.cc │ ├── UiAreaDrawParams.cc │ ├── UiAreaMouseEvent.cc │ ├── UiDrawContext.cc │ ├── UiArea.cc │ ├── UiAreaHandler.cc │ ├── UiDrawPath.cc │ ├── DrawStrokeParams.cc │ ├── DrawBrush.cc │ └── DrawMatrix.cc ├── arch │ ├── unix │ │ ├── libui_loop.cc │ │ └── timer.cc │ ├── darwin │ │ ├── libui_loop.mm │ │ └── timer.mm │ └── win32 │ │ ├── libui_loop.cc │ │ └── timer.cc ├── PointDouble.cc ├── UiDateTimePicker.cc ├── UiLabel.cc ├── Ui.cc ├── Color.cc ├── UiFontButton.cc ├── UiSlider.cc ├── UiSpinbox.cc ├── UiButton.cc ├── UiCombobox.cc ├── UiColorButton.cc ├── Font │ ├── FontDescriptor.cc │ ├── OpenTypeFeatures.cc │ └── AttributedString.cc ├── UiRadioButtons.cc ├── UiForm.cc ├── UiEditableCombobox.cc ├── UiCheckbox.cc ├── UiControl.cc ├── UiGroup.cc ├── UiMultilineEntry.cc ├── UiBox.cc ├── UiTab.cc ├── UiGrid.cc ├── UiMenu.cc └── UiEntry.cc ├── examples ├── ControlGallery.app │ └── Contents │ │ └── MacOS │ │ └── ControlGallery ├── initialization.js ├── widgets │ ├── showUiButton.js │ ├── showUiEntry.js │ ├── showUiLabel.js │ ├── showUiCheckbox.js │ ├── showUiProgressBar.js │ ├── showUiSpinbox.js │ ├── showUiColorButton.js │ ├── showUiDatePicker.js │ ├── showUiTimePicker.js │ ├── showUiDateTimePicker.js │ ├── showUiMultilineEntry.js │ ├── showUiCombobox.js │ ├── showUiRadioButtons.js │ ├── showUiEditableCombobox.js │ ├── showUiSlider.js │ ├── showUiTab.js │ ├── showUiVerticalBox.js │ ├── showUiForm.js │ ├── showUiHorizontalBox.js │ ├── showUiHorizontalSeparator.js │ ├── showUiVerticalSeparator.js │ ├── showUiGroup.js │ └── showUiGrid.js ├── forms.js ├── grid.js ├── check-memory.js ├── core-api.js ├── area-adv.js ├── node-pad.js └── check-control-destroy.js ├── list-sources.js ├── .travis.yml ├── appveyor.yml ├── .clang-format ├── license ├── package.json ├── binding.gyp └── .gitignore /.gitmodules: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /autogypi.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": [ 3 | "nbind" 4 | ], 5 | "includes": [] 6 | } 7 | -------------------------------------------------------------------------------- /docs/media/UiTab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Abdelaziz18003/libui-node/master/docs/media/UiTab.png -------------------------------------------------------------------------------- /docs/media/UiArea.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Abdelaziz18003/libui-node/master/docs/media/UiArea.png -------------------------------------------------------------------------------- /docs/media/UiEntry.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Abdelaziz18003/libui-node/master/docs/media/UiEntry.png -------------------------------------------------------------------------------- /docs/media/UiForm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Abdelaziz18003/libui-node/master/docs/media/UiForm.png -------------------------------------------------------------------------------- /docs/media/UiGrid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Abdelaziz18003/libui-node/master/docs/media/UiGrid.png -------------------------------------------------------------------------------- /docs/media/UiGroup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Abdelaziz18003/libui-node/master/docs/media/UiGroup.png -------------------------------------------------------------------------------- /docs/media/UiLabel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Abdelaziz18003/libui-node/master/docs/media/UiLabel.png -------------------------------------------------------------------------------- /docs/media/UiButton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Abdelaziz18003/libui-node/master/docs/media/UiButton.png -------------------------------------------------------------------------------- /docs/media/UiCheckbox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Abdelaziz18003/libui-node/master/docs/media/UiCheckbox.png -------------------------------------------------------------------------------- /docs/media/UiCombobox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Abdelaziz18003/libui-node/master/docs/media/UiCombobox.png -------------------------------------------------------------------------------- /docs/media/UiSlider.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Abdelaziz18003/libui-node/master/docs/media/UiSlider.png -------------------------------------------------------------------------------- /docs/media/UiSpinbox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Abdelaziz18003/libui-node/master/docs/media/UiSpinbox.png -------------------------------------------------------------------------------- /docs/media/Pick_a_Color.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Abdelaziz18003/libui-node/master/docs/media/Pick_a_Color.png -------------------------------------------------------------------------------- /docs/media/UiDatePicker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Abdelaziz18003/libui-node/master/docs/media/UiDatePicker.png -------------------------------------------------------------------------------- /docs/media/UiFontButton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Abdelaziz18003/libui-node/master/docs/media/UiFontButton.png -------------------------------------------------------------------------------- /docs/media/UiTimePicker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Abdelaziz18003/libui-node/master/docs/media/UiTimePicker.png -------------------------------------------------------------------------------- /docs/media/Window-Linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Abdelaziz18003/libui-node/master/docs/media/Window-Linux.png -------------------------------------------------------------------------------- /docs/media/Window-macOS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Abdelaziz18003/libui-node/master/docs/media/Window-macOS.png -------------------------------------------------------------------------------- /docs/media/UiColorButton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Abdelaziz18003/libui-node/master/docs/media/UiColorButton.png -------------------------------------------------------------------------------- /docs/media/UiHorizontalBox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Abdelaziz18003/libui-node/master/docs/media/UiHorizontalBox.png -------------------------------------------------------------------------------- /docs/media/UiProgressBar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Abdelaziz18003/libui-node/master/docs/media/UiProgressBar.png -------------------------------------------------------------------------------- /docs/media/UiRadioButtons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Abdelaziz18003/libui-node/master/docs/media/UiRadioButtons.png -------------------------------------------------------------------------------- /docs/media/UiVerticalBox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Abdelaziz18003/libui-node/master/docs/media/UiVerticalBox.png -------------------------------------------------------------------------------- /docs/media/Window-Windows.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Abdelaziz18003/libui-node/master/docs/media/Window-Windows.png -------------------------------------------------------------------------------- /docs/media/UiDateTimePicker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Abdelaziz18003/libui-node/master/docs/media/UiDateTimePicker.png -------------------------------------------------------------------------------- /docs/media/UiMultilineEntry.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Abdelaziz18003/libui-node/master/docs/media/UiMultilineEntry.png -------------------------------------------------------------------------------- /docs/media/UiEditableCombobox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Abdelaziz18003/libui-node/master/docs/media/UiEditableCombobox.png -------------------------------------------------------------------------------- /docs/media/UiVerticalSeparator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Abdelaziz18003/libui-node/master/docs/media/UiVerticalSeparator.png -------------------------------------------------------------------------------- /docs/media/UiHorizontalSeparator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Abdelaziz18003/libui-node/master/docs/media/UiHorizontalSeparator.png -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | indent_style = tab 7 | trim_trailing_whitespace = true 8 | -------------------------------------------------------------------------------- /src/includes/event-loop-linux.h: -------------------------------------------------------------------------------- 1 | #ifndef ui_node_event_loop_linux 2 | #define ui_node_event_loop_linux 1 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /src/includes/event-loop-darwin.h: -------------------------------------------------------------------------------- 1 | #ifndef ui_node_event_loop_darwin 2 | #define ui_node_event_loop_darwin 1 3 | 4 | #import 5 | #import 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /examples/ControlGallery.app/Contents/MacOS/ControlGallery: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | #/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --enable-benchmarking --enable-extension-timeline-api& 3 | /Users/parroit/.nvm/versions/node/v9.5.0/bin/node /Users/parroit/repos/libui-node/examples/control-gallery.js& 4 | -------------------------------------------------------------------------------- /list-sources.js: -------------------------------------------------------------------------------- 1 | const readdirSync = require('fs').readdirSync; 2 | 3 | function listDir(dir) { 4 | readdirSync(dir) 5 | .filter(f => f.endsWith('.cc')) 6 | .forEach(f => console.log(dir + '/' + f)); 7 | } 8 | 9 | listDir('src'); 10 | listDir('src/Font'); 11 | listDir('src/UiArea'); 12 | listDir('src/arch/win32'); 13 | -------------------------------------------------------------------------------- /examples/initialization.js: -------------------------------------------------------------------------------- 1 | const { 2 | UiWindow, 3 | UiMenu, 4 | startLoop, 5 | stopLoop, 6 | onShouldQuit 7 | } = require('..'); 8 | 9 | const menu = new UiMenu('File'); 10 | menu.appendQuitItem(); 11 | 12 | const window = UiWindow('Initialization Example', 400, 300, true); 13 | 14 | onShouldQuit(() => { 15 | window.close(); 16 | stopLoop(); 17 | }); 18 | 19 | window.show(); 20 | startLoop(); 21 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | os: 2 | - linux 3 | - osx 4 | 5 | dist: trusty 6 | 7 | language: node_js 8 | 9 | node_js: 10 | - '10' 11 | - '9' 12 | - '8' 13 | - '6' 14 | - '4' 15 | 16 | sudo: required 17 | 18 | addons: 19 | apt: 20 | packages: 21 | - libgtk-3-dev 22 | - xvfb 23 | 24 | install: 25 | - export DISPLAY=':99.0' 26 | - Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & 27 | - npm install 28 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | version: 1.0.{build} 2 | image: Visual Studio 2015 3 | 4 | 5 | environment: 6 | matrix: 7 | - nodejs_version: "10" 8 | - nodejs_version: "9" 9 | - nodejs_version: "8" 10 | - nodejs_version: "6" 11 | - nodejs_version: "4" 12 | 13 | install: 14 | - ps: Install-Product node $env:nodejs_version x64 15 | - npm i npm@5.7 -g 16 | - npm install 17 | 18 | 19 | test_script: 20 | - npm test 21 | 22 | build: off 23 | -------------------------------------------------------------------------------- /examples/widgets/showUiButton.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable unicorn/filename-case */ 2 | 3 | const libui = require('../..'); 4 | 5 | const win = new libui.UiWindow('UiButton example', 320, 60, true); 6 | win.margined = true; 7 | 8 | const widget = new libui.UiButton(); 9 | widget.text = 'sample text'; 10 | win.setChild(widget); 11 | 12 | win.onClosing(() => { 13 | win.close(); 14 | libui.Ui.quit(); 15 | }); 16 | 17 | win.show(); 18 | 19 | libui.Ui.main(); 20 | -------------------------------------------------------------------------------- /examples/widgets/showUiEntry.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable unicorn/filename-case */ 2 | 3 | const libui = require('../..'); 4 | 5 | const win = new libui.UiWindow('UiEntry example', 320, 60, true); 6 | win.margined = true; 7 | 8 | const widget = new libui.UiEntry(); 9 | widget.text = 'sample text'; 10 | win.setChild(widget); 11 | 12 | win.onClosing(() => { 13 | win.close(); 14 | libui.Ui.quit(); 15 | }); 16 | 17 | win.show(); 18 | 19 | libui.Ui.main(); 20 | -------------------------------------------------------------------------------- /examples/widgets/showUiLabel.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable unicorn/filename-case */ 2 | 3 | const libui = require('../..'); 4 | 5 | const win = new libui.UiWindow('UiLabel example', 320, 60, true); 6 | win.margined = true; 7 | 8 | const widget = new libui.UiLabel(); 9 | widget.text = 'sample text'; 10 | win.setChild(widget); 11 | 12 | win.onClosing(() => { 13 | win.close(); 14 | libui.Ui.quit(); 15 | }); 16 | 17 | win.show(); 18 | 19 | libui.Ui.main(); 20 | -------------------------------------------------------------------------------- /examples/widgets/showUiCheckbox.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable unicorn/filename-case */ 2 | 3 | const libui = require('../..'); 4 | 5 | const win = new libui.UiWindow('UiCheckbox example', 320, 60, true); 6 | win.margined = true; 7 | 8 | const widget = new libui.UiCheckbox(); 9 | widget.text = 'sample text'; 10 | win.setChild(widget); 11 | 12 | win.onClosing(() => { 13 | win.close(); 14 | libui.Ui.quit(); 15 | }); 16 | 17 | win.show(); 18 | 19 | libui.Ui.main(); 20 | -------------------------------------------------------------------------------- /examples/widgets/showUiProgressBar.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable unicorn/filename-case */ 2 | 3 | const libui = require('../..'); 4 | 5 | const win = new libui.UiWindow('UiProgressBar example', 320, 60, true); 6 | win.margined = true; 7 | 8 | const widget = new libui.UiProgressBar(); 9 | widget.value = 50; 10 | win.setChild(widget); 11 | 12 | win.onClosing(() => { 13 | win.close(); 14 | libui.Ui.quit(); 15 | }); 16 | 17 | win.show(); 18 | 19 | libui.Ui.main(); 20 | -------------------------------------------------------------------------------- /examples/widgets/showUiSpinbox.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable unicorn/filename-case */ 2 | 3 | const libui = require('../..'); 4 | 5 | const win = new libui.UiWindow('UiSpinbox example', 320, 60, true); 6 | win.margined = true; 7 | 8 | const widget = new libui.UiSpinbox(); 9 | widget.value = 'sample text'; 10 | win.setChild(widget); 11 | 12 | win.onClosing(() => { 13 | win.close(); 14 | libui.stopLoop(); 15 | }); 16 | 17 | win.show(); 18 | 19 | libui.startLoop(); 20 | -------------------------------------------------------------------------------- /examples/widgets/showUiColorButton.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable unicorn/filename-case */ 2 | 3 | const libui = require('../..'); 4 | 5 | const win = new libui.UiWindow('UiColorButton example', 320, 60, true); 6 | win.margined = true; 7 | 8 | const widget = new libui.UiColorButton(); 9 | widget.text = 'sample text'; 10 | win.setChild(widget); 11 | 12 | win.onClosing(() => { 13 | win.close(); 14 | libui.Ui.quit(); 15 | }); 16 | 17 | win.show(); 18 | 19 | libui.Ui.main(); 20 | -------------------------------------------------------------------------------- /examples/widgets/showUiDatePicker.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable unicorn/filename-case */ 2 | 3 | const libui = require('../..'); 4 | 5 | const win = new libui.UiWindow('UiDatePicker example', 320, 60, true); 6 | win.margined = true; 7 | 8 | const widget = new libui.UiDatePicker(); 9 | widget.text = 'sample text'; 10 | win.setChild(widget); 11 | 12 | win.onClosing(() => { 13 | win.close(); 14 | libui.Ui.quit(); 15 | }); 16 | 17 | win.show(); 18 | 19 | libui.Ui.main(); 20 | -------------------------------------------------------------------------------- /examples/widgets/showUiTimePicker.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable unicorn/filename-case */ 2 | 3 | const libui = require('../..'); 4 | 5 | const win = new libui.UiWindow('UiTimePicker example', 320, 60, true); 6 | win.margined = true; 7 | 8 | const widget = new libui.UiTimePicker(); 9 | widget.text = 'sample text'; 10 | win.setChild(widget); 11 | 12 | win.onClosing(() => { 13 | win.close(); 14 | libui.Ui.quit(); 15 | }); 16 | 17 | win.show(); 18 | 19 | libui.Ui.main(); 20 | -------------------------------------------------------------------------------- /examples/widgets/showUiDateTimePicker.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable unicorn/filename-case */ 2 | 3 | const libui = require('../..'); 4 | 5 | const win = new libui.UiWindow('UiDateTimePicker example', 320, 60, true); 6 | win.margined = true; 7 | 8 | const widget = new libui.UiDateTimePicker(); 9 | widget.text = 'sample text'; 10 | win.setChild(widget); 11 | 12 | win.onClosing(() => { 13 | win.close(); 14 | libui.Ui.quit(); 15 | }); 16 | 17 | win.show(); 18 | 19 | libui.Ui.main(); 20 | -------------------------------------------------------------------------------- /examples/widgets/showUiMultilineEntry.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable unicorn/filename-case */ 2 | 3 | const libui = require('../..'); 4 | 5 | const win = new libui.UiWindow('UiMultilineEntry example', 320, 60, true); 6 | win.margined = true; 7 | 8 | const widget = new libui.UiMultilineEntry(); 9 | widget.text = 'sample text'; 10 | win.setChild(widget); 11 | 12 | win.onClosing(() => { 13 | win.close(); 14 | libui.Ui.quit(); 15 | }); 16 | 17 | win.show(); 18 | 19 | libui.Ui.main(); 20 | -------------------------------------------------------------------------------- /examples/widgets/showUiCombobox.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable unicorn/filename-case */ 2 | 3 | const libui = require('../..'); 4 | 5 | const win = new libui.UiWindow('UiCombobox example', 320, 60, true); 6 | win.margined = true; 7 | 8 | const widget = new libui.UiCombobox(); 9 | widget.append('Item1'); 10 | widget.append('Item2'); 11 | widget.append('Item3'); 12 | win.setChild(widget); 13 | 14 | win.onClosing(() => { 15 | win.close(); 16 | libui.Ui.quit(); 17 | }); 18 | 19 | win.show(); 20 | 21 | libui.Ui.main(); 22 | -------------------------------------------------------------------------------- /examples/widgets/showUiRadioButtons.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable unicorn/filename-case */ 2 | 3 | const libui = require('../..'); 4 | 5 | const win = new libui.UiWindow('UiRadioButtons example', 320, 60, true); 6 | win.margined = true; 7 | 8 | const widget = new libui.UiRadioButtons(); 9 | widget.append('Item1'); 10 | widget.append('Item2'); 11 | widget.append('Item3'); 12 | win.setChild(widget); 13 | 14 | win.onClosing(() => { 15 | win.close(); 16 | libui.Ui.quit(); 17 | }); 18 | 19 | win.show(); 20 | 21 | libui.Ui.main(); 22 | -------------------------------------------------------------------------------- /examples/widgets/showUiEditableCombobox.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable unicorn/filename-case */ 2 | 3 | const libui = require('../..'); 4 | 5 | const win = new libui.UiWindow('UiEditableCombobox example', 320, 60, true); 6 | win.margined = true; 7 | 8 | const widget = new libui.UiEditableCombobox(); 9 | 10 | widget.append('Item1'); 11 | widget.append('Item2'); 12 | widget.append('Item3'); 13 | 14 | win.setChild(widget); 15 | 16 | win.onClosing(() => { 17 | win.close(); 18 | libui.Ui.quit(); 19 | }); 20 | 21 | win.show(); 22 | 23 | libui.Ui.main(); 24 | -------------------------------------------------------------------------------- /examples/widgets/showUiSlider.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable unicorn/filename-case */ 2 | 3 | const libui = require('../..'); 4 | 5 | const win = new libui.UiWindow('UiSlider example', 320, 60, true); 6 | win.margined = true; 7 | 8 | const widget = new libui.UiSlider(); 9 | widget.value = 50; 10 | 11 | const cnt = new libui.UiVerticalBox(); 12 | cnt.padded = true; 13 | cnt.append(widget, false); 14 | 15 | win.setChild(cnt); 16 | 17 | win.onClosing(() => { 18 | win.close(); 19 | libui.Ui.quit(); 20 | }); 21 | 22 | win.show(); 23 | 24 | libui.Ui.main(); 25 | -------------------------------------------------------------------------------- /src/includes/event-loop.h: -------------------------------------------------------------------------------- 1 | #ifndef ui_node_event_loop 2 | #define ui_node_event_loop 1 3 | 4 | #include 5 | #include 6 | #include "nbind/nbind.h" 7 | #include "ui.h" 8 | 9 | // #define UI_NODE_DEBUG 1 10 | 11 | #ifdef UI_NODE_DEBUG 12 | #define DEBUG(msg) fprintf(stderr, msg) 13 | #define DEBUG_F(msg, ...) fprintf(stderr, msg, __VA_ARGS__) 14 | #else 15 | #define DEBUG(msg) ; 16 | #define DEBUG_F(msg, ...) ; 17 | #endif 18 | 19 | int uiEventsPending(); 20 | int uiLoopWakeup(); 21 | int waitForNodeEvents(uv_loop_t *loop, int timeout); 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /examples/widgets/showUiTab.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable unicorn/filename-case */ 2 | 3 | const libui = require('../..'); 4 | 5 | const win = new libui.UiWindow('UiTab example', 320, 90, true); 6 | win.margined = true; 7 | 8 | const widget = new libui.UiTab(); 9 | widget.padded = true; 10 | widget.append('Tab 1', new libui.UiEntry()); 11 | widget.append('Tab 2', new libui.UiEntry()); 12 | widget.append('Tab 3', new libui.UiEntry()); 13 | win.setChild(widget); 14 | 15 | win.onClosing(() => { 16 | win.close(); 17 | libui.Ui.quit(); 18 | }); 19 | 20 | win.show(); 21 | 22 | libui.Ui.main(); 23 | -------------------------------------------------------------------------------- /src/timer-common.cc: -------------------------------------------------------------------------------- 1 | #include "nbind/api.h" 2 | #include "timer.h" 3 | 4 | TimeoutHandle::TimeoutHandle(nbind::cbFunction *callbackJs) { 5 | this->callbackJs = callbackJs; 6 | this->destroyed = false; 7 | } 8 | 9 | void TimeoutHandle::destroy() { 10 | if (this->destroyed) { 11 | return; 12 | } 13 | 14 | delete this->callbackJs; 15 | this->destroyed = true; 16 | } 17 | 18 | #include "nbind/nbind.h" 19 | 20 | NBIND_GLOBAL() { 21 | function(setTimeout); 22 | function(clearTimeout); 23 | function(setInterval); 24 | function(clearInterval); 25 | } 26 | 27 | NBIND_CLASS(TimeoutHandle) {} 28 | -------------------------------------------------------------------------------- /examples/widgets/showUiVerticalBox.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable unicorn/filename-case */ 2 | 3 | const libui = require('../..'); 4 | 5 | const win = new libui.UiWindow('UiVerticalBox example', 320, 60, true); 6 | win.margined = true; 7 | 8 | const widget = new libui.UiVerticalBox(); 9 | widget.padded = true; 10 | widget.append(new libui.UiEntry(), false); 11 | widget.append(new libui.UiEntry(), false); 12 | widget.append(new libui.UiEntry(), false); 13 | win.setChild(widget); 14 | 15 | win.onClosing(() => { 16 | win.close(); 17 | libui.Ui.quit(); 18 | }); 19 | 20 | win.show(); 21 | 22 | libui.Ui.main(); 23 | -------------------------------------------------------------------------------- /examples/widgets/showUiForm.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable unicorn/filename-case */ 2 | 3 | const libui = require('../..'); 4 | 5 | const win = new libui.UiWindow('UiForm example', 320, 60, true); 6 | win.margined = true; 7 | 8 | const widget = new libui.UiForm(); 9 | widget.padded = true; 10 | widget.append('name', new libui.UiEntry(), false); 11 | widget.append('surname', new libui.UiEntry(), false); 12 | widget.append('age', new libui.UiEntry(), false); 13 | win.setChild(widget); 14 | 15 | win.onClosing(() => { 16 | win.close(); 17 | libui.Ui.quit(); 18 | }); 19 | 20 | win.show(); 21 | 22 | libui.Ui.main(); 23 | -------------------------------------------------------------------------------- /examples/widgets/showUiHorizontalBox.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable unicorn/filename-case */ 2 | 3 | const libui = require('../..'); 4 | 5 | const win = new libui.UiWindow('UiHorizontalBox example', 320, 60, true); 6 | win.margined = true; 7 | 8 | const widget = new libui.UiHorizontalBox(); 9 | widget.padded = true; 10 | widget.append(new libui.UiMultilineEntry(), false); 11 | widget.append(new libui.UiMultilineEntry(), false); 12 | widget.append(new libui.UiMultilineEntry(), false); 13 | win.setChild(widget); 14 | 15 | win.onClosing(() => { 16 | win.close(); 17 | libui.Ui.quit(); 18 | }); 19 | 20 | win.show(); 21 | 22 | libui.Ui.main(); 23 | -------------------------------------------------------------------------------- /examples/widgets/showUiHorizontalSeparator.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable unicorn/filename-case */ 2 | 3 | const libui = require('../..'); 4 | 5 | const win = new libui.UiWindow('UiHorizontalSeparator example', 320, 60, true); 6 | win.margined = true; 7 | 8 | const widget = new libui.UiVerticalBox(); 9 | widget.padded = true; 10 | widget.append(new libui.UiEntry(), false); 11 | widget.append(new libui.UiHorizontalSeparator(), false); 12 | widget.append(new libui.UiEntry(), false); 13 | win.setChild(widget); 14 | 15 | win.onClosing(() => { 16 | win.close(); 17 | libui.Ui.quit(); 18 | }); 19 | 20 | win.show(); 21 | 22 | libui.Ui.main(); 23 | -------------------------------------------------------------------------------- /examples/widgets/showUiVerticalSeparator.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable unicorn/filename-case */ 2 | 3 | const libui = require('../..'); 4 | 5 | const win = new libui.UiWindow('UiVerticalSeparator example', 320, 60, true); 6 | win.margined = true; 7 | 8 | const widget = new libui.UiHorizontalBox(); 9 | widget.padded = true; 10 | widget.append(new libui.UiMultilineEntry(), true); 11 | widget.append(new libui.UiVerticalSeparator(), false); 12 | widget.append(new libui.UiMultilineEntry(), true); 13 | win.setChild(widget); 14 | 15 | win.onClosing(() => { 16 | win.close(); 17 | libui.Ui.quit(); 18 | }); 19 | 20 | win.show(); 21 | 22 | libui.Ui.main(); 23 | -------------------------------------------------------------------------------- /src/Size.cc: -------------------------------------------------------------------------------- 1 | #include "values.h" 2 | 3 | Size::Size(int width, int height) { 4 | w = width; 5 | h = height; 6 | } 7 | 8 | int Size::getWidth() { 9 | return w; 10 | } 11 | 12 | void Size::setWidth(int value) { 13 | w = value; 14 | } 15 | 16 | int Size::getHeight() { 17 | return h; 18 | } 19 | 20 | void Size::setHeight(int value) { 21 | h = value; 22 | } 23 | 24 | void Size::toJS(nbind::cbOutput output) { 25 | output(w, h); 26 | } 27 | 28 | NBIND_CLASS(Size) { 29 | construct(); 30 | method(getWidth); 31 | method(setWidth); 32 | method(getHeight); 33 | method(setHeight); 34 | 35 | getset(getWidth, setWidth); 36 | getset(getHeight, setHeight); 37 | } 38 | -------------------------------------------------------------------------------- /src/Point.cc: -------------------------------------------------------------------------------- 1 | #include "values.h" 2 | 3 | Point::Point(const Point &other) { 4 | x = other.x; 5 | y = other.y; 6 | } 7 | 8 | Point::Point(int xCoord, int yCoord) { 9 | x = xCoord; 10 | y = yCoord; 11 | } 12 | 13 | int Point::getX() { 14 | return x; 15 | } 16 | 17 | void Point::setX(int value) { 18 | x = value; 19 | } 20 | 21 | int Point::getY() { 22 | return y; 23 | } 24 | 25 | void Point::setY(int value) { 26 | y = value; 27 | } 28 | 29 | void Point::toJS(nbind::cbOutput output) { 30 | output(x, y); 31 | } 32 | 33 | NBIND_CLASS(Point) { 34 | construct(); 35 | method(getX); 36 | method(setX); 37 | method(getY); 38 | method(setY); 39 | 40 | getset(getX, setX); 41 | getset(getY, setY); 42 | } 43 | -------------------------------------------------------------------------------- /src/UiSeparator.cc: -------------------------------------------------------------------------------- 1 | #include "nbind/api.h" 2 | #include "control.h" 3 | #include "ui.h" 4 | 5 | class UiHorizontalSeparator : public UiControl { 6 | public: 7 | UiHorizontalSeparator(); 8 | }; 9 | 10 | class UiVerticalSeparator : public UiControl { 11 | public: 12 | UiVerticalSeparator(); 13 | }; 14 | UiHorizontalSeparator::UiHorizontalSeparator() 15 | : UiControl((uiControl *)uiNewHorizontalSeparator()) {} 16 | 17 | NBIND_CLASS(UiHorizontalSeparator) { 18 | inherit(UiControl); 19 | construct<>(); 20 | } 21 | 22 | UiVerticalSeparator::UiVerticalSeparator() 23 | : UiControl((uiControl *)uiNewVerticalSeparator()) {} 24 | 25 | NBIND_CLASS(UiVerticalSeparator) { 26 | inherit(UiControl); 27 | construct<>(); 28 | } 29 | -------------------------------------------------------------------------------- /examples/widgets/showUiGroup.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable unicorn/filename-case */ 2 | 3 | const libui = require('../..'); 4 | 5 | const win = new libui.UiWindow('UiGroup example', 320, 60, true); 6 | win.margined = true; 7 | 8 | const widget = new libui.UiVerticalBox(); 9 | widget.padded = true; 10 | widget.append(new libui.UiEntry(), false); 11 | widget.append(new libui.UiEntry(), false); 12 | widget.append(new libui.UiEntry(), false); 13 | 14 | const group = new libui.UiGroup(); 15 | group.margined = true; 16 | group.title = 'A group of entries'; 17 | group.setChild(widget); 18 | 19 | win.setChild(group); 20 | 21 | win.onClosing(() => { 22 | win.close(); 23 | libui.Ui.quit(); 24 | }); 25 | 26 | win.show(); 27 | 28 | libui.Ui.main(); 29 | -------------------------------------------------------------------------------- /src/UiProgressBar.cc: -------------------------------------------------------------------------------- 1 | #include "nbind/api.h" 2 | #include "control.h" 3 | #include "ui.h" 4 | 5 | class UiProgressBar : public UiControl { 6 | private: 7 | int value = 0; 8 | 9 | public: 10 | UiProgressBar(); 11 | int getValue(); 12 | void setValue(int value); 13 | }; 14 | 15 | UiProgressBar::UiProgressBar() : UiControl((uiControl *)uiNewProgressBar()) {} 16 | 17 | void UiProgressBar::setValue(int val) { 18 | value = val; 19 | uiProgressBarSetValue((uiProgressBar *)getHandle(), value); 20 | } 21 | 22 | int UiProgressBar::getValue() { 23 | return value; 24 | } 25 | 26 | NBIND_CLASS(UiProgressBar) { 27 | inherit(UiControl); 28 | construct<>(); 29 | getset(getValue, setValue); 30 | method(getValue); 31 | method(setValue); 32 | } 33 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: LLVM 2 | IndentWidth: 4 3 | TabWidth: 4 4 | UseTab: Always 5 | MaxEmptyLinesToKeep: 1 6 | ColumnLimit: 80 7 | AllowShortBlocksOnASingleLine: false 8 | AllowShortIfStatementsOnASingleLine: false 9 | AllowShortLoopsOnASingleLine: false 10 | --- 11 | Language: Cpp 12 | AllowShortFunctionsOnASingleLine: Empty 13 | PointerAlignment: Right 14 | IncludeCategories: 15 | - Regex: "^<" 16 | Priority: 0 17 | - Regex: '/ui.h"$' 18 | Priority: 1 19 | - Regex: 'ui-node.h"$' 20 | Priority: 2 21 | - Regex: '"nbind/.*"' 22 | Priority: 3 23 | 24 | --- 25 | Language: JavaScript 26 | ColumnLimit: 0 27 | AllowShortFunctionsOnASingleLine: Empty 28 | JavaScriptQuotes: Single 29 | IndentCaseLabels: true 30 | SpacesInContainerLiterals: false 31 | -------------------------------------------------------------------------------- /src/SizeDouble.cc: -------------------------------------------------------------------------------- 1 | #include "values.h" 2 | 3 | SizeDouble::SizeDouble(double width, double height) { 4 | w = width; 5 | h = height; 6 | } 7 | 8 | double SizeDouble::getWidth() { 9 | return w; 10 | } 11 | 12 | void SizeDouble::setWidth(double value) { 13 | w = value; 14 | } 15 | 16 | double SizeDouble::getHeight() { 17 | return h; 18 | } 19 | 20 | void SizeDouble::setHeight(double value) { 21 | h = value; 22 | } 23 | 24 | void SizeDouble::toJS(nbind::cbOutput output) { 25 | output(w, h); 26 | } 27 | 28 | NBIND_CLASS(SizeDouble) { 29 | construct(); 30 | method(getWidth); 31 | method(setWidth); 32 | method(getHeight); 33 | method(setHeight); 34 | method(toJS); 35 | 36 | getset(getWidth, setWidth); 37 | getset(getHeight, setHeight); 38 | } 39 | -------------------------------------------------------------------------------- /src/UiArea/UiAreaKeyEvent.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "area.h" 3 | #include "ui.h" 4 | 5 | UiAreaKeyEvent::UiAreaKeyEvent(uiAreaKeyEvent *event) { 6 | e = event; 7 | } 8 | 9 | std::string UiAreaKeyEvent::getKey() { 10 | return std::string(1, e->Key); 11 | } 12 | 13 | int UiAreaKeyEvent::getExtKey() { 14 | return e->ExtKey; 15 | } 16 | 17 | int UiAreaKeyEvent::getModifier() { 18 | return e->Modifier; 19 | } 20 | 21 | int UiAreaKeyEvent::getModifiers() { 22 | return e->Modifiers; 23 | } 24 | 25 | int UiAreaKeyEvent::getUp() { 26 | return e->Up; 27 | } 28 | 29 | NBIND_CLASS(UiAreaKeyEvent) { 30 | construct(); 31 | method(getKey); 32 | method(getExtKey); 33 | method(getModifier); 34 | method(getModifiers); 35 | method(getUp); 36 | } 37 | -------------------------------------------------------------------------------- /docs/events.md: -------------------------------------------------------------------------------- 1 | # libui-node widgets events 2 | 3 | Many widgets have events that are raised when their properties changed, because user interacts with GUI or because programmer has invoked a property setter. 4 | 5 | All events are methods that accepts a single callback that receive 0 arguments. 6 | 7 | ```js 8 | var widget = new libui.UiEntry(); 9 | 10 | widget.onChanged(function() { 11 | console.log(widget.text); 12 | }); 13 | 14 | // set the text contained in the entry 15 | widget.text = 'sample text'; 16 | ``` 17 | 18 | Widgets don't keep an internal list of event listener. If you register more that one callbacks, previous one are lost and never get called. This is implemented directly in `libui`, maybe we implement `Node.js` style event emitter in a future release. 19 | 20 | -------------------------------------------------------------------------------- /src/arch/unix/libui_loop.cc: -------------------------------------------------------------------------------- 1 | #include "event-loop-linux.h" 2 | #include "event-loop.h" 3 | 4 | int uiLoopWakeup() { 5 | DEBUG("uiLoopWakeup\n"); 6 | g_main_context_wakeup(NULL); 7 | DEBUG("uiLoopWakeup exit\n"); 8 | return 0; 9 | } 10 | 11 | int uiEventsPending() { 12 | DEBUG("uiEventsPending\n"); 13 | return gtk_events_pending(); 14 | } 15 | 16 | int waitForNodeEvents(uv_loop_t *loop, int timeout) { 17 | DEBUG("uv_backend_fd\n"); 18 | int nodeBackendFd = uv_backend_fd(loop); 19 | DEBUG_F("uv_backend_fd %d\n", nodeBackendFd); 20 | 21 | if (nodeBackendFd == -1) { 22 | fprintf(stderr, "Invalid node backend fd.\n"); 23 | return 0; 24 | } 25 | 26 | struct epoll_event ev; 27 | DEBUG("epoll_wait\n"); 28 | 29 | return epoll_wait(nodeBackendFd, &ev, 1, timeout); 30 | } 31 | -------------------------------------------------------------------------------- /src/PointDouble.cc: -------------------------------------------------------------------------------- 1 | #include "values.h" 2 | 3 | PointDouble::PointDouble(const PointDouble &other) { 4 | x = other.x; 5 | y = other.y; 6 | } 7 | 8 | PointDouble::PointDouble(double xCoord, double yCoord) { 9 | x = xCoord; 10 | y = yCoord; 11 | } 12 | 13 | double PointDouble::getX() { 14 | return x; 15 | } 16 | 17 | void PointDouble::setX(double value) { 18 | x = value; 19 | } 20 | 21 | double PointDouble::getY() { 22 | return y; 23 | } 24 | 25 | void PointDouble::setY(double value) { 26 | y = value; 27 | } 28 | 29 | void PointDouble::toJS(nbind::cbOutput output) { 30 | output(x, y); 31 | } 32 | 33 | NBIND_CLASS(PointDouble) { 34 | construct(); 35 | method(getX); 36 | method(setX); 37 | method(getY); 38 | method(setY); 39 | 40 | getset(getX, setX); 41 | getset(getY, setY); 42 | } 43 | -------------------------------------------------------------------------------- /src/UiArea/BrushGradientStop.cc: -------------------------------------------------------------------------------- 1 | #include "area.h" 2 | #include "ui.h" 3 | 4 | BrushGradientStop::BrushGradientStop(double pos, Color color) : c(color) { 5 | p = pos; 6 | } 7 | 8 | Color BrushGradientStop::getColor() { 9 | return c; 10 | } 11 | 12 | void BrushGradientStop::setColor(Color value) { 13 | c = value; 14 | } 15 | 16 | double BrushGradientStop::getPos() { 17 | return p; 18 | } 19 | 20 | void BrushGradientStop::setPos(double value) { 21 | p = value; 22 | } 23 | 24 | void BrushGradientStop::toJS(nbind::cbOutput output) { 25 | output(p, c); 26 | } 27 | 28 | NBIND_CLASS(BrushGradientStop) { 29 | construct(); 30 | method(getColor); 31 | method(setColor); 32 | method(getPos); 33 | method(setPos); 34 | method(toJS); 35 | getset(getColor, setColor); 36 | getset(getPos, setPos); 37 | } 38 | -------------------------------------------------------------------------------- /examples/widgets/showUiGrid.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable unicorn/filename-case */ 2 | 3 | const libui = require('../..'); 4 | 5 | const win = new libui.UiWindow('UiGrid example', 320, 60, true); 6 | win.margined = true; 7 | 8 | const grid = new libui.UiGrid(); 9 | grid.padded = true; 10 | grid.append(new libui.UiLabel('name'), 0, 0, 2, 1, 0, 0, 0, 1); 11 | grid.append(new libui.UiLabel('surname'), 0, 1, 2, 1, 0, 0, 0, 1); 12 | grid.append(new libui.UiLabel('age'), 0, 2, 2, 1, 0, 0, 0, 1); 13 | 14 | grid.append(new libui.UiEntry(), 2, 0, 2, 1, 0, 0, 0, 1); 15 | grid.append(new libui.UiEntry(), 2, 1, 3, 1, 0, 0, 0, 1); 16 | grid.append(new libui.UiEntry(), 2, 2, 4, 2, 0, 0, 0, 1); 17 | 18 | win.setChild(grid); 19 | 20 | win.onClosing(() => { 21 | win.close(); 22 | libui.Ui.quit(); 23 | }); 24 | 25 | win.show(); 26 | 27 | libui.Ui.main(); 28 | -------------------------------------------------------------------------------- /src/UiArea/DrawTextLayout.cc: -------------------------------------------------------------------------------- 1 | #include "area.h" 2 | #include "ui.h" 3 | 4 | DrawTextLayout::DrawTextLayout(AttributedString *str, 5 | FontDescriptor *defaultFont, double width, 6 | int align) { 7 | uiDrawTextLayoutParams params = {str->getHandle(), defaultFont->getHandle(), 8 | width, (uiDrawTextAlign)align}; 9 | 10 | handle = uiDrawNewTextLayout(¶ms); 11 | } 12 | 13 | DrawTextLayout::~DrawTextLayout() { 14 | uiDrawFreeTextLayout(handle); 15 | } 16 | 17 | uiDrawTextLayout *DrawTextLayout::getHandle() { 18 | return handle; 19 | } 20 | 21 | SizeDouble DrawTextLayout::getExtents() { 22 | double width; 23 | double height; 24 | uiDrawTextLayoutExtents(handle, &width, &height); 25 | return SizeDouble(width, height); 26 | } 27 | 28 | NBIND_CLASS(DrawTextLayout) { 29 | construct(); 30 | method(getExtents); 31 | } 32 | -------------------------------------------------------------------------------- /src/UiDateTimePicker.cc: -------------------------------------------------------------------------------- 1 | #include "nbind/api.h" 2 | #include "control.h" 3 | #include "ui.h" 4 | 5 | class UiDateTimePicker : public UiControl { 6 | public: 7 | UiDateTimePicker(); 8 | }; 9 | 10 | UiDateTimePicker::UiDateTimePicker() 11 | : UiControl((uiControl *)uiNewDateTimePicker()) {} 12 | 13 | NBIND_CLASS(UiDateTimePicker) { 14 | inherit(UiControl); 15 | construct<>(); 16 | } 17 | 18 | class UiTimePicker : public UiControl { 19 | public: 20 | UiTimePicker(); 21 | }; 22 | 23 | UiTimePicker::UiTimePicker() : UiControl((uiControl *)uiNewTimePicker()) {} 24 | 25 | NBIND_CLASS(UiTimePicker) { 26 | inherit(UiControl); 27 | construct<>(); 28 | } 29 | 30 | class UiDatePicker : public UiControl { 31 | public: 32 | UiDatePicker(); 33 | }; 34 | 35 | UiDatePicker::UiDatePicker() : UiControl((uiControl *)uiNewDatePicker()) {} 36 | 37 | NBIND_CLASS(UiDatePicker) { 38 | inherit(UiControl); 39 | construct<>(); 40 | } 41 | -------------------------------------------------------------------------------- /src/UiLabel.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "nbind/api.h" 3 | #include "control.h" 4 | #include "ui.h" 5 | 6 | class UiLabel : public UiControl { 7 | public: 8 | UiLabel(); 9 | UiLabel(std::string text); 10 | void setText(std::string text); 11 | std::string getText(); 12 | }; 13 | 14 | UiLabel::UiLabel(std::string text) 15 | : UiControl(uiControl(uiNewLabel(text.c_str()))) {} 16 | UiLabel::UiLabel() : UiControl(uiControl(uiNewLabel(""))) {} 17 | 18 | void UiLabel::setText(std::string text) { 19 | uiLabelSetText(uiLabel(getHandle()), text.c_str()); 20 | } 21 | 22 | std::string UiLabel::getText() { 23 | char *char_ptr = uiLabelText(uiLabel(getHandle())); 24 | std::string s(char_ptr); 25 | uiFreeText(char_ptr); 26 | return s; 27 | } 28 | 29 | NBIND_CLASS(UiLabel) { 30 | inherit(UiControl); 31 | construct(); 32 | construct<>(); 33 | getset(getText, setText); 34 | method(getText); 35 | method(setText); 36 | } 37 | -------------------------------------------------------------------------------- /src/includes/timer.h: -------------------------------------------------------------------------------- 1 | #ifndef UI_NODE_CONTROL 2 | #define UI_NODE_CONTROL 1 3 | 4 | #include "nbind/api.h" 5 | 6 | #ifdef WIN32 7 | #include 8 | typedef UINT_PTR TIMER_HANDLE; 9 | #endif 10 | 11 | #ifdef __APPLE__ 12 | typedef void *TIMER_HANDLE; 13 | #endif 14 | 15 | #ifdef __linux__ 16 | #include 17 | #include 18 | typedef unsigned int TIMER_HANDLE; 19 | #endif 20 | 21 | class TimeoutHandle { 22 | public: 23 | TIMER_HANDLE handle; 24 | nbind::cbFunction *callbackJs; 25 | bool destroyed; 26 | 27 | TimeoutHandle(nbind::cbFunction *callbackJs); 28 | void destroy(); 29 | }; 30 | 31 | #define CALL_JSCB(timeoutHandle) (*(timeoutHandle->callbackJs))() 32 | 33 | TimeoutHandle *setInterval(nbind::cbFunction &cb, unsigned int timeout); 34 | void clearInterval(TimeoutHandle *timeoutHandle); 35 | TimeoutHandle *setTimeout(nbind::cbFunction &cb, unsigned int timeout); 36 | void clearTimeout(TimeoutHandle *timeoutHandle); 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /docs/properties.md: -------------------------------------------------------------------------------- 1 | # libui-node widgets properties 2 | 3 | Every widget properties has a dual implementation. 4 | 5 | You can read and write them both using javascript properties and using setter/getter methods. 6 | 7 | Javascript properties are implemented on top of getter/setter methods provided by `libui`. 8 | We've choosen to provide access to getter/setter method to increase flexibility. They could be useful for a functional style paradigm style coding. You can bind / map / filter on them. 9 | 10 | 11 | ### using javascript properties 12 | 13 | ```js 14 | var widget = new libui.UiEntry(); 15 | // set the text contained in the entry 16 | widget.text = 'sample text'; 17 | 18 | // retrieve it 19 | console.log(widget.text); 20 | ``` 21 | 22 | ### using setter/getter methods 23 | 24 | ```js 25 | var widget = new libui.UiEntry(); 26 | // set the text contained in the entry 27 | widget.setText('sample text'); 28 | 29 | // retrieve it 30 | console.log(widget.getText()); 31 | ``` 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /src/UiArea/UiAreaDrawParams.cc: -------------------------------------------------------------------------------- 1 | #include "area.h" 2 | #include "ui.h" 3 | 4 | UiAreaDrawParams::UiAreaDrawParams(uiAreaDrawParams *params) { 5 | p = params; 6 | } 7 | 8 | UiDrawContext *UiAreaDrawParams::getContext() { 9 | return new UiDrawContext(p->Context); 10 | } 11 | 12 | // TODO: make readony properties 13 | // 14 | 15 | double UiAreaDrawParams::getAreaWidth() { 16 | return p->AreaWidth; 17 | } 18 | 19 | double UiAreaDrawParams::getAreaHeight() { 20 | return p->AreaHeight; 21 | } 22 | 23 | double UiAreaDrawParams::getClipX() { 24 | return p->ClipX; 25 | } 26 | 27 | double UiAreaDrawParams::getClipY() { 28 | return p->ClipY; 29 | } 30 | 31 | double UiAreaDrawParams::getClipWidth() { 32 | return p->ClipWidth; 33 | } 34 | 35 | double UiAreaDrawParams::getClipHeight() { 36 | return p->ClipHeight; 37 | } 38 | 39 | NBIND_CLASS(UiAreaDrawParams) { 40 | construct(); 41 | method(getContext); 42 | method(getAreaWidth); 43 | method(getAreaHeight); 44 | method(getClipX); 45 | method(getClipY); 46 | method(getClipWidth); 47 | method(getClipHeight); 48 | } 49 | -------------------------------------------------------------------------------- /src/Ui.cc: -------------------------------------------------------------------------------- 1 | #include "ui.h" 2 | #include "nbind/api.h" 3 | #include "nbind/nbind.h" 4 | 5 | /* TODO: this file has to be removed */ 6 | 7 | static int onShouldQuit_cb(void *data) { 8 | nbind::cbFunction *cb = (nbind::cbFunction *)data; 9 | (*cb)(); 10 | return 0; 11 | } 12 | 13 | struct Ui { 14 | static void main() { 15 | uiMain(); 16 | } 17 | 18 | static void mainSteps() { 19 | uiMainSteps(); 20 | } 21 | 22 | static int mainStep(int wait) { 23 | return uiMainStep(wait); 24 | } 25 | 26 | static void onShouldQuit(nbind::cbFunction &cb) { 27 | uiOnShouldQuit(onShouldQuit_cb, new nbind::cbFunction(cb)); 28 | } 29 | 30 | static void quit() { 31 | uiQuit(); 32 | } 33 | 34 | static void init() { 35 | uiInitOptions o; 36 | memset(&o, 0, sizeof(uiInitOptions)); 37 | const char *err = uiInit(&o); 38 | if (err != NULL) { 39 | NBIND_ERR(err); 40 | uiFreeInitError(err); 41 | } 42 | } 43 | }; 44 | 45 | NBIND_CLASS(Ui) { 46 | method(init); 47 | method(main); 48 | method(quit); 49 | method(mainStep); 50 | method(mainSteps); 51 | method(onShouldQuit); 52 | } 53 | -------------------------------------------------------------------------------- /examples/forms.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const libui = require('..'); 3 | 4 | const win = new libui.UiWindow('Forms window', 800, 600, false); 5 | win.margined = 1; 6 | win.onClosing(() => { 7 | libui.stopLoop(); 8 | }); 9 | 10 | const hBox = new libui.UiHorizontalBox(); 11 | hBox.padded = true; 12 | 13 | const name = new libui.UiEntry(); 14 | const surname = new libui.UiEntry(); 15 | const age = new libui.UiSlider(0, 100); 16 | const JSONData = new libui.UiMultilineEntry(); 17 | 18 | name.onChanged(setJSON); 19 | surname.onChanged(setJSON); 20 | age.onChanged(setJSON); 21 | 22 | name.text = 'Andrea'; 23 | surname.text = 'Parodi'; 24 | age.value = 40; 25 | 26 | const form = new libui.UiForm(); 27 | form.padded = true; 28 | form.append('name', name, 0); 29 | form.append('surname', surname, 0); 30 | form.append('age', age, 0); 31 | 32 | hBox.append(form, 1); 33 | hBox.append(JSONData, 1); 34 | 35 | win.setChild(hBox); 36 | win.show(); 37 | libui.startLoop(); 38 | 39 | function setJSON() { 40 | const data = { 41 | name: name.text, 42 | surname: surname.text, 43 | age: age.value 44 | }; 45 | JSONData.text = JSON.stringify(data, null, 4); 46 | } 47 | -------------------------------------------------------------------------------- /license: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018 parro-it 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 19 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 20 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE 21 | OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /src/UiArea/UiAreaMouseEvent.cc: -------------------------------------------------------------------------------- 1 | #include "area.h" 2 | #include "ui.h" 3 | 4 | UiAreaMouseEvent::UiAreaMouseEvent(uiAreaMouseEvent *event) { 5 | e = event; 6 | } 7 | 8 | double UiAreaMouseEvent::getX() { 9 | return e->X; 10 | } 11 | 12 | double UiAreaMouseEvent::getY() { 13 | return e->Y; 14 | } 15 | 16 | double UiAreaMouseEvent::getAreaWidth() { 17 | return e->AreaWidth; 18 | } 19 | 20 | double UiAreaMouseEvent::getAreaHeight() { 21 | return e->AreaHeight; 22 | } 23 | 24 | int UiAreaMouseEvent::getDown() { 25 | return e->Down; 26 | } 27 | 28 | int UiAreaMouseEvent::getUp() { 29 | return e->Up; 30 | } 31 | 32 | int UiAreaMouseEvent::getCount() { 33 | return e->Count; 34 | } 35 | 36 | int UiAreaMouseEvent::getModifiers() { 37 | return e->Modifiers; 38 | } 39 | 40 | unsigned int UiAreaMouseEvent::getHeld1To64() { 41 | return e->Held1To64; 42 | } 43 | 44 | NBIND_CLASS(UiAreaMouseEvent) { 45 | construct(); 46 | method(getX); 47 | method(getY); 48 | method(getAreaWidth); 49 | method(getAreaHeight); 50 | method(getDown); 51 | method(getUp); 52 | method(getCount); 53 | method(getModifiers); 54 | method(getHeld1To64); 55 | } 56 | -------------------------------------------------------------------------------- /src/UiArea/UiDrawContext.cc: -------------------------------------------------------------------------------- 1 | #include "area.h" 2 | #include "ui.h" 3 | 4 | UiDrawContext::UiDrawContext(uiDrawContext *ctx) { 5 | c = ctx; 6 | } 7 | 8 | void UiDrawContext::stroke(UiDrawPath *path, DrawBrush *b, 9 | DrawStrokeParams *p) { 10 | uiDrawStroke(c, path->getHandle(), b->toStruct(), p->toStruct()); 11 | } 12 | 13 | void UiDrawContext::fill(UiDrawPath *path, DrawBrush *b) { 14 | uiDrawFill(c, path->getHandle(), b->toStruct()); 15 | } 16 | 17 | void UiDrawContext::transform(UiDrawMatrix *m) { 18 | uiDrawTransform(c, m->getStruct()); 19 | } 20 | 21 | void UiDrawContext::clip(UiDrawPath *path) { 22 | uiDrawClip(c, path->getHandle()); 23 | } 24 | 25 | void UiDrawContext::save() { 26 | uiDrawSave(c); 27 | } 28 | 29 | void UiDrawContext::restore() { 30 | uiDrawRestore(c); 31 | } 32 | 33 | void UiDrawContext::text(double x, double y, DrawTextLayout *layout) { 34 | uiDrawText(c, layout->getHandle(), x, y); 35 | } 36 | 37 | NBIND_CLASS(UiDrawContext) { 38 | construct(); 39 | method(stroke); 40 | method(fill); 41 | method(transform); 42 | method(clip); 43 | method(save); 44 | method(restore); 45 | method(text); 46 | } 47 | -------------------------------------------------------------------------------- /src/Color.cc: -------------------------------------------------------------------------------- 1 | #include "values.h" 2 | 3 | Color::Color(const Color &other) { 4 | r = other.r; 5 | g = other.g; 6 | b = other.b; 7 | a = other.a; 8 | } 9 | 10 | Color::Color(double red, double green, double blue, double alpha) { 11 | r = red; 12 | g = green; 13 | b = blue; 14 | a = alpha; 15 | } 16 | 17 | double Color::getR() { 18 | return r; 19 | } 20 | 21 | void Color::setR(double value) { 22 | r = value; 23 | } 24 | 25 | double Color::getG() { 26 | return g; 27 | } 28 | 29 | void Color::setG(double value) { 30 | g = value; 31 | } 32 | 33 | double Color::getB() { 34 | return b; 35 | } 36 | 37 | void Color::setB(double value) { 38 | b = value; 39 | } 40 | 41 | double Color::getA() { 42 | return a; 43 | } 44 | 45 | void Color::setA(double value) { 46 | a = value; 47 | } 48 | 49 | void Color::toJS(nbind::cbOutput output) { 50 | output(r, g, b, a); 51 | } 52 | 53 | NBIND_CLASS(Color) { 54 | construct(); 55 | method(getR); 56 | method(setR); 57 | method(getG); 58 | method(setG); 59 | method(getB); 60 | method(setB); 61 | method(getA); 62 | method(setA); 63 | 64 | getset(getR, setR); 65 | getset(getG, setG); 66 | getset(getB, setB); 67 | getset(getA, setA); 68 | } 69 | -------------------------------------------------------------------------------- /src/arch/darwin/libui_loop.mm: -------------------------------------------------------------------------------- 1 | #include "event-loop-darwin.h" 2 | #include "event-loop.h" 3 | 4 | int uiLoopWakeup() { 5 | [NSApp postEvent:[NSEvent otherEventWithType:NSApplicationDefined 6 | location:NSZeroPoint 7 | modifierFlags:0 8 | timestamp:0.0 9 | windowNumber:0 10 | context:nil 11 | subtype:0 12 | data1:0 13 | data2:0] 14 | atStart:NO]; 15 | 16 | return 0; 17 | } 18 | 19 | int uiEventsPending() { 20 | NSEvent *event = [NSApp nextEventMatchingMask:NSAnyEventMask 21 | untilDate:[NSDate distantPast] 22 | inMode:NSDefaultRunLoopMode 23 | dequeue:NO]; 24 | return nil != event; 25 | } 26 | 27 | int waitForNodeEvents(uv_loop_t *loop, int timeout) { 28 | int nodeBackendFd = uv_backend_fd(loop); 29 | if (nodeBackendFd == -1) { 30 | fprintf(stderr, "Invalid node backend fd.\n"); 31 | return 0; 32 | } 33 | 34 | struct kevent event; 35 | struct timespec ts; 36 | struct timespec *tsp = nullptr; 37 | 38 | if (timeout != -1) { 39 | tsp = &ts; 40 | ts.tv_sec = timeout / 1000; 41 | ts.tv_nsec = (timeout % 1000) * 1000000; 42 | } 43 | 44 | return kevent(nodeBackendFd, NULL, 0, &event, 1, tsp); 45 | } 46 | -------------------------------------------------------------------------------- /docs/initialization.md: -------------------------------------------------------------------------------- 1 | # Event loop 2 | 3 | `libui-node` runs an event loop independent of that of Node.js that takes care of processing GUI events. This event loop can run seamlessy together with the Node.js one, so you can still use any asynchronous Node.js function. 4 | 5 | You are responsible to start and stop the loop, by calling the `startLoop` and `stopLoop` functions. 6 | 7 | `startLoop` returns immediately after it started the event loop. It keeps 8 | a Node.js handle active, so it prevents your process to terminate, until 9 | you call `stopLoop` later. 10 | 11 | # Quit handler 12 | 13 | The `onShouldQuit` function allows you to register a callback that is called when a "Quit" menu item is clicked. You are responsible to terminate the application in response to this event, usually by calling `stopLoop` method. 14 | 15 | # Example 16 | 17 | ```js 18 | const { 19 | UiWindow, 20 | UiMenu, 21 | startLoop, 22 | stopLoop, 23 | onShouldQuit 24 | } = require('libui'); 25 | 26 | 27 | const menu = new UiMenu('File'); 28 | menu.appendQuitItem(); 29 | 30 | const window = UiWindow('Initialization Example', 400, 300, true); 31 | 32 | onShouldQuit(() => { 33 | window.close(); 34 | stopLoop(); 35 | }); 36 | 37 | window.show(); 38 | startLoop(); 39 | ``` 40 | -------------------------------------------------------------------------------- /src/UiFontButton.cc: -------------------------------------------------------------------------------- 1 | #include "nbind/api.h" 2 | #include "area.h" 3 | #include "control.h" 4 | #include "ui.h" 5 | #include "values.h" 6 | 7 | class UiFontButton : public UiControl { 8 | DEFINE_EVENT(onChanged) 9 | 10 | public: 11 | UiFontButton(); 12 | ~UiFontButton(); 13 | FontDescriptor getFont(); 14 | void onDestroy(uiControl *control) override; 15 | }; 16 | 17 | UiFontButton::~UiFontButton() { 18 | // printf("UiFontButton %p destroyed with wrapper %p.\n", getHandle(), 19 | // this); 20 | } 21 | 22 | void UiFontButton::onDestroy(uiControl *control) { 23 | /* 24 | freeing event callbacks to allow JS to garbage collect this class 25 | when there are no references to it left in JS code. 26 | */ 27 | DISPOSE_EVENT(onChanged); 28 | } 29 | 30 | UiFontButton::UiFontButton() : UiControl((uiControl *)uiNewFontButton()) {} 31 | 32 | IMPLEMENT_EVENT(UiFontButton, uiFontButton, onChanged, uiFontButtonOnChanged) 33 | 34 | FontDescriptor UiFontButton::getFont() { 35 | uiFontDescriptor *desc = new uiFontDescriptor(); 36 | uiFontButtonFont((uiFontButton *)getHandle(), desc); 37 | return FontDescriptor(desc); 38 | } 39 | 40 | NBIND_CLASS(UiFontButton) { 41 | inherit(UiControl); 42 | construct<>(); 43 | getter(getFont); 44 | method(getFont); 45 | method(onChanged); 46 | } 47 | -------------------------------------------------------------------------------- /examples/grid.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const libui = require('..'); 3 | 4 | const win = new libui.UiWindow('Forms window', 800, 600, false); 5 | win.margined = 1; 6 | win.onClosing(() => { 7 | libui.stopLoop(); 8 | }); 9 | 10 | const name = new libui.UiEntry(); 11 | const surname = new libui.UiEntry(); 12 | const age = new libui.UiSlider(0, 100); 13 | const JSONData = new libui.UiMultilineEntry(); 14 | 15 | name.onChanged(setJSON); 16 | surname.onChanged(setJSON); 17 | age.onChanged(setJSON); 18 | 19 | name.text = 'Andrea'; 20 | surname.text = 'Parodi'; 21 | age.value = 40; 22 | 23 | const grid = new libui.UiGrid(); 24 | grid.padded = true; 25 | grid.append(new libui.UiLabel('name'), 0, 0, 2, 1, 0, 0, 0, 1); 26 | grid.append(new libui.UiLabel('surname'), 0, 1, 2, 1, 0, 0, 0, 1); 27 | grid.append(new libui.UiLabel('age'), 0, 2, 2, 1, 0, 0, 0, 1); 28 | 29 | grid.append(name, 2, 0, 2, 1, 0, 0, 0, 1); 30 | grid.append(surname, 2, 1, 2, 1, 0, 0, 0, 1); 31 | grid.append(age, 2, 2, 2, 1, 0, 0, 0, 1); 32 | 33 | grid.append(JSONData, 4, 0, 1, 3, 1, 0, 1, 0); 34 | 35 | win.setChild(grid); 36 | win.show(); 37 | libui.startLoop(); 38 | 39 | function setJSON() { 40 | const data = { 41 | name: name.text, 42 | surname: surname.text, 43 | age: age.value 44 | }; 45 | JSONData.text = JSON.stringify(data, null, 4); 46 | } 47 | -------------------------------------------------------------------------------- /src/arch/unix/timer.cc: -------------------------------------------------------------------------------- 1 | #include "timer.h" 2 | #include "nbind/api.h" 3 | 4 | gboolean glib_timeout_cb(TimeoutHandle *timeoutHandle) { 5 | CALL_JSCB(timeoutHandle); 6 | timeoutHandle->destroy(); 7 | return FALSE; 8 | } 9 | 10 | gboolean glib_interval_cb(TimeoutHandle *timeoutHandle) { 11 | CALL_JSCB(timeoutHandle); 12 | return TRUE; 13 | } 14 | 15 | TimeoutHandle *setTimeout(nbind::cbFunction &cb, unsigned int timeout) { 16 | nbind::cbFunction *callbackJs = new nbind::cbFunction(cb); 17 | TimeoutHandle *timeoutHandle = new TimeoutHandle(callbackJs); 18 | timeoutHandle->handle = 19 | g_timeout_add(timeout, (GSourceFunc)glib_timeout_cb, timeoutHandle); 20 | return timeoutHandle; 21 | } 22 | 23 | void clearTimeout(TimeoutHandle *timeoutHandle) { 24 | g_source_remove(timeoutHandle->handle); 25 | timeoutHandle->destroy(); 26 | } 27 | 28 | TimeoutHandle *setInterval(nbind::cbFunction &cb, unsigned int timeout) { 29 | nbind::cbFunction *callbackJs = new nbind::cbFunction(cb); 30 | TimeoutHandle *timeoutHandle = new TimeoutHandle(callbackJs); 31 | timeoutHandle->handle = 32 | g_timeout_add(timeout, (GSourceFunc)glib_interval_cb, timeoutHandle); 33 | return timeoutHandle; 34 | } 35 | 36 | void clearInterval(TimeoutHandle *timeoutHandle) { 37 | g_source_remove(timeoutHandle->handle); 38 | timeoutHandle->destroy(); 39 | } 40 | -------------------------------------------------------------------------------- /src/arch/win32/libui_loop.cc: -------------------------------------------------------------------------------- 1 | #include "event-loop-windows.h" 2 | #include "event-loop.h" 3 | 4 | void noop(void *data) {} 5 | 6 | int uiLoopWakeup() { 7 | uiQueueMain(noop, NULL); 8 | // give main thread some time to react 9 | return 0; 10 | } 11 | 12 | int uiEventsPending() { 13 | MSG msg; 14 | return PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE); 15 | } 16 | 17 | int waitForNodeEvents(uv_loop_t *loop, int timeout) { 18 | DWORD bytes; 19 | ULONG_PTR key; 20 | OVERLAPPED *overlapped; 21 | 22 | struct _internal_uv_loop_s *_loop = (_internal_uv_loop_s *)loop; 23 | 24 | if (timeout == -1) { 25 | timeout = INFINITE; 26 | } 27 | 28 | int ret = GetQueuedCompletionStatus(_loop->iocp, &bytes, &key, &overlapped, 29 | timeout); 30 | 31 | // Does we need to requeue the queued completions? 32 | // this happen to be same code used by Electron 33 | // on Windows: 34 | // https://github.com/electron/electron/blob/master/atom/common/node_bindings_win.cc#L24 35 | // but the application become unstable when this 36 | // part is uncommented. 37 | // See laso this PRs on libuv repo: 38 | // https://github.com/libuv/libuv/pull/1007 39 | // https://github.com/libuv/libuv/pull/1544 40 | // https://github.com/libuv/libuv/pull/1651 41 | if (overlapped != NULL) { 42 | DEBUG("node event!\n"); 43 | PostQueuedCompletionStatus(_loop->iocp, bytes, key, overlapped); 44 | } 45 | 46 | return ret; 47 | } 48 | -------------------------------------------------------------------------------- /src/arch/darwin/timer.mm: -------------------------------------------------------------------------------- 1 | #include "timer.h" 2 | #include "nbind/api.h" 3 | #import 4 | 5 | TimeoutHandle *setTimeout(nbind::cbFunction &cb, unsigned int timeout) { 6 | nbind::cbFunction *callbackJs = new nbind::cbFunction(cb); 7 | TimeoutHandle *timeoutHandle = new TimeoutHandle(callbackJs); 8 | timeoutHandle->handle = 9 | [NSTimer scheduledTimerWithTimeInterval:timeout / 1000.0 10 | repeats:NO 11 | block:^(NSTimer *timer) { 12 | CALL_JSCB(timeoutHandle); 13 | timeoutHandle->destroy(); 14 | }]; 15 | return timeoutHandle; 16 | } 17 | 18 | void clearTimeout(TimeoutHandle *timeoutHandle) { 19 | NSTimer *handle = (NSTimer *)timeoutHandle->handle; 20 | [handle invalidate]; 21 | timeoutHandle->destroy(); 22 | } 23 | 24 | TimeoutHandle *setInterval(nbind::cbFunction &cb, unsigned int timeout) { 25 | nbind::cbFunction *callbackJs = new nbind::cbFunction(cb); 26 | TimeoutHandle *timeoutHandle = new TimeoutHandle(callbackJs); 27 | timeoutHandle->handle = 28 | [NSTimer scheduledTimerWithTimeInterval:timeout / 1000.0 29 | repeats:YES 30 | block:^(NSTimer *timer) { 31 | CALL_JSCB(timeoutHandle); 32 | }]; 33 | return timeoutHandle; 34 | } 35 | 36 | void clearInterval(TimeoutHandle *timeoutHandle) { 37 | NSTimer *handle = (NSTimer *)timeoutHandle->handle; 38 | [handle invalidate]; 39 | timeoutHandle->destroy(); 40 | } 41 | -------------------------------------------------------------------------------- /src/UiSlider.cc: -------------------------------------------------------------------------------- 1 | #include "nbind/api.h" 2 | #include "control.h" 3 | #include "ui.h" 4 | 5 | class UiSlider : public UiControl { 6 | DEFINE_EVENT(onChanged) 7 | 8 | public: 9 | UiSlider(int min, int max); 10 | UiSlider(); 11 | int getValue(); 12 | void setValue(int value); 13 | ~UiSlider(); 14 | void onDestroy(uiControl *control) override; 15 | }; 16 | 17 | UiSlider::~UiSlider() { 18 | // printf("UiSlider %p destroyed with wrapper %p.\n", getHandle(), 19 | // this); 20 | } 21 | 22 | void UiSlider::onDestroy(uiControl *control) { 23 | /* 24 | freeing event callbacks to allow JS to garbage collect this class 25 | when there are no references to it left in JS code. 26 | */ 27 | DISPOSE_EVENT(onChanged); 28 | } 29 | 30 | UiSlider::UiSlider(int min, int max) 31 | : UiControl((uiControl *)uiNewSlider(min, max)) {} 32 | 33 | UiSlider::UiSlider() : UiControl((uiControl *)uiNewSlider(0, 100)) {} 34 | 35 | int UiSlider::getValue() { 36 | return uiSliderValue((uiSlider *)getHandle()); 37 | } 38 | 39 | void UiSlider::setValue(int value) { 40 | uiSliderSetValue((uiSlider *)getHandle(), value); 41 | if (onChangedCallback != NULL) { 42 | (*onChangedCallback)(); 43 | } 44 | } 45 | 46 | IMPLEMENT_EVENT(UiSlider, uiSlider, onChanged, uiSliderOnChanged) 47 | 48 | NBIND_CLASS(UiSlider) { 49 | inherit(UiControl); 50 | construct(); 51 | construct<>(); 52 | getset(getValue, setValue); 53 | method(getValue); 54 | method(setValue); 55 | method(onChanged); 56 | } 57 | -------------------------------------------------------------------------------- /src/UiSpinbox.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "nbind/api.h" 3 | #include "control.h" 4 | #include "ui.h" 5 | 6 | class UiSpinbox : public UiControl { 7 | public: 8 | DEFINE_EVENT(onChanged) 9 | 10 | UiSpinbox(int min, int max); 11 | UiSpinbox(); 12 | int getValue(); 13 | void setValue(int value); 14 | ~UiSpinbox(); 15 | void onDestroy(uiControl *control) override; 16 | }; 17 | 18 | UiSpinbox::~UiSpinbox() { 19 | // printf("UiSpinbox %p destroyed with wrapper %p.\n", getHandle(), this); 20 | } 21 | 22 | void UiSpinbox::onDestroy(uiControl *control) { 23 | /* 24 | freeing event callbacks to allow JS to garbage collect this class 25 | when there are no references to it left in JS code. 26 | */ 27 | DISPOSE_EVENT(onChanged); 28 | } 29 | 30 | UiSpinbox::UiSpinbox(int min, int max) 31 | : UiControl((uiControl *)uiNewSpinbox(min, max)) {} 32 | 33 | UiSpinbox::UiSpinbox() : UiControl((uiControl *)uiNewSpinbox(0, 100)) {} 34 | 35 | int UiSpinbox::getValue() { 36 | return uiSpinboxValue((uiSpinbox *)getHandle()); 37 | } 38 | 39 | void UiSpinbox::setValue(int value) { 40 | uiSpinboxSetValue((uiSpinbox *)getHandle(), value); 41 | if (onChangedCallback != nullptr) { 42 | (*onChangedCallback)(); 43 | } 44 | } 45 | 46 | IMPLEMENT_EVENT(UiSpinbox, uiSpinbox, onChanged, uiSpinboxOnChanged) 47 | 48 | NBIND_CLASS(UiSpinbox) { 49 | inherit(UiControl); 50 | construct(); 51 | construct<>(); 52 | getset(getValue, setValue); 53 | method(getValue); 54 | method(setValue); 55 | method(onChanged); 56 | } 57 | -------------------------------------------------------------------------------- /src/UiButton.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "nbind/api.h" 3 | #include "control.h" 4 | #include "ui.h" 5 | 6 | class UiButton : public UiControl { 7 | DEFINE_EVENT(onClicked) 8 | 9 | public: 10 | UiButton(std::string text); 11 | UiButton(); 12 | void setText(std::string text); 13 | std::string getText(); 14 | ~UiButton(); 15 | void onDestroy(uiControl *control) override; 16 | }; 17 | 18 | void UiButton::onDestroy(uiControl *control) { 19 | /* 20 | freeing event callbacks to allow JS to garbage collect this class 21 | when there are no references to it left in JS code. 22 | */ 23 | DISPOSE_EVENT(onClicked); 24 | } 25 | 26 | UiButton::~UiButton() { 27 | // printf("UiButton %p destroyed with wrapper %p.\n", getHandle(), this); 28 | } 29 | 30 | UiButton::UiButton(std::string text) 31 | : UiControl(uiControl(uiNewButton(text.c_str()))) {} 32 | 33 | UiButton::UiButton() : UiControl(uiControl(uiNewButton(""))) {} 34 | 35 | void UiButton::setText(std::string text) { 36 | uiButtonSetText(uiButton(getHandle()), text.c_str()); 37 | } 38 | 39 | std::string UiButton::getText() { 40 | char *char_ptr = uiButtonText(uiButton(getHandle())); 41 | std::string s(char_ptr); 42 | uiFreeText(char_ptr); 43 | return s; 44 | } 45 | 46 | IMPLEMENT_EVENT(UiButton, uiButton, onClicked, uiButtonOnClicked) 47 | 48 | NBIND_CLASS(UiButton) { 49 | inherit(UiControl); 50 | construct(); 51 | construct<>(); 52 | getset(getText, setText); 53 | method(getText); 54 | method(setText); 55 | method(onClicked); 56 | } 57 | -------------------------------------------------------------------------------- /examples/check-memory.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const libui = require('..'); 3 | const humanize = require('humanize'); 4 | const procStats = require('proc-stats'); 5 | 6 | function openBigWindow() { 7 | const win = new libui.UiWindow('Forms window', 80, 60, false); 8 | win.margined = 1; 9 | win.onClosing(() => { 10 | win.close(); 11 | }); 12 | 13 | const vBox = new libui.UiVerticalBox(); 14 | vBox.padded = true; 15 | 16 | const entries = []; 17 | for (let i = 0; i < 300; i++) { 18 | entries[i] = new libui.UiEntry(); 19 | entries[i].text = i; 20 | vBox.append(entries[i], 1); 21 | } 22 | 23 | win.setChild(vBox); 24 | win.show(); 25 | } 26 | 27 | const winCheckMem = new libui.UiWindow('Memory', 200, 100, true); 28 | const label = new libui.UiLabel(); 29 | const btn = new libui.UiButton(); 30 | btn.text = 'Open'; 31 | btn.onClicked(openBigWindow); 32 | const vBox2 = new libui.UiVerticalBox(); 33 | vBox2.padded = true; 34 | 35 | vBox2.append(label, true); 36 | vBox2.append(btn, false); 37 | 38 | winCheckMem.setChild(vBox2); 39 | winCheckMem.show(); 40 | 41 | const interval = setInterval(() => { 42 | procStats.stats((err, result) => { 43 | if (err) { 44 | label.text = err.message; 45 | } else { 46 | const text = ` 47 | Memory: ${humanize.filesize(result.memory)} 48 | Heap: ${humanize.filesize(result.memoryInfo.heapUsed)} 49 | CPU: ${result.cpu} % 50 | `; 51 | label.text = text; 52 | } 53 | }); 54 | }, 1000); 55 | 56 | winCheckMem.onClosing(() => { 57 | clearInterval(interval); 58 | libui.stopLoop(); 59 | }); 60 | 61 | libui.startLoop(); 62 | -------------------------------------------------------------------------------- /src/UiCombobox.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "nbind/api.h" 3 | #include "control.h" 4 | #include "ui.h" 5 | 6 | class UiCombobox : public UiControl { 7 | DEFINE_EVENT(onSelected) 8 | 9 | public: 10 | UiCombobox(); 11 | 12 | void append(std::string text); 13 | int getSelected(); 14 | void setSelected(int n); 15 | ~UiCombobox(); 16 | void onDestroy(uiControl *control) override; 17 | }; 18 | 19 | void UiCombobox::onDestroy(uiControl *control) { 20 | /* 21 | freeing event callbacks to allow JS to garbage collect this class 22 | when there are no references to it left in JS code. 23 | */ 24 | DISPOSE_EVENT(onSelected); 25 | } 26 | 27 | UiCombobox::~UiCombobox() { 28 | // printf("UiCombobox %p destroyed with wrapper %p.\n", getHandle(), this); 29 | } 30 | 31 | UiCombobox::UiCombobox() : UiControl((uiControl *)uiNewCombobox()) {} 32 | 33 | IMPLEMENT_EVENT(UiCombobox, uiCombobox, onSelected, uiComboboxOnSelected) 34 | 35 | void UiCombobox::append(std::string text) { 36 | uiComboboxAppend((uiCombobox *)getHandle(), text.c_str()); 37 | } 38 | 39 | int UiCombobox::getSelected() { 40 | return uiComboboxSelected((uiCombobox *)getHandle()); 41 | } 42 | 43 | void UiCombobox::setSelected(int n) { 44 | uiComboboxSetSelected((uiCombobox *)getHandle(), n); 45 | if (onSelectedCallback != NULL) { 46 | (*onSelectedCallback)(); 47 | } 48 | } 49 | 50 | NBIND_CLASS(UiCombobox) { 51 | inherit(UiControl); 52 | construct<>(); 53 | method(append); 54 | getset(getSelected, setSelected); 55 | method(getSelected); 56 | method(setSelected); 57 | method(onSelected); 58 | } 59 | -------------------------------------------------------------------------------- /src/UiColorButton.cc: -------------------------------------------------------------------------------- 1 | #include "nbind/api.h" 2 | #include "control.h" 3 | #include "ui.h" 4 | #include "values.h" 5 | 6 | class UiColorButton : public UiControl { 7 | DEFINE_EVENT(onChanged) 8 | 9 | public: 10 | UiColorButton(); 11 | Color getColor(); 12 | void setColor(Color value); 13 | ~UiColorButton(); 14 | void onDestroy(uiControl *control) override; 15 | }; 16 | 17 | void UiColorButton::onDestroy(uiControl *control) { 18 | /* 19 | freeing event callbacks to allow JS to garbage collect this class 20 | when there are no references to it left in JS code. 21 | */ 22 | DISPOSE_EVENT(onChanged); 23 | } 24 | 25 | UiColorButton::~UiColorButton() { 26 | // printf("UiColorButton %p destroyed with wrapper %p.\n", getHandle(), 27 | // this); 28 | } 29 | 30 | UiColorButton::UiColorButton() : UiControl((uiControl *)uiNewColorButton()) {} 31 | 32 | IMPLEMENT_EVENT(UiColorButton, uiColorButton, onChanged, uiColorButtonOnChanged) 33 | 34 | void UiColorButton::setColor(Color color) { 35 | uiColorButtonSetColor((uiColorButton *)getHandle(), color.getR(), 36 | color.getG(), color.getB(), color.getA()); 37 | if (onChangedCallback != NULL) { 38 | (*onChangedCallback)(); 39 | } 40 | } 41 | 42 | Color UiColorButton::getColor() { 43 | double r = 0.0; 44 | double g = 0.0; 45 | double b = 0.0; 46 | double a = 0.0; 47 | 48 | uiColorButtonColor((uiColorButton *)getHandle(), &r, &g, &b, &a); 49 | 50 | return Color(r, g, b, a); 51 | } 52 | 53 | NBIND_CLASS(UiColorButton) { 54 | inherit(UiControl); 55 | construct<>(); 56 | method(setColor); 57 | method(getColor); 58 | method(onChanged); 59 | getset(getColor, setColor); 60 | } 61 | -------------------------------------------------------------------------------- /src/Font/FontDescriptor.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "area.h" 3 | #include "ui.h" 4 | 5 | // needed because of UiFontButton::getFont 6 | FontDescriptor::FontDescriptor(FontDescriptor &&other) { 7 | d = other.d; 8 | buttonCleanup = other.buttonCleanup; 9 | other.d = nullptr; 10 | } 11 | 12 | FontDescriptor::FontDescriptor(uiFontDescriptor *desc) { 13 | d = desc; 14 | buttonCleanup = 1; 15 | } 16 | 17 | FontDescriptor::FontDescriptor(const char *family, double size, int weight, 18 | int italic, int stretch) { 19 | d = new uiFontDescriptor(); 20 | 21 | d->Family = new char[std::strlen(family) + 1]; 22 | std::strcpy(d->Family, family); 23 | d->Size = size; 24 | d->Weight = weight; 25 | d->Italic = italic; 26 | d->Stretch = stretch; 27 | } 28 | 29 | FontDescriptor::~FontDescriptor() { 30 | if (d != nullptr) { 31 | if (buttonCleanup) { 32 | uiFreeFontButtonFont(d); 33 | } else { 34 | delete[] d->Family; 35 | } 36 | delete d; 37 | } 38 | } 39 | 40 | char *FontDescriptor::getFamily() { 41 | return d->Family; 42 | } 43 | 44 | double FontDescriptor::getSize() { 45 | return d->Size; 46 | } 47 | 48 | int FontDescriptor::getWeight() { 49 | return d->Weight; 50 | } 51 | 52 | int FontDescriptor::getItalic() { 53 | return d->Italic; 54 | } 55 | 56 | int FontDescriptor::getStretch() { 57 | return d->Stretch; 58 | } 59 | 60 | uiFontDescriptor *FontDescriptor::getHandle() { 61 | return d; 62 | } 63 | 64 | NBIND_CLASS(FontDescriptor) { 65 | construct(); 66 | method(getFamily); 67 | method(getSize); 68 | method(getWeight); 69 | method(getItalic); 70 | method(getStretch); 71 | } 72 | -------------------------------------------------------------------------------- /src/UiRadioButtons.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "nbind/api.h" 3 | #include "control.h" 4 | #include "ui.h" 5 | 6 | class UiRadioButtons : public UiControl { 7 | DEFINE_EVENT(onSelected) 8 | 9 | public: 10 | UiRadioButtons(); 11 | void append(std::string text); 12 | int getSelected(); 13 | void setSelected(int n); 14 | 15 | ~UiRadioButtons(); 16 | void onDestroy(uiControl *control) override; 17 | }; 18 | 19 | UiRadioButtons::~UiRadioButtons() { 20 | // printf("UiRadioButtons %p destroyed with wrapper %p.\n", getHandle(), 21 | // this); 22 | } 23 | 24 | void UiRadioButtons::onDestroy(uiControl *control) { 25 | /* 26 | freeing event callbacks to allow JS to garbage collect this class 27 | when there are no references to it left in JS code. 28 | */ 29 | DISPOSE_EVENT(onSelected); 30 | } 31 | 32 | UiRadioButtons::UiRadioButtons() 33 | : UiControl((uiControl *)uiNewRadioButtons()) {} 34 | 35 | IMPLEMENT_EVENT(UiRadioButtons, uiRadioButtons, onSelected, 36 | uiRadioButtonsOnSelected) 37 | 38 | int UiRadioButtons::getSelected() { 39 | return uiRadioButtonsSelected((uiRadioButtons *)getHandle()); 40 | } 41 | 42 | void UiRadioButtons::setSelected(int n) { 43 | uiRadioButtonsSetSelected((uiRadioButtons *)getHandle(), n); 44 | if (onSelectedCallback != NULL) { 45 | (*onSelectedCallback)(); 46 | } 47 | } 48 | 49 | void UiRadioButtons::append(std::string text) { 50 | uiRadioButtonsAppend(uiRadioButtons(getHandle()), text.c_str()); 51 | } 52 | 53 | NBIND_CLASS(UiRadioButtons) { 54 | inherit(UiControl); 55 | construct<>(); 56 | method(append); 57 | getset(getSelected, setSelected); 58 | method(getSelected); 59 | method(setSelected); 60 | method(onSelected); 61 | } 62 | -------------------------------------------------------------------------------- /src/UiArea/UiArea.cc: -------------------------------------------------------------------------------- 1 | #include "area.h" 2 | #include "control.h" 3 | #include "ui.h" 4 | 5 | void UiArea::setSize(int width, int height) { 6 | uiAreaSetSize((uiArea *)getHandle(), width, height); 7 | } 8 | 9 | void UiArea::queueRedrawAll() { 10 | uiAreaQueueRedrawAll((uiArea *)getHandle()); 11 | } 12 | 13 | void UiArea::scrollTo(double x, double y, double width, double height) { 14 | uiAreaScrollTo((uiArea *)getHandle(), x, y, width, height); 15 | } 16 | 17 | UiArea::UiArea(nbind::cbFunction &drawCb, nbind::cbFunction &mouseEventCb, 18 | nbind::cbFunction &mouseCrossedCb, 19 | nbind::cbFunction &dragBrokenCb, nbind::cbFunction &keyEventCb) 20 | : UiControl( 21 | (uiControl *)uiNewArea((uiAreaHandler *)UiAreaHandlerFactory::build( 22 | drawCb, mouseEventCb, mouseCrossedCb, dragBrokenCb, 23 | keyEventCb))) {} 24 | 25 | UiArea::UiArea(nbind::cbFunction &drawCb, nbind::cbFunction &mouseEventCb, 26 | nbind::cbFunction &mouseCrossedCb, 27 | nbind::cbFunction &dragBrokenCb, nbind::cbFunction &keyEventCb, 28 | int width, int height) 29 | : UiControl((uiControl *)uiNewScrollingArea( 30 | (uiAreaHandler *)UiAreaHandlerFactory::build( 31 | drawCb, mouseEventCb, mouseCrossedCb, dragBrokenCb, keyEventCb), 32 | width, height)) {} 33 | 34 | #include "nbind/api.h" 35 | 36 | NBIND_CLASS(UiArea) { 37 | inherit(UiControl); 38 | construct(); 40 | construct(); 42 | method(setSize); 43 | method(queueRedrawAll); 44 | method(scrollTo); 45 | } 46 | -------------------------------------------------------------------------------- /docs/containers.md: -------------------------------------------------------------------------------- 1 | # Container widgets 2 | 3 | `libui-node` provide various widgets that could contains children and that layout them using different strategies. 4 | 5 | * [UiWindow](window.md) - A OS native window that contains only one child. 6 | * [UiForm](form.md) - organize children as labeled fields. 7 | * [UiGrid](grid.md) - allow to specify size and position of each children. 8 | * [UiVerticalBox](verticalbox.md) - stack its chidren vertically. 9 | * [UiHorizontalBox](horizontalbox.md) - stack its chidren horizontally. 10 | * [UiTab](tab.md) - show each chidren in a separate tab. 11 | * [UiGroup](group.md) - provide a caption and visually group it's child. 12 | 13 | 14 | There are actually some inconsistency between container implementation, that will be resolved in future version of `libui`. 15 | 16 | They also share many concept: 17 | 18 | ### margined 19 | 20 | A container with margined property set to `true` will display an empty border around its content area. 21 | 22 | ### padded 23 | 24 | A container with padded property set to `true` will separate its children with an increased amount of vertical and/or horizontal space. 25 | 26 | ### stretchy 27 | 28 | A widget appended to its container with `stretchy` argument `true` will increase its size when parent size change. 29 | 30 | ### append 31 | 32 | Append method allows to insert children as last one of the container. 33 | 34 | ### insertAt 35 | 36 | `insertAt` method allows to insert children in specified position within the container. 37 | 38 | ### deleteAt 39 | 40 | `delete` method allows to remove children at specified position within the container. 41 | 42 | ### setChild 43 | 44 | `setChild` method set the child widget of containers that contains only one (group, window). 45 | -------------------------------------------------------------------------------- /docs/fontbutton.md: -------------------------------------------------------------------------------- 1 | 2 | # FontButton 3 | 4 | > A button that opens a font chooser. 5 | 6 | ![UiFontButton example](media/UiFontButton.png) 7 | 8 | ```js 9 | var libui = require('libui'); 10 | 11 | var win = new libui.UiWindow('UiFontButton example', 640, 480, true); 12 | 13 | var widget = new libui.UiFontButton(); 14 | win.setChild(widget); 15 | 16 | win.onClosing(function () { 17 | win.close(); 18 | libui.stopLoop(); 19 | }); 20 | 21 | win.show(); 22 | 23 | libui.startLoop(); 24 | 25 | ``` 26 | 27 | --- 28 | 29 | # Constructor 30 | 31 | > new libui.UiFontButton() 32 | 33 | Create a new UiFontButton object. 34 | 35 | --- 36 | 37 | # Properties 38 | 39 | See [properties implementation](properties.md) for generic details on how properties are implemented. 40 | 41 | 42 | ### font: FontDescriptor 43 | 44 | Return or set the currently selected font (see [FontDescriptor](attributedstring.md#fontdescriptor) 45 | 46 | 47 | 48 | 49 | --- 50 | 51 | # Methods 52 | 53 | 54 | ## destroy 55 | 56 | Destroy and free the control. 57 | 58 | 59 | 60 | 61 | ## setParent 62 | 63 | Change the parent of the control 64 | 65 | 66 | **Arguments** 67 | 68 | * parent: UiControl - the new parent of the widget or null to detach it. 69 | 70 | 71 | 72 | ## toplevel 73 | 74 | Return whether the control is a top level one or not. 75 | 76 | 77 | 78 | 79 | 80 | ## getFont 81 | 82 | Return the value of property `font` 83 | 84 | 85 | 86 | --- 87 | 88 | # Events 89 | 90 | See [events implementation](events.md) for generic details on how events are implemented. 91 | 92 | 93 | ### onChanged 94 | 95 | Emitted whenever property `font` change. 96 | 97 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /src/UiArea/UiAreaHandler.cc: -------------------------------------------------------------------------------- 1 | #include "area.h" 2 | #include "ui.h" 3 | 4 | void Draw(UiAreaHandler *self, uiArea *area, uiAreaDrawParams *params) { 5 | UiAreaDrawParams *pp = new UiAreaDrawParams(params); 6 | (*self->draw)(controlsMap[uiControl(area)], pp); 7 | } 8 | 9 | void MouseEvent(UiAreaHandler *self, uiArea *area, uiAreaMouseEvent *event) { 10 | UiAreaMouseEvent *ev = new UiAreaMouseEvent(event); 11 | (*(self->mouseEvent))(controlsMap[uiControl(area)], ev); 12 | } 13 | 14 | void MouseCrossed(UiAreaHandler *self, uiArea *area, int left) { 15 | (*(self->mouseCrossed))(controlsMap[uiControl(area)], left); 16 | } 17 | 18 | void DragBroken(UiAreaHandler *self, uiArea *area) { 19 | (*(self->dragBroken))(controlsMap[uiControl(area)]); 20 | } 21 | 22 | int KeyEvent(UiAreaHandler *self, uiArea *area, uiAreaKeyEvent *event) { 23 | UiAreaKeyEvent *ev = new UiAreaKeyEvent(event); 24 | return (self->keyEvent)->call(controlsMap[uiControl(area)], ev); 25 | } 26 | 27 | UiAreaHandler *UiAreaHandlerFactory::build(nbind::cbFunction &drawCb, 28 | nbind::cbFunction &mouseEventCb, 29 | nbind::cbFunction &mouseCrossedCb, 30 | nbind::cbFunction &dragBrokenCb, 31 | nbind::cbFunction &keyEventCb) { 32 | UiAreaHandler *handler = new UiAreaHandler(); 33 | handler->draw = new nbind::cbFunction(drawCb); 34 | handler->mouseEvent = new nbind::cbFunction(mouseEventCb); 35 | handler->mouseCrossed = new nbind::cbFunction(mouseCrossedCb); 36 | handler->dragBroken = new nbind::cbFunction(dragBrokenCb); 37 | handler->keyEvent = new nbind::cbFunction(keyEventCb); 38 | 39 | handler->Draw = Draw; 40 | handler->MouseEvent = MouseEvent; 41 | handler->MouseCrossed = MouseCrossed; 42 | handler->DragBroken = DragBroken; 43 | handler->KeyEvent = KeyEvent; 44 | 45 | return handler; 46 | } 47 | -------------------------------------------------------------------------------- /src/UiArea/UiDrawPath.cc: -------------------------------------------------------------------------------- 1 | #include "area.h" 2 | #include "ui.h" 3 | 4 | UiDrawPath::UiDrawPath(int fillMode) { 5 | handle = uiDrawNewPath(fillMode); 6 | } 7 | 8 | void UiDrawPath::freePath() { 9 | uiDrawFreePath(handle); 10 | } 11 | 12 | void UiDrawPath::newFigure(double x, double y) { 13 | uiDrawPathNewFigure(handle, x, y); 14 | } 15 | 16 | void UiDrawPath::newFigureWithArc(double xCenter, double yCenter, double radius, 17 | double startAngle, double sweep, 18 | int negative) { 19 | uiDrawPathNewFigureWithArc(handle, xCenter, yCenter, radius, startAngle, 20 | sweep, negative); 21 | } 22 | 23 | void UiDrawPath::lineTo(double x, double y) { 24 | uiDrawPathLineTo(handle, x, y); 25 | } 26 | 27 | void UiDrawPath::arcTo(double xCenter, double yCenter, double radius, 28 | double startAngle, double sweep, int negative) { 29 | uiDrawPathArcTo(handle, xCenter, yCenter, radius, startAngle, sweep, 30 | negative); 31 | } 32 | 33 | void UiDrawPath::bezierTo(double c1x, double c1y, double c2x, double c2y, 34 | double endX, double endY) { 35 | uiDrawPathBezierTo(handle, c1x, c1y, c2x, c2y, endX, endY); 36 | } 37 | 38 | void UiDrawPath::closeFigure() { 39 | uiDrawPathCloseFigure(handle); 40 | } 41 | 42 | void UiDrawPath::addRectangle(double x, double y, double width, double height) { 43 | uiDrawPathAddRectangle(handle, x, y, width, height); 44 | } 45 | 46 | void UiDrawPath::end() { 47 | uiDrawPathEnd(handle); 48 | } 49 | 50 | uiDrawPath *UiDrawPath::getHandle() { 51 | return handle; 52 | } 53 | 54 | NBIND_CLASS(UiDrawPath) { 55 | construct(); 56 | method(freePath); 57 | method(newFigure); 58 | method(newFigureWithArc); 59 | method(lineTo); 60 | method(arcTo); 61 | method(bezierTo); 62 | method(closeFigure); 63 | method(addRectangle); 64 | method(end); 65 | } 66 | -------------------------------------------------------------------------------- /src/UiForm.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "ui.h" 3 | 4 | #include "nbind/api.h" 5 | #include "control.h" 6 | 7 | class UiForm : public UiControl { 8 | public: 9 | UiForm(); 10 | void append(std::string label, std::shared_ptr c, bool stretchy); 11 | void deleteAt(int index); 12 | bool getPadded(); 13 | void setPadded(bool padded); 14 | ~UiForm(); 15 | void onDestroy(uiControl *control) override; 16 | 17 | private: 18 | // this hold references to children controls 19 | // to avoid them being garbage collected 20 | // until not destroyed. 21 | std::vector> children; 22 | }; 23 | UiForm::~UiForm() { 24 | // printf("UiForm %p destroyed with wrapper %p.\n", getHandle(), this); 25 | } 26 | 27 | void UiForm::onDestroy(uiControl *control) { 28 | /* 29 | freeing children to allow JS to garbage collect their wrapper classes 30 | when there are no references to them left in JS code. 31 | */ 32 | children.clear(); 33 | } 34 | UiForm::UiForm() : UiControl(uiControl(uiNewForm())) {} 35 | 36 | void UiForm::append(std::string label, std::shared_ptr c, 37 | bool stretchy) { 38 | children.push_back(c); 39 | 40 | uiFormAppend(uiForm(getHandle()), label.c_str(), c.get()->getHandle(), 41 | stretchy); 42 | } 43 | 44 | void UiForm::deleteAt(int index) { 45 | children.erase(children.begin() + index); 46 | uiFormDelete(uiForm(getHandle()), index); 47 | } 48 | 49 | bool UiForm::getPadded() { 50 | return uiFormPadded(uiForm(getHandle())); 51 | } 52 | 53 | void UiForm::setPadded(bool padded) { 54 | uiFormSetPadded(uiForm(getHandle()), padded); 55 | } 56 | 57 | NBIND_CLASS(UiForm) { 58 | inherit(UiControl); 59 | construct<>(); 60 | method(append); 61 | method(deleteAt); 62 | method(getPadded); 63 | method(setPadded); 64 | getset(getPadded, setPadded); 65 | } 66 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "libui-node", 3 | "version": "0.2.0", 4 | "description": "Node.js bindings for libui", 5 | "repository": "parro-it/libui-node", 6 | "license": "MIT", 7 | "libui": "alpha3.5-master-002", 8 | "contributors": [ 9 | { 10 | "name": "Andrea Parodi", 11 | "email": "andrea@parro.it" 12 | }, 13 | { 14 | "name": "Niklas Mischkulnig", 15 | "url": "https://github.com/mischnic" 16 | }, 17 | { 18 | "name": "Gustav Hansen", 19 | "url": "https://github.com/kusti8" 20 | }, 21 | { 22 | "name": "Juha Järvi", 23 | "url": "https://github.com/jjrv" 24 | } 25 | ], 26 | "scripts": { 27 | "test": "ava", 28 | "start": "node examples/control-gallery.js", 29 | "start-np": "node examples/node-pad.js", 30 | "start-core": "node examples/core-api.js", 31 | "autogypi": "autogypi", 32 | "node-gyp": "node-gyp", 33 | "install": "libui-download && autogypi && npm run build", 34 | "build": "node-gyp configure build", 35 | "clean": "rm -rf build; rm -rf node_modules;", 36 | "precommit": "check-clang-format \"'npm run lint'\"", 37 | "lint": "clang-format -i --glob='{src/**/*.{h,cc,mm},index.js,examples/**/*.js}'" 38 | }, 39 | "keywords": [ 40 | "libui", 41 | "desktop", 42 | "multiplatform", 43 | "GUI" 44 | ], 45 | "engines": { 46 | "node": ">=4" 47 | }, 48 | "files": [ 49 | "list-sources.js", 50 | "index.js", 51 | "src", 52 | "binding.gyp", 53 | "auto-top.gypi", 54 | "auto.gypi", 55 | "autogypi.json" 56 | ], 57 | "devDependencies": { 58 | "ava": "^0.25.0", 59 | "clang-format": "^1.2.2", 60 | "humanize": "0.0.9", 61 | "husky": "^0.14.3", 62 | "proc-stats": "0.0.4" 63 | }, 64 | "dependencies": { 65 | "@mischnic/async-hooks": "^0.0.4", 66 | "autogypi": "^0.2.2", 67 | "libui-download": "^1.1.0", 68 | "nbind": "^0.3.14", 69 | "node-gyp": "^3.3.1" 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/UiEditableCombobox.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "nbind/api.h" 3 | #include "control.h" 4 | #include "ui.h" 5 | 6 | class UiEditableCombobox : public UiControl { 7 | DEFINE_EVENT(onChanged) 8 | 9 | public: 10 | UiEditableCombobox(); 11 | void append(std::string text); 12 | std::string getText(); 13 | void setText(std::string text); 14 | ~UiEditableCombobox(); 15 | void onDestroy(uiControl *control) override; 16 | }; 17 | 18 | UiEditableCombobox::~UiEditableCombobox() { 19 | // printf("UiEditableCombobox %p destroyed with wrapper %p.\n", getHandle(), 20 | // this); 21 | } 22 | 23 | void UiEditableCombobox::onDestroy(uiControl *control) { 24 | /* 25 | freeing event callbacks to allow JS to garbage collect this class 26 | when there are no references to it left in JS code. 27 | */ 28 | DISPOSE_EVENT(onChanged); 29 | } 30 | 31 | UiEditableCombobox::UiEditableCombobox() 32 | : UiControl(uiControl(uiNewEditableCombobox())) {} 33 | 34 | IMPLEMENT_EVENT(UiEditableCombobox, uiEditableCombobox, onChanged, 35 | uiEditableComboboxOnChanged) 36 | 37 | void UiEditableCombobox::append(std::string text) { 38 | uiEditableComboboxAppend(uiEditableCombobox(getHandle()), text.c_str()); 39 | } 40 | 41 | void UiEditableCombobox::setText(std::string text) { 42 | uiEditableComboboxSetText(uiEditableCombobox(getHandle()), text.c_str()); 43 | if (onChangedCallback != NULL) { 44 | (*onChangedCallback)(); 45 | } 46 | } 47 | 48 | std::string UiEditableCombobox::getText() { 49 | char *char_ptr = uiEditableComboboxText(uiEditableCombobox(getHandle())); 50 | std::string s(char_ptr); 51 | uiFreeText(char_ptr); 52 | return s; 53 | } 54 | 55 | NBIND_CLASS(UiEditableCombobox) { 56 | inherit(UiControl); 57 | method(append); 58 | construct<>(); 59 | getset(getText, setText); 60 | method(getText); 61 | method(setText); 62 | method(onChanged); 63 | } 64 | -------------------------------------------------------------------------------- /docs/colorbutton.md: -------------------------------------------------------------------------------- 1 | 2 | # ColorButton 3 | 4 | > A button that opens a color palette popup. 5 | 6 | ![UiColorButton example](media/UiColorButton.png) 7 | 8 | ```js 9 | var libui = require('libui'); 10 | 11 | var win = new libui.UiWindow('UiColorButton example', 640, 480, true); 12 | 13 | var widget = new libui.UiColorButton(); 14 | win.setChild(widget); 15 | 16 | win.onClosing(function () { 17 | win.close(); 18 | libui.stopLoop(); 19 | }); 20 | 21 | win.show(); 22 | 23 | libui.startLoop(); 24 | 25 | ``` 26 | 27 | --- 28 | 29 | # Constructor 30 | 31 | > new libui.UiColorButton() 32 | 33 | Create a new UiColorButton object. 34 | 35 | --- 36 | 37 | # Properties 38 | 39 | See [properties implementation](properties.md) for generic details on how properties are implemented. 40 | 41 | 42 | ### color: Color 43 | 44 | Return or set the currently selected color 45 | 46 | 47 | 48 | 49 | --- 50 | 51 | # Methods 52 | 53 | 54 | ## destroy 55 | 56 | Destroy and free the control. 57 | 58 | 59 | 60 | 61 | ## setParent 62 | 63 | Change the parent of the control 64 | 65 | 66 | **Arguments** 67 | 68 | * parent: UiControl - the new parent of the widget or null to detach it. 69 | 70 | 71 | 72 | ## toplevel 73 | 74 | Return whether the control is a top level one or not. 75 | 76 | 77 | 78 | 79 | ## setColor 80 | 81 | Set the value of property `color` 82 | 83 | **Arguments** 84 | 85 | * value: Color - The new value for `color` property. 86 | 87 | ## getColor 88 | 89 | Return the value of property `color` 90 | 91 | 92 | 93 | --- 94 | 95 | # Events 96 | 97 | See [events implementation](events.md) for generic details on how events are implemented. 98 | 99 | 100 | ### onChanged 101 | 102 | Emitted whenever property `color` change. 103 | 104 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /src/includes/values.h: -------------------------------------------------------------------------------- 1 | #ifndef UI_VALUES 2 | #define UI_VALUES 1 3 | 4 | #include "nbind/api.h" 5 | 6 | class Point { 7 | private: 8 | int x; 9 | int y; 10 | 11 | public: 12 | Point(const Point &other); 13 | Point(int x, int y); 14 | int getX(); 15 | void setX(int value); 16 | int getY(); 17 | void setY(int value); 18 | void toJS(nbind::cbOutput output); 19 | }; 20 | 21 | class Size { 22 | private: 23 | int w; 24 | int h; 25 | 26 | public: 27 | Size(int w, int h); 28 | int getWidth(); 29 | void setWidth(int value); 30 | int getHeight(); 31 | void setHeight(int value); 32 | void toJS(nbind::cbOutput output); 33 | }; 34 | 35 | class PointDouble { 36 | private: 37 | double x; 38 | double y; 39 | 40 | public: 41 | PointDouble(double x, double y); 42 | PointDouble(const PointDouble &other); 43 | double getX(); 44 | void setX(double value); 45 | double getY(); 46 | void setY(double value); 47 | void toJS(nbind::cbOutput output); 48 | }; 49 | 50 | class SizeDouble { 51 | private: 52 | double w; 53 | double h; 54 | 55 | public: 56 | SizeDouble(double w, double h); 57 | double getWidth(); 58 | void setWidth(double value); 59 | double getHeight(); 60 | void setHeight(double value); 61 | void toJS(nbind::cbOutput output); 62 | }; 63 | 64 | class Color { 65 | private: 66 | double r; 67 | double g; 68 | double b; 69 | double a; 70 | 71 | public: 72 | Color(const Color &other); 73 | Color(double r, double g, double b, double a); 74 | double getR(); 75 | void setR(double value); 76 | double getG(); 77 | void setG(double value); 78 | double getB(); 79 | void setB(double value); 80 | double getA(); 81 | void setA(double value); 82 | void toJS(nbind::cbOutput output); 83 | }; 84 | 85 | // This is included at end of file 86 | // to minimize conflicts with existing 87 | // symbols from other headers. 88 | #include "nbind/nbind.h" 89 | 90 | #endif 91 | -------------------------------------------------------------------------------- /src/arch/win32/timer.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "nbind/api.h" 3 | #include "timer.h" 4 | 5 | static std::map timersMap; 6 | 7 | void killTimer(TimeoutHandle *timeoutHandle) { 8 | KillTimer(NULL, timeoutHandle->handle); 9 | timersMap.erase(timeoutHandle->handle); 10 | timeoutHandle->destroy(); 11 | } 12 | 13 | void CALLBACK win_timeout_cb(HWND hwnd, UINT uMsg, UINT_PTR idEvent, 14 | DWORD dwTime) { 15 | TimeoutHandle *timeoutHandle = timersMap[idEvent]; 16 | CALL_JSCB(timeoutHandle); 17 | killTimer(timeoutHandle); 18 | } 19 | 20 | void CALLBACK win_interval_cb(HWND hwnd, UINT uMsg, UINT_PTR idEvent, 21 | DWORD dwTime) { 22 | TimeoutHandle *timeoutHandle = timersMap[idEvent]; 23 | CALL_JSCB(timeoutHandle); 24 | } 25 | 26 | TimeoutHandle *setTimeout(nbind::cbFunction &cb, unsigned int timeout) { 27 | nbind::cbFunction *callbackJs = new nbind::cbFunction(cb); 28 | TimeoutHandle *timeoutHandle = new TimeoutHandle(callbackJs); 29 | // SetTimer could work with a NULL window. 30 | // https://stackoverflow.com/questions/7531650/can-i-use-a-settimer-api-in-a-console-c-application 31 | timeoutHandle->handle = SetTimer(NULL, NULL, timeout, win_timeout_cb); 32 | timersMap[timeoutHandle->handle] = timeoutHandle; 33 | return timeoutHandle; 34 | } 35 | 36 | void clearTimeout(TimeoutHandle *timeoutHandle) { 37 | if (!timeoutHandle->destroyed) { 38 | killTimer(timeoutHandle); 39 | } 40 | } 41 | 42 | TimeoutHandle *setInterval(nbind::cbFunction &cb, unsigned int timeout) { 43 | nbind::cbFunction *callbackJs = new nbind::cbFunction(cb); 44 | TimeoutHandle *timeoutHandle = new TimeoutHandle(callbackJs); 45 | timeoutHandle->handle = SetTimer(NULL, NULL, timeout, win_interval_cb); 46 | timersMap[timeoutHandle->handle] = timeoutHandle; 47 | return timeoutHandle; 48 | } 49 | 50 | void clearInterval(TimeoutHandle *timeoutHandle) { 51 | killTimer(timeoutHandle); 52 | } 53 | -------------------------------------------------------------------------------- /src/includes/event-loop-windows.h: -------------------------------------------------------------------------------- 1 | #ifndef ui_node_event_loop_windows 2 | #define ui_node_event_loop_windows 1 3 | 4 | #include 5 | 6 | struct _internal_uv_loop_s { 7 | /* User data - use this for whatever. */ 8 | void *data; 9 | /* Loop reference counting. */ 10 | unsigned int active_handles; 11 | void *handle_queue[2]; 12 | void *active_reqs[2]; 13 | /* Internal flag to signal loop stop. */ 14 | unsigned int stop_flag; 15 | /* The loop's I/O completion port */ 16 | void *iocp; 17 | /* The current time according to the event loop. in msecs. 18 | // uint64_t tim 19 | // Tail of a single-linked circular queue of pending reqs. If the queue 20 | // is empty, tail_ is NULL. If there is only one item, 21 | // tail_->next_req == tail_ 22 | void* pending_reqs_tail; 23 | // Head of a single-linked list of closed handles 24 | void* endgame_handles; 25 | // The head of the timers tree 26 | struct uv_timer_tree_s timers; 27 | // Lists of active loop (prepare / check / idle) watchers 28 | uv_prepare_t* prepare_handles; 29 | uv_check_t* check_handles; 30 | uv_idle_t* idle_handles; 31 | // This pointer will refer to the prepare/check/idle handle whose 32 | // callback is scheduled to be called next. This is needed to allow 33 | // safe removal from one of the lists above while that list being 34 | // iterated over. 35 | uv_prepare_t* next_prepare_handle; 36 | uv_check_t* next_check_handle; 37 | uv_idle_t* next_idle_handle; 38 | // This handle holds the peer sockets for the fast variant of uv_poll_t 39 | SOCKET poll_peer_sockets[UV_MSAFD_PROVIDER_COUNT]; 40 | // Counter to keep track of active tcp streams 41 | unsigned int active_tcp_streams; 42 | // Counter to keep track of active udp streams 43 | unsigned int active_udp_streams; 44 | // Counter to started timer 45 | uint64_t timer_counter; 46 | // Threadpool 47 | void* wq[2]; 48 | uv_mutex_t wq_mutex; 49 | uv_async_t wq_async; 50 | */ 51 | }; 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /binding.gyp: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { 4 | "target_name": "nbind", 5 | 'include_dirs': ["<(module_root_dir)/src/includes", "<(module_root_dir)"], 6 | "includes": [ 7 | "auto.gypi" 8 | ], 9 | "conditions": [ 10 | ["OS=='win'", { 11 | "sources": [ 12 | ' 2 | #include "nbind/api.h" 3 | #include "control.h" 4 | #include "ui.h" 5 | 6 | class UiCheckbox : public UiControl { 7 | DEFINE_EVENT(onToggled) 8 | 9 | public: 10 | UiCheckbox(std::string text); 11 | UiCheckbox(); 12 | void setText(std::string text); 13 | std::string getText(); 14 | void setChecked(bool checked); 15 | bool getChecked(); 16 | ~UiCheckbox(); 17 | void onDestroy(uiControl *control) override; 18 | }; 19 | 20 | void UiCheckbox::onDestroy(uiControl *control) { 21 | /* 22 | freeing event callbacks to allow JS to garbage collect this class 23 | when there are no references to it left in JS code. 24 | */ 25 | DISPOSE_EVENT(onToggled); 26 | } 27 | 28 | UiCheckbox::~UiCheckbox() { 29 | // printf("UiCheckbox %p destroyed with wrapper %p.\n", getHandle(), this); 30 | } 31 | 32 | IMPLEMENT_EVENT(UiCheckbox, uiCheckbox, onToggled, uiCheckboxOnToggled) 33 | 34 | UiCheckbox::UiCheckbox(std::string text) 35 | : UiControl(uiControl(uiNewCheckbox(text.c_str()))) {} 36 | UiCheckbox::UiCheckbox() : UiControl(uiControl(uiNewCheckbox(""))) {} 37 | 38 | void UiCheckbox::setText(std::string text) { 39 | uiCheckboxSetText(uiCheckbox(getHandle()), text.c_str()); 40 | } 41 | 42 | std::string UiCheckbox::getText() { 43 | char *char_ptr = uiCheckboxText(uiCheckbox(getHandle())); 44 | std::string s(char_ptr); 45 | uiFreeText(char_ptr); 46 | return s; 47 | } 48 | 49 | void UiCheckbox::setChecked(bool checked) { 50 | uiCheckboxSetChecked(uiCheckbox(getHandle()), checked); 51 | if (onToggledCallback != NULL) { 52 | (*onToggledCallback)(); 53 | } 54 | } 55 | 56 | bool UiCheckbox::getChecked() { 57 | return uiCheckboxChecked(uiCheckbox(getHandle())); 58 | } 59 | 60 | NBIND_CLASS(UiCheckbox) { 61 | inherit(UiControl); 62 | construct(); 63 | construct<>(); 64 | getset(getChecked, setChecked); 65 | getset(getText, setText); 66 | method(getChecked); 67 | method(setChecked); 68 | method(getText); 69 | method(setText); 70 | method(onToggled); 71 | } 72 | -------------------------------------------------------------------------------- /docs/datepicker.md: -------------------------------------------------------------------------------- 1 | 2 | # DatePicker 3 | 4 | > A widgets to edit dates. 5 | 6 | ![UiDatePicker example](media/UiDatePicker.png) 7 | 8 | ```js 9 | var libui = require('libui'); 10 | 11 | var win = new libui.UiWindow('UiDatePicker example', 640, 480, true); 12 | 13 | var widget = new libui.UiDatePicker(); 14 | win.setChild(widget); 15 | 16 | win.onClosing(function () { 17 | win.close(); 18 | libui.stopLoop(); 19 | }); 20 | 21 | win.show(); 22 | 23 | libui.startLoop(); 24 | 25 | ``` 26 | 27 | --- 28 | 29 | # Constructor 30 | 31 | > new libui.UiDatePicker() 32 | 33 | Create a new UiDatePicker object. 34 | 35 | --- 36 | 37 | # Properties 38 | 39 | See [properties implementation](properties.md) for generic details on how properties are implemented. 40 | 41 | 42 | ### visible: Boolean 43 | 44 | Whether the widget should be visible or hidden. 45 | Read write. 46 | Defaults to `true`. 47 | 48 | 49 | 50 | ### enabled: Boolean 51 | 52 | Whether the widget should be enabled or disabled. 53 | Read write. 54 | Defaults to `true`. 55 | 56 | 57 | 58 | 59 | --- 60 | 61 | # Methods 62 | 63 | 64 | ## destroy 65 | 66 | Destroy and free the control. 67 | 68 | 69 | 70 | 71 | ## setParent 72 | 73 | Change the parent of the control 74 | 75 | 76 | **Arguments** 77 | 78 | * parent: UiControl - the new parent of the widget or null to detach it. 79 | 80 | 81 | 82 | ## toplevel 83 | 84 | Return whether the control is a top level one or not. 85 | 86 | 87 | 88 | 89 | ## setVisible 90 | 91 | Set the value of property `visible` 92 | 93 | **Arguments** 94 | 95 | * value: Boolean - The new value for `visible` property. 96 | 97 | ## getVisible 98 | 99 | Return the value of property `visible` 100 | 101 | 102 | 103 | ## setEnabled 104 | 105 | Set the value of property `enabled` 106 | 107 | **Arguments** 108 | 109 | * value: Boolean - The new value for `enabled` property. 110 | 111 | ## getEnabled 112 | 113 | Return the value of property `enabled` 114 | 115 | 116 | 117 | 118 | -------------------------------------------------------------------------------- /docs/timepicker.md: -------------------------------------------------------------------------------- 1 | 2 | # TimePicker 3 | 4 | > A widgets to edit times. 5 | 6 | ![UiTimePicker example](media/UiTimePicker.png) 7 | 8 | ```js 9 | var libui = require('libui'); 10 | 11 | var win = new libui.UiWindow('UiTimePicker example', 640, 480, true); 12 | 13 | var widget = new libui.UiTimePicker(); 14 | win.setChild(widget); 15 | 16 | win.onClosing(function () { 17 | win.close(); 18 | libui.stopLoop(); 19 | }); 20 | 21 | win.show(); 22 | 23 | libui.startLoop(); 24 | 25 | ``` 26 | 27 | --- 28 | 29 | # Constructor 30 | 31 | > new libui.UiTimePicker() 32 | 33 | Create a new UiTimePicker object. 34 | 35 | --- 36 | 37 | # Properties 38 | 39 | See [properties implementation](properties.md) for generic details on how properties are implemented. 40 | 41 | 42 | ### visible: Boolean 43 | 44 | Whether the widget should be visible or hidden. 45 | Read write. 46 | Defaults to `true`. 47 | 48 | 49 | 50 | ### enabled: Boolean 51 | 52 | Whether the widget should be enabled or disabled. 53 | Read write. 54 | Defaults to `true`. 55 | 56 | 57 | 58 | 59 | --- 60 | 61 | # Methods 62 | 63 | 64 | ## destroy 65 | 66 | Destroy and free the control. 67 | 68 | 69 | 70 | 71 | ## setParent 72 | 73 | Change the parent of the control 74 | 75 | 76 | **Arguments** 77 | 78 | * parent: UiControl - the new parent of the widget or null to detach it. 79 | 80 | 81 | 82 | ## toplevel 83 | 84 | Return whether the control is a top level one or not. 85 | 86 | 87 | 88 | 89 | ## setVisible 90 | 91 | Set the value of property `visible` 92 | 93 | **Arguments** 94 | 95 | * value: Boolean - The new value for `visible` property. 96 | 97 | ## getVisible 98 | 99 | Return the value of property `visible` 100 | 101 | 102 | 103 | ## setEnabled 104 | 105 | Set the value of property `enabled` 106 | 107 | **Arguments** 108 | 109 | * value: Boolean - The new value for `enabled` property. 110 | 111 | ## getEnabled 112 | 113 | Return the value of property `enabled` 114 | 115 | 116 | 117 | 118 | -------------------------------------------------------------------------------- /src/UiControl.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "nbind/api.h" 3 | #include "control.h" 4 | #include "ui.h" 5 | 6 | std::map controlsMap; 7 | 8 | uiControl *UiControl::getHandle() { 9 | return handle; 10 | } 11 | 12 | static void _uicontrol_onDestroy(uiControl *control) { 13 | UiControl *wrapper = controlsMap[control]; 14 | wrapper->onDestroy(control); 15 | wrapper->originalDestroy(control); 16 | wrapper->destroyed = true; 17 | controlsMap.erase(control); 18 | } 19 | 20 | void UiControl::onDestroy(uiControl *control) { 21 | // this method should be overriden 22 | // in control classes to perform 23 | // specific cleanup when natove control 24 | // is destroyed by libui 25 | } 26 | 27 | UiControl::~UiControl() { 28 | // printf("Control %p destroyed with wrapper %p.\n", getHandle(), this); 29 | } 30 | 31 | UiControl::UiControl(uiControl *hnd) { 32 | handle = hnd; 33 | originalDestroy = hnd->Destroy; 34 | hnd->Destroy = _uicontrol_onDestroy; 35 | destroyed = false; 36 | controlsMap[hnd] = this; 37 | } 38 | 39 | void UiControl::destroy() { 40 | uiControlDestroy(handle); 41 | } 42 | 43 | void UiControl::setParent(UiControl *parent) { 44 | uiControlSetParent(handle, parent->getHandle()); 45 | } 46 | 47 | bool UiControl::toplevel() { 48 | return uiControlToplevel(handle); 49 | } 50 | 51 | bool UiControl::getVisible() { 52 | return uiControlVisible(handle); 53 | } 54 | 55 | void UiControl::setVisible(bool visible) { 56 | if (visible == 1) { 57 | uiControlShow(handle); 58 | } else { 59 | uiControlHide(handle); 60 | } 61 | } 62 | 63 | bool UiControl::getEnabled() { 64 | return uiControlEnabled(handle); 65 | } 66 | 67 | void UiControl::setEnabled(bool enabled) { 68 | if (enabled == 1) { 69 | uiControlEnable(handle); 70 | } else { 71 | uiControlDisable(handle); 72 | } 73 | } 74 | 75 | NBIND_CLASS(UiControl) { 76 | method(destroy); 77 | method(setParent); 78 | method(toplevel); 79 | method(getVisible); 80 | method(setVisible); 81 | method(getEnabled); 82 | method(setEnabled); 83 | getset(getVisible, setVisible); 84 | getset(getEnabled, setEnabled); 85 | } 86 | -------------------------------------------------------------------------------- /docs/datetimepicker.md: -------------------------------------------------------------------------------- 1 | 2 | # DateTimePicker 3 | 4 | > A widgets to edit date/times. 5 | 6 | ![UiDateTimePicker example](media/UiDateTimePicker.png) 7 | 8 | ```js 9 | var libui = require('libui'); 10 | 11 | var win = new libui.UiWindow('UiDateTimePicker example', 640, 480, true); 12 | 13 | var widget = new libui.UiDateTimePicker(); 14 | win.setChild(widget); 15 | 16 | win.onClosing(function () { 17 | win.close(); 18 | libui.stopLoop(); 19 | }); 20 | 21 | win.show(); 22 | 23 | libui.startLoop(); 24 | 25 | ``` 26 | 27 | --- 28 | 29 | # Constructor 30 | 31 | > new libui.UiDateTimePicker() 32 | 33 | Create a new UiDateTimePicker object. 34 | 35 | --- 36 | 37 | # Properties 38 | 39 | See [properties implementation](properties.md) for generic details on how properties are implemented. 40 | 41 | 42 | ### visible: Boolean 43 | 44 | Whether the widget should be visible or hidden. 45 | Read write. 46 | Defaults to `true`. 47 | 48 | 49 | 50 | ### enabled: Boolean 51 | 52 | Whether the widget should be enabled or disabled. 53 | Read write. 54 | Defaults to `true`. 55 | 56 | 57 | 58 | 59 | --- 60 | 61 | # Methods 62 | 63 | 64 | ## destroy 65 | 66 | Destroy and free the control. 67 | 68 | 69 | 70 | 71 | ## setParent 72 | 73 | Change the parent of the control 74 | 75 | 76 | **Arguments** 77 | 78 | * parent: UiControl - the new parent of the widget or null to detach it. 79 | 80 | 81 | 82 | ## toplevel 83 | 84 | Return whether the control is a top level one or not. 85 | 86 | 87 | 88 | 89 | ## setVisible 90 | 91 | Set the value of property `visible` 92 | 93 | **Arguments** 94 | 95 | * value: Boolean - The new value for `visible` property. 96 | 97 | ## getVisible 98 | 99 | Return the value of property `visible` 100 | 101 | 102 | 103 | ## setEnabled 104 | 105 | Set the value of property `enabled` 106 | 107 | **Arguments** 108 | 109 | * value: Boolean - The new value for `enabled` property. 110 | 111 | ## getEnabled 112 | 113 | Return the value of property `enabled` 114 | 115 | 116 | 117 | 118 | -------------------------------------------------------------------------------- /docs/verticalseparator.md: -------------------------------------------------------------------------------- 1 | 2 | # VerticalSeparator 3 | 4 | > A vertical line to visually separate widgets. 5 | 6 | ![UiVerticalSeparator example](media/UiVerticalSeparator.png) 7 | 8 | ```js 9 | var libui = require('libui'); 10 | 11 | var win = new libui.UiWindow('UiVerticalSeparator example', 640, 480, true); 12 | 13 | var widget = new libui.UiVerticalSeparator(); 14 | win.setChild(widget); 15 | 16 | win.onClosing(function () { 17 | win.close(); 18 | libui.stopLoop(); 19 | }); 20 | 21 | win.show(); 22 | 23 | libui.startLoop(); 24 | 25 | ``` 26 | 27 | --- 28 | 29 | # Constructor 30 | 31 | > new libui.UiVerticalSeparator() 32 | 33 | Create a new UiVerticalSeparator object. 34 | 35 | --- 36 | 37 | # Properties 38 | 39 | See [properties implementation](properties.md) for generic details on how properties are implemented. 40 | 41 | 42 | ### visible: Boolean 43 | 44 | Whether the widget should be visible or hidden. 45 | Read write. 46 | Defaults to `true`. 47 | 48 | 49 | 50 | ### enabled: Boolean 51 | 52 | Whether the widget should be enabled or disabled. 53 | Read write. 54 | Defaults to `true`. 55 | 56 | 57 | 58 | 59 | --- 60 | 61 | # Methods 62 | 63 | 64 | ## destroy 65 | 66 | Destroy and free the control. 67 | 68 | 69 | 70 | 71 | ## setParent 72 | 73 | Change the parent of the control 74 | 75 | 76 | **Arguments** 77 | 78 | * parent: UiControl - the new parent of the widget or null to detach it. 79 | 80 | 81 | 82 | ## toplevel 83 | 84 | Return whether the control is a top level one or not. 85 | 86 | 87 | 88 | 89 | ## setVisible 90 | 91 | Set the value of property `visible` 92 | 93 | **Arguments** 94 | 95 | * value: Boolean - The new value for `visible` property. 96 | 97 | ## getVisible 98 | 99 | Return the value of property `visible` 100 | 101 | 102 | 103 | ## setEnabled 104 | 105 | Set the value of property `enabled` 106 | 107 | **Arguments** 108 | 109 | * value: Boolean - The new value for `enabled` property. 110 | 111 | ## getEnabled 112 | 113 | Return the value of property `enabled` 114 | 115 | 116 | 117 | 118 | -------------------------------------------------------------------------------- /src/Font/OpenTypeFeatures.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "area.h" 3 | #include "ui.h" 4 | 5 | OpenTypeFeatures::OpenTypeFeatures(OpenTypeFeatures &&other) { 6 | f = other.f; 7 | other.f = nullptr; 8 | } 9 | 10 | OpenTypeFeatures::OpenTypeFeatures(uiOpenTypeFeatures *feat) { 11 | f = feat; 12 | } 13 | 14 | OpenTypeFeatures::OpenTypeFeatures() { 15 | f = uiNewOpenTypeFeatures(); 16 | } 17 | 18 | OpenTypeFeatures::~OpenTypeFeatures() { 19 | if (f != nullptr) { 20 | uiFreeOpenTypeFeatures(f); 21 | } 22 | } 23 | 24 | uiOpenTypeFeatures *OpenTypeFeatures::getHandle() { 25 | return f; 26 | } 27 | 28 | OpenTypeFeatures OpenTypeFeatures::clone(OpenTypeFeatures *f2) { 29 | return OpenTypeFeatures(uiOpenTypeFeaturesClone(f2->f)); 30 | } 31 | 32 | void OpenTypeFeatures::add(const char *tag, uint32_t value) { 33 | uiOpenTypeFeaturesAdd(f, tag[0], tag[1], tag[2], tag[3], value); 34 | } 35 | 36 | void OpenTypeFeatures::remove(const char *tag) { 37 | uiOpenTypeFeaturesRemove(f, tag[0], tag[1], tag[2], tag[3]); 38 | } 39 | 40 | std::array OpenTypeFeatures::getInternal(const char *tag) { 41 | unsigned int value = 0; 42 | unsigned int exists = 43 | uiOpenTypeFeaturesGet(f, tag[0], tag[1], tag[2], tag[3], &value); 44 | return std::array{{value, exists}}; 45 | } 46 | 47 | typedef struct { 48 | OpenTypeFeatures *otf; 49 | nbind::cbFunction *cb; 50 | } ForEachData; 51 | 52 | static uiForEach OpenTypeFeatures__forEach(const uiOpenTypeFeatures *otf, 53 | char a, char b, char c, char d, 54 | uint32_t value, void *dat) { 55 | ForEachData *data = (ForEachData *)dat; 56 | const char tag[5] = {a, b, c, d, '\0'}; 57 | 58 | unsigned int v = data->cb->call(data->otf, &tag[0], value); 59 | 60 | return v ? uiForEachStop : uiForEachContinue; 61 | } 62 | 63 | void OpenTypeFeatures::forEach(nbind::cbFunction &cb) { 64 | ForEachData d = {this, &cb}; 65 | uiOpenTypeFeaturesForEach(f, OpenTypeFeatures__forEach, &d); 66 | } 67 | 68 | NBIND_CLASS(OpenTypeFeatures) { 69 | construct<>(); 70 | method(clone); 71 | method(add); 72 | method(remove); 73 | method(getInternal); 74 | method(forEach); 75 | } 76 | -------------------------------------------------------------------------------- /src/UiGroup.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "nbind/api.h" 3 | #include "control.h" 4 | #include "ui.h" 5 | 6 | class UiGroup : public UiControl { 7 | private: 8 | // this hold a reference to child control 9 | // to avoid it being garbage collected 10 | // until not destroyed. 11 | std::shared_ptr child; 12 | 13 | public: 14 | UiGroup(std::string text); 15 | UiGroup(); 16 | ~UiGroup(); 17 | void onDestroy(uiControl *control) override; 18 | void setChild(std::shared_ptr control); 19 | bool getMargined(); 20 | void setMargined(bool margined); 21 | std::string getTitle(); 22 | void setTitle(std::string title); 23 | }; 24 | 25 | UiGroup::~UiGroup() { 26 | // printf("UiGroup %p destroyed with wrapper %p.\n", getHandle(), this); 27 | } 28 | 29 | void UiGroup::onDestroy(uiControl *control) { 30 | /* 31 | freeing children to allow JS to garbage collect their wrapper classes 32 | when there are no references to them left in JS code. 33 | */ 34 | child = nullptr; 35 | } 36 | UiGroup::UiGroup(std::string text) 37 | : UiControl(uiControl(uiNewGroup(text.c_str()))) {} 38 | UiGroup::UiGroup() : UiControl(uiControl(uiNewGroup(""))) {} 39 | 40 | void UiGroup::setChild(std::shared_ptr control) { 41 | child = control; 42 | uiGroupSetChild(uiGroup(getHandle()), control.get()->getHandle()); 43 | } 44 | 45 | bool UiGroup::getMargined() { 46 | return uiGroupMargined(uiGroup(getHandle())); 47 | } 48 | 49 | void UiGroup::setMargined(bool margined) { 50 | uiGroupSetMargined(uiGroup(getHandle()), margined); 51 | } 52 | 53 | std::string UiGroup::getTitle() { 54 | char *char_ptr = uiGroupTitle(uiGroup(getHandle())); 55 | std::string s(char_ptr); 56 | uiFreeText(char_ptr); 57 | return s; 58 | } 59 | 60 | void UiGroup::setTitle(std::string title) { 61 | uiGroupSetTitle(uiGroup(getHandle()), title.c_str()); 62 | } 63 | 64 | NBIND_CLASS(UiGroup) { 65 | inherit(UiControl); 66 | construct(); 67 | construct<>(); 68 | method(setChild); 69 | method(getTitle); 70 | method(setTitle); 71 | method(getMargined); 72 | method(setMargined); 73 | getset(getTitle, setTitle); 74 | getset(getMargined, setMargined); 75 | } 76 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | #### joe made this: https://goel.io/joe 2 | 3 | #####=== SublimeText ===##### 4 | # cache files for sublime text 5 | *.tmlanguage.cache 6 | *.tmPreferences.cache 7 | *.stTheme.cache 8 | 9 | # workspace files are user-specific 10 | *.sublime-workspace 11 | 12 | # project files should be checked into the repository, unless a significant 13 | # proportion of contributors will probably not be using SublimeText 14 | # *.sublime-project 15 | 16 | # sftp configuration file 17 | sftp-config.json 18 | 19 | #####=== Node ===##### 20 | 21 | # Logs 22 | logs 23 | *.log 24 | 25 | # Runtime data 26 | pids 27 | *.pid 28 | *.seed 29 | 30 | # Directory for instrumented libs generated by jscoverage/JSCover 31 | lib-cov 32 | 33 | # Coverage directory used by tools like istanbul 34 | coverage 35 | 36 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 37 | .grunt 38 | 39 | # node-waf configuration 40 | .lock-wscript 41 | 42 | # Compiled binary addons (http://nodejs.org/api/addons.html) 43 | build/Release 44 | 45 | # Dependency directory 46 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git- 47 | node_modules 48 | 49 | # Debug log from npm 50 | npm-debug.log 51 | 52 | #####=== OSX ===##### 53 | .DS_Store 54 | .AppleDouble 55 | .LSOverride 56 | 57 | # Icon must end with two \r 58 | Icon 59 | 60 | 61 | # Thumbnails 62 | ._* 63 | 64 | # Files that might appear on external disk 65 | .Spotlight-V100 66 | .Trashes 67 | 68 | # Directories potentially created on remote AFP share 69 | .AppleDB 70 | .AppleDesktop 71 | Network Trash Folder 72 | Temporary Items 73 | .apdisk 74 | 75 | #####=== Linux ===##### 76 | *~ 77 | 78 | # KDE directory preferences 79 | .directory 80 | 81 | # Linux trash folder which might appear on any partition or disk 82 | .Trash-* 83 | 84 | 85 | build 86 | 87 | *.so 88 | *.so.* 89 | 90 | 91 | *.dylib 92 | 93 | auto*.gypi 94 | _libui 95 | 96 | ui_*.h 97 | ui.h 98 | uitable.h 99 | 100 | *.dylib 101 | *.dll 102 | *.so 103 | nbind.node 104 | *.dll 105 | *.exp 106 | *.lib 107 | -------------------------------------------------------------------------------- /docs/horizontalseparator.md: -------------------------------------------------------------------------------- 1 | 2 | # HorizontalSeparator 3 | 4 | > An horizontal line to visually separate widgets. 5 | 6 | ![UiHorizontalSeparator example](media/UiHorizontalSeparator.png) 7 | 8 | ```js 9 | var libui = require('libui'); 10 | 11 | var win = new libui.UiWindow('UiHorizontalSeparator example', 640, 480, true); 12 | 13 | var widget = new libui.UiHorizontalSeparator(); 14 | win.setChild(widget); 15 | 16 | win.onClosing(function () { 17 | win.close(); 18 | libui.stopLoop(); 19 | }); 20 | 21 | win.show(); 22 | 23 | libui.startLoop(); 24 | 25 | ``` 26 | 27 | --- 28 | 29 | # Constructor 30 | 31 | > new libui.UiHorizontalSeparator() 32 | 33 | Create a new UiHorizontalSeparator object. 34 | 35 | --- 36 | 37 | # Properties 38 | 39 | See [properties implementation](properties.md) for generic details on how properties are implemented. 40 | 41 | 42 | ### visible: Boolean 43 | 44 | Whether the widget should be visible or hidden. 45 | Read write. 46 | Defaults to `true`. 47 | 48 | 49 | 50 | ### enabled: Boolean 51 | 52 | Whether the widget should be enabled or disabled. 53 | Read write. 54 | Defaults to `true`. 55 | 56 | 57 | 58 | 59 | --- 60 | 61 | # Methods 62 | 63 | 64 | ## destroy 65 | 66 | Destroy and free the control. 67 | 68 | 69 | 70 | 71 | ## setParent 72 | 73 | Change the parent of the control 74 | 75 | 76 | **Arguments** 77 | 78 | * parent: UiControl - the new parent of the widget or null to detach it. 79 | 80 | 81 | 82 | ## toplevel 83 | 84 | Return whether the control is a top level one or not. 85 | 86 | 87 | 88 | 89 | ## setVisible 90 | 91 | Set the value of property `visible` 92 | 93 | **Arguments** 94 | 95 | * value: Boolean - The new value for `visible` property. 96 | 97 | ## getVisible 98 | 99 | Return the value of property `visible` 100 | 101 | 102 | 103 | ## setEnabled 104 | 105 | Set the value of property `enabled` 106 | 107 | **Arguments** 108 | 109 | * value: Boolean - The new value for `enabled` property. 110 | 111 | ## getEnabled 112 | 113 | Return the value of property `enabled` 114 | 115 | 116 | 117 | 118 | -------------------------------------------------------------------------------- /src/UiMultilineEntry.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "nbind/api.h" 3 | #include "control.h" 4 | #include "ui.h" 5 | 6 | class UiMultilineEntry : public UiControl { 7 | DEFINE_EVENT(onChanged) 8 | 9 | public: 10 | UiMultilineEntry(); 11 | void setText(std::string text); 12 | std::string getText(); 13 | void setReadOnly(bool readOnly); 14 | bool getReadOnly(); 15 | void append(std::string text); 16 | ~UiMultilineEntry(); 17 | void onDestroy(uiControl *control) override; 18 | }; 19 | 20 | UiMultilineEntry::~UiMultilineEntry() { 21 | // printf("UiMultilineEntry %p destroyed with wrapper %p.\n", getHandle(), 22 | // this); 23 | } 24 | 25 | void UiMultilineEntry::onDestroy(uiControl *control) { 26 | /* 27 | freeing event callbacks to allow JS to garbage collect this class 28 | when there are no references to it left in JS code. 29 | */ 30 | DISPOSE_EVENT(onChanged); 31 | } 32 | UiMultilineEntry::UiMultilineEntry() 33 | : UiControl(uiControl(uiNewNonWrappingMultilineEntry())) {} 34 | 35 | IMPLEMENT_EVENT(UiMultilineEntry, uiMultilineEntry, onChanged, 36 | uiMultilineEntryOnChanged) 37 | 38 | void UiMultilineEntry::setText(std::string text) { 39 | uiMultilineEntrySetText(uiMultilineEntry(getHandle()), text.c_str()); 40 | if (onChangedCallback != NULL) { 41 | (*onChangedCallback)(); 42 | } 43 | } 44 | 45 | std::string UiMultilineEntry::getText() { 46 | char *char_ptr = uiMultilineEntryText(uiMultilineEntry(getHandle())); 47 | std::string s(char_ptr); 48 | uiFreeText(char_ptr); 49 | return s; 50 | } 51 | 52 | void UiMultilineEntry::setReadOnly(bool readOnly) { 53 | uiMultilineEntrySetReadOnly(uiMultilineEntry(getHandle()), readOnly); 54 | } 55 | 56 | bool UiMultilineEntry::getReadOnly() { 57 | return uiMultilineEntryReadOnly(uiMultilineEntry(getHandle())); 58 | } 59 | 60 | void UiMultilineEntry::append(std::string text) { 61 | uiMultilineEntryAppend(uiMultilineEntry(getHandle()), text.c_str()); 62 | } 63 | 64 | NBIND_CLASS(UiMultilineEntry) { 65 | inherit(UiControl); 66 | construct<>(); 67 | getset(getText, setText); 68 | getset(getReadOnly, setReadOnly); 69 | method(getText); 70 | method(setText); 71 | method(getReadOnly); 72 | method(setReadOnly); 73 | method(append); 74 | method(onChanged); 75 | } 76 | -------------------------------------------------------------------------------- /src/UiBox.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "nbind/api.h" 4 | #include "control.h" 5 | #include "ui.h" 6 | 7 | class UiBox : public UiControl { 8 | public: 9 | UiBox(uiControl *hnd); 10 | ~UiBox(); 11 | void onDestroy(uiControl *control) override; 12 | 13 | // this hold references to children controls 14 | // to avoid them being garbage collected 15 | // until not destroyed. 16 | std::vector> children; 17 | 18 | void append(std::shared_ptr, bool stretchy); 19 | void deleteAt(int index); 20 | bool getPadded(); 21 | void setPadded(bool padded); 22 | }; 23 | 24 | class UiVerticalBox : public UiBox { 25 | public: 26 | UiVerticalBox(); 27 | }; 28 | 29 | class UiHorizontalBox : public UiBox { 30 | public: 31 | UiHorizontalBox(); 32 | }; 33 | 34 | UiBox::~UiBox() { 35 | // printf("UiBox %p destroyed with wrapper %p.\n", getHandle(), this); 36 | } 37 | 38 | void UiBox::onDestroy(uiControl *control) { 39 | /* 40 | freeing children to allow JS to garbage collect their wrapper classes 41 | when there are no references to them left in JS code. 42 | */ 43 | children.clear(); 44 | } 45 | UiBox::UiBox(uiControl *control) : UiControl(control) {} 46 | 47 | void UiBox::append(std::shared_ptr control, bool stretchy) { 48 | children.push_back(control); 49 | uiBoxAppend((uiBox *)getHandle(), control->getHandle(), stretchy); 50 | } 51 | 52 | void UiBox::deleteAt(int index) { 53 | children.erase(children.begin() + index); 54 | uiBoxDelete((uiBox *)getHandle(), index); 55 | } 56 | 57 | void UiBox::setPadded(bool padded) { 58 | uiBoxSetPadded((uiBox *)getHandle(), padded); 59 | } 60 | 61 | bool UiBox::getPadded() { 62 | return uiBoxPadded((uiBox *)getHandle()); 63 | } 64 | 65 | UiVerticalBox::UiVerticalBox() : UiBox((uiControl *)uiNewVerticalBox()) {} 66 | 67 | UiHorizontalBox::UiHorizontalBox() : UiBox((uiControl *)uiNewHorizontalBox()) {} 68 | 69 | NBIND_CLASS(UiBox) { 70 | inherit(UiControl); 71 | getset(getPadded, setPadded); 72 | method(getPadded); 73 | method(setPadded); 74 | method(append); 75 | method(deleteAt); 76 | } 77 | 78 | NBIND_CLASS(UiVerticalBox) { 79 | inherit(UiBox); 80 | construct<>(); 81 | } 82 | 83 | NBIND_CLASS(UiHorizontalBox) { 84 | inherit(UiBox); 85 | construct<>(); 86 | } 87 | -------------------------------------------------------------------------------- /src/UiTab.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "nbind/api.h" 3 | #include "control.h" 4 | #include "ui.h" 5 | 6 | class UiTab : public UiControl { 7 | public: 8 | UiTab(); 9 | void append(std::string text, std::shared_ptr child); 10 | void insertAt(std::string name, int before, 11 | std::shared_ptr child); 12 | void deleteAt(int index); 13 | int numPages(); 14 | bool getMargined(int page); 15 | void setMargined(int page, bool margined); 16 | 17 | ~UiTab(); 18 | void onDestroy(uiControl *control) override; 19 | 20 | private: 21 | // this hold references to children controls 22 | // to avoid them being garbage collected 23 | // until not destroyed. 24 | std::vector> children; 25 | }; 26 | 27 | UiTab::~UiTab() { 28 | // printf("UiTab %p destroyed with wrapper %p.\n", getHandle(), this); 29 | } 30 | 31 | void UiTab::onDestroy(uiControl *control) { 32 | /* 33 | freeing children to allow JS to garbage collect their wrapper classes 34 | when there are no references to them left in JS code. 35 | */ 36 | children.clear(); 37 | } 38 | UiTab::UiTab() : UiControl((uiControl *)uiNewTab()) {} 39 | 40 | void UiTab::append(std::string text, std::shared_ptr child) { 41 | children.push_back(child); 42 | uiTabAppend(uiTab(getHandle()), text.c_str(), child.get()->getHandle()); 43 | } 44 | 45 | void UiTab::insertAt(std::string name, int before, 46 | std::shared_ptr child) { 47 | children.insert(children.begin() + before, child); 48 | uiTabInsertAt(uiTab(getHandle()), name.c_str(), before, 49 | child.get()->getHandle()); 50 | } 51 | 52 | void UiTab::deleteAt(int index) { 53 | children.erase(children.begin() + index); 54 | uiTabDelete(uiTab(getHandle()), index); 55 | } 56 | 57 | int UiTab::numPages() { 58 | return uiTabNumPages(uiTab(getHandle())); 59 | } 60 | 61 | bool UiTab::getMargined(int page) { 62 | return uiTabMargined(uiTab(getHandle()), page); 63 | } 64 | 65 | void UiTab::setMargined(int page, bool margined) { 66 | uiTabSetMargined(uiTab(getHandle()), page, margined); 67 | } 68 | 69 | NBIND_CLASS(UiTab) { 70 | inherit(UiControl); 71 | construct<>(); 72 | method(append); 73 | method(numPages); 74 | method(deleteAt); 75 | method(insertAt); 76 | method(getMargined); 77 | method(setMargined); 78 | } 79 | -------------------------------------------------------------------------------- /src/includes/control.h: -------------------------------------------------------------------------------- 1 | #ifndef UI_NODE_CONTROL 2 | #define UI_NODE_CONTROL 1 3 | 4 | #include 5 | #include "ui.h" 6 | 7 | #define DEFINE_EVENT(NAME) \ 8 | private: \ 9 | nbind::cbFunction *NAME##Callback = NULL; \ 10 | \ 11 | public: \ 12 | void NAME(nbind::cbFunction &cb); 13 | 14 | #define IMPLEMENT_EVENT(CLASS, WIDGET, NAME, LIBUI_FUN) \ 15 | static void CLASS##_##NAME(WIDGET *w, void *data) { \ 16 | nbind::cbFunction *cb = (nbind::cbFunction *)data; \ 17 | (*cb)(); \ 18 | } \ 19 | void CLASS::NAME(nbind::cbFunction &cb) { \ 20 | NAME##Callback = new nbind::cbFunction(cb); \ 21 | LIBUI_FUN((WIDGET *)getHandle(), CLASS##_##NAME, NAME##Callback); \ 22 | } 23 | 24 | #define DISPOSE_EVENT(NAME) \ 25 | /*if (NAME##Callback != nullptr) { \ 26 | delete NAME##Callback; \ 27 | NAME##Callback = nullptr; \ 28 | }*/ 29 | 30 | typedef void (*DestroyCb)(uiControl *); 31 | 32 | class UiControl { 33 | private: 34 | uiControl *handle; 35 | 36 | public: 37 | DestroyCb originalDestroy; 38 | bool destroyed; 39 | virtual void onDestroy(uiControl *); 40 | 41 | uiControl *getHandle(); 42 | UiControl(uiControl *hnd); 43 | virtual ~UiControl(); 44 | void destroy(); 45 | void setParent(UiControl *parent); 46 | bool toplevel(); 47 | bool getVisible(); 48 | void setVisible(bool visible); 49 | bool getEnabled(); 50 | void setEnabled(bool enabled); 51 | }; 52 | 53 | extern std::map controlsMap; 54 | 55 | // This is included at end of file 56 | // to minimize conflicts with existing 57 | // symbols from other headers. 58 | #include "nbind/nbind.h" 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /src/UiGrid.cc: -------------------------------------------------------------------------------- 1 | #include "nbind/api.h" 2 | #include "control.h" 3 | #include "ui.h" 4 | 5 | // TODO - document 6 | class UiGrid : public UiControl { 7 | public: 8 | UiGrid(); 9 | bool getPadded(); 10 | void setPadded(bool value); 11 | void append(std::shared_ptr c, int left, int top, int xspan, 12 | int yspan, int hexpand, int halign, int vexpand, int valign); 13 | void insertAt(std::shared_ptr c, UiControl *existing, int at, 14 | int xspan, int yspan, int hexpand, int halign, int vexpand, 15 | int valign); 16 | 17 | ~UiGrid(); 18 | void onDestroy(uiControl *control) override; 19 | 20 | private: 21 | // this hold references to children controls 22 | // to avoid them being garbage collected 23 | // until not destroyed. 24 | std::vector> children; 25 | }; 26 | 27 | UiGrid::~UiGrid() { 28 | // printf("UiGrid %p destroyed with wrapper %p.\n", getHandle(), this); 29 | } 30 | 31 | void UiGrid::onDestroy(uiControl *control) { 32 | /* 33 | freeing children to allow JS to garbage collect their wrapper classes 34 | when there are no references to them left in JS code. 35 | */ 36 | children.clear(); 37 | } 38 | UiGrid::UiGrid() : UiControl((uiControl *)uiNewGrid()) {} 39 | 40 | bool UiGrid::getPadded() { 41 | return uiGridPadded((uiGrid *)getHandle()); 42 | } 43 | 44 | void UiGrid::setPadded(bool value) { 45 | uiGridSetPadded((uiGrid *)getHandle(), value); 46 | } 47 | 48 | void UiGrid::append(std::shared_ptr c, int left, int top, int xspan, 49 | int yspan, int hexpand, int halign, int vexpand, 50 | int valign) { 51 | children.push_back(c); 52 | uiGridAppend((uiGrid *)getHandle(), c.get()->getHandle(), left, top, xspan, 53 | yspan, hexpand, halign, vexpand, valign); 54 | } 55 | 56 | void UiGrid::insertAt(std::shared_ptr c, UiControl *existing, int at, 57 | int xspan, int yspan, int hexpand, int halign, 58 | int vexpand, int valign) { 59 | children.push_back(c); 60 | uiGridInsertAt((uiGrid *)getHandle(), c.get()->getHandle(), 61 | existing->getHandle(), at, xspan, yspan, hexpand, halign, 62 | vexpand, valign); 63 | } 64 | 65 | NBIND_CLASS(UiGrid) { 66 | inherit(UiControl); 67 | construct<>(); 68 | method(append); 69 | method(insertAt); 70 | method(getPadded); 71 | method(setPadded); 72 | getset(getPadded, setPadded); 73 | } 74 | -------------------------------------------------------------------------------- /docs/label.md: -------------------------------------------------------------------------------- 1 | 2 | # Label 3 | 4 | > A static text label. 5 | 6 | ![UiLabel example](media/UiLabel.png) 7 | 8 | ```js 9 | var libui = require('libui'); 10 | 11 | var win = new libui.UiWindow('UiLabel example', 640, 480, true); 12 | 13 | var widget = new libui.UiLabel(); 14 | win.setChild(widget); 15 | 16 | win.onClosing(function () { 17 | win.close(); 18 | libui.stopLoop(); 19 | }); 20 | 21 | win.show(); 22 | 23 | libui.startLoop(); 24 | 25 | ``` 26 | 27 | --- 28 | 29 | # Constructor 30 | 31 | > new libui.UiLabel() 32 | 33 | Create a new UiLabel object. 34 | 35 | --- 36 | 37 | # Properties 38 | 39 | See [properties implementation](properties.md) for generic details on how properties are implemented. 40 | 41 | 42 | ### visible: Boolean 43 | 44 | Whether the widget should be visible or hidden. 45 | Read write. 46 | Defaults to `true`. 47 | 48 | 49 | 50 | ### enabled: Boolean 51 | 52 | Whether the widget should be enabled or disabled. 53 | Read write. 54 | Defaults to `true`. 55 | 56 | 57 | 58 | ### text: String 59 | 60 | The static text of the label. 61 | Read write. 62 | 63 | 64 | 65 | 66 | --- 67 | 68 | # Methods 69 | 70 | 71 | ## destroy 72 | 73 | Destroy and free the control. 74 | 75 | 76 | 77 | 78 | ## setParent 79 | 80 | Change the parent of the control 81 | 82 | 83 | **Arguments** 84 | 85 | * parent: UiControl - the new parent of the widget or null to detach it. 86 | 87 | 88 | 89 | ## toplevel 90 | 91 | Return whether the control is a top level one or not. 92 | 93 | 94 | 95 | 96 | ## setVisible 97 | 98 | Set the value of property `visible` 99 | 100 | **Arguments** 101 | 102 | * value: Boolean - The new value for `visible` property. 103 | 104 | ## getVisible 105 | 106 | Return the value of property `visible` 107 | 108 | 109 | 110 | ## setEnabled 111 | 112 | Set the value of property `enabled` 113 | 114 | **Arguments** 115 | 116 | * value: Boolean - The new value for `enabled` property. 117 | 118 | ## getEnabled 119 | 120 | Return the value of property `enabled` 121 | 122 | 123 | 124 | ## setText 125 | 126 | Set the value of property `text` 127 | 128 | **Arguments** 129 | 130 | * value: String - The new value for `text` property. 131 | 132 | ## getText 133 | 134 | Return the value of property `text` 135 | 136 | 137 | 138 | 139 | -------------------------------------------------------------------------------- /src/UiArea/DrawStrokeParams.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "area.h" 4 | #include "ui.h" 5 | 6 | DrawStrokeParams::DrawStrokeParams() { 7 | sp = new uiDrawStrokeParams(); 8 | } 9 | 10 | DrawStrokeParams::~DrawStrokeParams() { 11 | if (sp->NumDashes > 0) { 12 | delete[] sp->Dashes; 13 | } 14 | delete sp; 15 | } 16 | 17 | int DrawStrokeParams::getCap() { 18 | return sp->Cap; 19 | } 20 | 21 | int DrawStrokeParams::getJoin() { 22 | return sp->Join; 23 | } 24 | 25 | double DrawStrokeParams::getThickness() { 26 | return sp->Thickness; 27 | } 28 | 29 | double DrawStrokeParams::getMiterLimit() { 30 | return sp->MiterLimit; 31 | } 32 | 33 | std::vector DrawStrokeParams::getDashes() { 34 | return std::vector(sp->Dashes, sp->Dashes + sp->NumDashes); 35 | } 36 | 37 | double DrawStrokeParams::getDashPhase() { 38 | return sp->DashPhase; 39 | } 40 | 41 | void DrawStrokeParams::setCap(int value) { 42 | sp->Cap = value; 43 | } 44 | 45 | void DrawStrokeParams::setJoin(int value) { 46 | sp->Join = value; 47 | } 48 | 49 | void DrawStrokeParams::setThickness(double value) { 50 | sp->Thickness = value; 51 | } 52 | 53 | void DrawStrokeParams::setMiterLimit(double value) { 54 | sp->MiterLimit = value; 55 | } 56 | 57 | void DrawStrokeParams::setDashes(std::vector value) { 58 | if (sp->NumDashes > 0) { 59 | delete[] sp->Dashes; 60 | } 61 | 62 | sp->NumDashes = value.size(); 63 | if (sp->NumDashes > 0) { 64 | sp->Dashes = new double[sp->NumDashes]; 65 | 66 | std::copy(value.begin(), value.end(), sp->Dashes); 67 | } 68 | } 69 | 70 | void DrawStrokeParams::setDashPhase(double value) { 71 | sp->DashPhase = value; 72 | } 73 | 74 | uiDrawStrokeParams *DrawStrokeParams::toStruct() { 75 | return sp; 76 | } 77 | 78 | NBIND_CLASS(DrawStrokeParams) { 79 | construct<>(); 80 | 81 | method(getCap); 82 | method(getJoin); 83 | method(getThickness); 84 | method(getMiterLimit); 85 | method(getDashes); 86 | method(getDashPhase); 87 | method(setCap); 88 | method(setJoin); 89 | method(setThickness); 90 | method(setMiterLimit); 91 | method(setDashes); 92 | method(setDashPhase); 93 | getset(getCap, setCap); 94 | getset(getJoin, setJoin); 95 | getset(getThickness, setThickness); 96 | getset(getMiterLimit, setMiterLimit); 97 | getset(getDashes, setDashes); 98 | getset(getDashPhase, setDashPhase); 99 | } 100 | -------------------------------------------------------------------------------- /docs/grid.md: -------------------------------------------------------------------------------- 1 | 2 | # Grid 3 | 4 | > A powerful container that allow to specify size and position of each children. 5 | 6 | ![UiGrid example](media/UiGrid.png) 7 | 8 | ```js 9 | var libui = require('libui'); 10 | 11 | var win = new libui.UiWindow('UiGrid example', 640, 480, true); 12 | 13 | var widget = new libui.UiGrid(); 14 | win.setChild(widget); 15 | 16 | win.onClosing(function () { 17 | win.close(); 18 | libui.stopLoop(); 19 | }); 20 | 21 | win.show(); 22 | 23 | libui.startLoop(); 24 | 25 | ``` 26 | 27 | --- 28 | 29 | # Constructor 30 | 31 | > new libui.UiGrid() 32 | 33 | Create a new UiGrid object. 34 | 35 | --- 36 | 37 | # Properties 38 | 39 | See [properties implementation](properties.md) for generic details on how properties are implemented. 40 | 41 | 42 | ### visible: Boolean 43 | 44 | Whether the widget should be visible or hidden. 45 | Read write. 46 | Defaults to `true`. 47 | 48 | 49 | 50 | ### enabled: Boolean 51 | 52 | Whether the widget should be enabled or disabled. 53 | Read write. 54 | Defaults to `true`. 55 | 56 | 57 | 58 | ### padded: Boolean 59 | 60 | If true, the container insert some space between children. 61 | Defaults to false. 62 | 63 | 64 | 65 | 66 | --- 67 | 68 | # Methods 69 | 70 | 71 | ## destroy 72 | 73 | Destroy and free the control. 74 | 75 | 76 | 77 | 78 | ## setParent 79 | 80 | Change the parent of the control 81 | 82 | 83 | **Arguments** 84 | 85 | * parent: UiControl - the new parent of the widget or null to detach it. 86 | 87 | 88 | 89 | ## toplevel 90 | 91 | Return whether the control is a top level one or not. 92 | 93 | 94 | 95 | 96 | ## setVisible 97 | 98 | Set the value of property `visible` 99 | 100 | **Arguments** 101 | 102 | * value: Boolean - The new value for `visible` property. 103 | 104 | ## getVisible 105 | 106 | Return the value of property `visible` 107 | 108 | 109 | 110 | ## setEnabled 111 | 112 | Set the value of property `enabled` 113 | 114 | **Arguments** 115 | 116 | * value: Boolean - The new value for `enabled` property. 117 | 118 | ## getEnabled 119 | 120 | Return the value of property `enabled` 121 | 122 | 123 | 124 | ## setPadded 125 | 126 | Set the value of property `padded` 127 | 128 | **Arguments** 129 | 130 | * value: Boolean - The new value for `padded` property. 131 | 132 | ## getPadded 133 | 134 | Return the value of property `padded` 135 | 136 | 137 | 138 | 139 | -------------------------------------------------------------------------------- /docs/progressbar.md: -------------------------------------------------------------------------------- 1 | 2 | # ProgressBar 3 | 4 | > Progress bar widget. 5 | 6 | ![UiProgressBar example](media/UiProgressBar.png) 7 | 8 | ```js 9 | var libui = require('libui'); 10 | 11 | var win = new libui.UiWindow('UiProgressBar example', 640, 480, true); 12 | 13 | var widget = new libui.UiProgressBar(); 14 | win.setChild(widget); 15 | 16 | win.onClosing(function () { 17 | win.close(); 18 | libui.stopLoop(); 19 | }); 20 | 21 | win.show(); 22 | 23 | libui.startLoop(); 24 | 25 | ``` 26 | 27 | --- 28 | 29 | # Constructor 30 | 31 | > new libui.UiProgressBar() 32 | 33 | Create a new UiProgressBar object. 34 | 35 | --- 36 | 37 | # Properties 38 | 39 | See [properties implementation](properties.md) for generic details on how properties are implemented. 40 | 41 | 42 | ### visible: Boolean 43 | 44 | Whether the widget should be visible or hidden. 45 | Read write. 46 | Defaults to `true`. 47 | 48 | 49 | 50 | ### enabled: Boolean 51 | 52 | Whether the widget should be enabled or disabled. 53 | Read write. 54 | Defaults to `true`. 55 | 56 | 57 | 58 | ### value: Number 59 | 60 | The current position of the progress bar. Could be setted to -1 to create an indeterminate progress bar. 61 | Read write. 62 | 63 | 64 | 65 | 66 | --- 67 | 68 | # Methods 69 | 70 | 71 | ## destroy 72 | 73 | Destroy and free the control. 74 | 75 | 76 | 77 | 78 | ## setParent 79 | 80 | Change the parent of the control 81 | 82 | 83 | **Arguments** 84 | 85 | * parent: UiControl - the new parent of the widget or null to detach it. 86 | 87 | 88 | 89 | ## toplevel 90 | 91 | Return whether the control is a top level one or not. 92 | 93 | 94 | 95 | 96 | ## setVisible 97 | 98 | Set the value of property `visible` 99 | 100 | **Arguments** 101 | 102 | * value: Boolean - The new value for `visible` property. 103 | 104 | ## getVisible 105 | 106 | Return the value of property `visible` 107 | 108 | 109 | 110 | ## setEnabled 111 | 112 | Set the value of property `enabled` 113 | 114 | **Arguments** 115 | 116 | * value: Boolean - The new value for `enabled` property. 117 | 118 | ## getEnabled 119 | 120 | Return the value of property `enabled` 121 | 122 | 123 | 124 | ## setValue 125 | 126 | Set the value of property `value` 127 | 128 | **Arguments** 129 | 130 | * value: Number - The new value for `value` property. 131 | 132 | ## getValue 133 | 134 | Return the value of property `value` 135 | 136 | 137 | 138 | 139 | -------------------------------------------------------------------------------- /docs/button.md: -------------------------------------------------------------------------------- 1 | 2 | # Button 3 | 4 | > A simple button. 5 | 6 | ![UiButton example](media/UiButton.png) 7 | 8 | ```js 9 | var libui = require('libui'); 10 | 11 | var win = new libui.UiWindow('UiButton example', 640, 480, true); 12 | 13 | var widget = new libui.UiButton(); 14 | win.setChild(widget); 15 | 16 | win.onClosing(function () { 17 | win.close(); 18 | libui.stopLoop(); 19 | }); 20 | 21 | win.show(); 22 | 23 | libui.startLoop(); 24 | 25 | ``` 26 | 27 | --- 28 | 29 | # Constructor 30 | 31 | > new libui.UiButton() 32 | 33 | Create a new UiButton object. 34 | 35 | --- 36 | 37 | # Properties 38 | 39 | See [properties implementation](properties.md) for generic details on how properties are implemented. 40 | 41 | 42 | ### visible: Boolean 43 | 44 | Whether the widget should be visible or hidden. 45 | Read write. 46 | Defaults to `true`. 47 | 48 | 49 | 50 | ### enabled: Boolean 51 | 52 | Whether the widget should be enabled or disabled. 53 | Read write. 54 | Defaults to `true`. 55 | 56 | 57 | 58 | ### text: String 59 | 60 | The static text of the button. 61 | Read write. 62 | 63 | 64 | 65 | 66 | --- 67 | 68 | # Methods 69 | 70 | 71 | ## destroy 72 | 73 | Destroy and free the control. 74 | 75 | 76 | 77 | 78 | ## setParent 79 | 80 | Change the parent of the control 81 | 82 | 83 | **Arguments** 84 | 85 | * parent: UiControl - the new parent of the widget or null to detach it. 86 | 87 | 88 | 89 | ## toplevel 90 | 91 | Return whether the control is a top level one or not. 92 | 93 | 94 | 95 | 96 | ## setVisible 97 | 98 | Set the value of property `visible` 99 | 100 | **Arguments** 101 | 102 | * value: Boolean - The new value for `visible` property. 103 | 104 | ## getVisible 105 | 106 | Return the value of property `visible` 107 | 108 | 109 | 110 | ## setEnabled 111 | 112 | Set the value of property `enabled` 113 | 114 | **Arguments** 115 | 116 | * value: Boolean - The new value for `enabled` property. 117 | 118 | ## getEnabled 119 | 120 | Return the value of property `enabled` 121 | 122 | 123 | 124 | ## setText 125 | 126 | Set the value of property `text` 127 | 128 | **Arguments** 129 | 130 | * value: String - The new value for `text` property. 131 | 132 | ## getText 133 | 134 | Return the value of property `text` 135 | 136 | 137 | 138 | --- 139 | 140 | # Events 141 | 142 | See [events implementation](events.md) for generic details on how events are implemented. 143 | 144 | 145 | ### onClicked 146 | Emitted when the button is clicked 147 | 148 | 149 | 150 | -------------------------------------------------------------------------------- /docs/slider.md: -------------------------------------------------------------------------------- 1 | 2 | # Slider 3 | 4 | > Horizontal slide to set numerical values. 5 | 6 | ![UiSlider example](media/UiSlider.png) 7 | 8 | ```js 9 | var libui = require('libui'); 10 | 11 | var win = new libui.UiWindow('UiSlider example', 640, 480, true); 12 | 13 | var widget = new libui.UiSlider(); 14 | win.setChild(widget); 15 | 16 | win.onClosing(function () { 17 | win.close(); 18 | libui.stopLoop(); 19 | }); 20 | 21 | win.show(); 22 | 23 | libui.startLoop(); 24 | 25 | ``` 26 | 27 | --- 28 | 29 | # Constructor 30 | 31 | > new libui.UiSlider() 32 | 33 | Create a new UiSlider object. 34 | 35 | --- 36 | 37 | # Properties 38 | 39 | See [properties implementation](properties.md) for generic details on how properties are implemented. 40 | 41 | 42 | ### visible: Boolean 43 | 44 | Whether the widget should be visible or hidden. 45 | Read write. 46 | Defaults to `true`. 47 | 48 | 49 | 50 | ### enabled: Boolean 51 | 52 | Whether the widget should be enabled or disabled. 53 | Read write. 54 | Defaults to `true`. 55 | 56 | 57 | 58 | ### value: Number 59 | 60 | The current numeric value of the slider. 61 | Read write. 62 | 63 | 64 | 65 | 66 | --- 67 | 68 | # Methods 69 | 70 | 71 | ## destroy 72 | 73 | Destroy and free the control. 74 | 75 | 76 | 77 | 78 | ## setParent 79 | 80 | Change the parent of the control 81 | 82 | 83 | **Arguments** 84 | 85 | * parent: UiControl - the new parent of the widget or null to detach it. 86 | 87 | 88 | 89 | ## toplevel 90 | 91 | Return whether the control is a top level one or not. 92 | 93 | 94 | 95 | 96 | ## setVisible 97 | 98 | Set the value of property `visible` 99 | 100 | **Arguments** 101 | 102 | * value: Boolean - The new value for `visible` property. 103 | 104 | ## getVisible 105 | 106 | Return the value of property `visible` 107 | 108 | 109 | 110 | ## setEnabled 111 | 112 | Set the value of property `enabled` 113 | 114 | **Arguments** 115 | 116 | * value: Boolean - The new value for `enabled` property. 117 | 118 | ## getEnabled 119 | 120 | Return the value of property `enabled` 121 | 122 | 123 | 124 | ## setValue 125 | 126 | Set the value of property `value` 127 | 128 | **Arguments** 129 | 130 | * value: Number - The new value for `value` property. 131 | 132 | ## getValue 133 | 134 | Return the value of property `value` 135 | 136 | 137 | 138 | --- 139 | 140 | # Events 141 | 142 | See [events implementation](events.md) for generic details on how events are implemented. 143 | 144 | 145 | ### onChanged 146 | 147 | Emitted whenever property `value` change. 148 | 149 | 150 | 151 | 152 | -------------------------------------------------------------------------------- /docs/spinbox.md: -------------------------------------------------------------------------------- 1 | 2 | # Spinbox 3 | 4 | > An entry widget for numerical values. 5 | 6 | ![UiSpinbox example](media/UiSpinbox.png) 7 | 8 | ```js 9 | var libui = require('libui'); 10 | 11 | var win = new libui.UiWindow('UiSpinbox example', 640, 480, true); 12 | 13 | var widget = new libui.UiSpinbox(); 14 | win.setChild(widget); 15 | 16 | win.onClosing(function () { 17 | win.close(); 18 | libui.stopLoop(); 19 | }); 20 | 21 | win.show(); 22 | 23 | libui.startLoop(); 24 | 25 | ``` 26 | 27 | --- 28 | 29 | # Constructor 30 | 31 | > new libui.UiSpinbox() 32 | 33 | Create a new UiSpinbox object. 34 | 35 | --- 36 | 37 | # Properties 38 | 39 | See [properties implementation](properties.md) for generic details on how properties are implemented. 40 | 41 | 42 | ### visible: Boolean 43 | 44 | Whether the widget should be visible or hidden. 45 | Read write. 46 | Defaults to `true`. 47 | 48 | 49 | 50 | ### enabled: Boolean 51 | 52 | Whether the widget should be enabled or disabled. 53 | Read write. 54 | Defaults to `true`. 55 | 56 | 57 | 58 | ### value: Number 59 | 60 | The current numeric value of the spinbox. 61 | Read write. 62 | 63 | 64 | 65 | 66 | --- 67 | 68 | # Methods 69 | 70 | 71 | ## destroy 72 | 73 | Destroy and free the control. 74 | 75 | 76 | 77 | 78 | ## setParent 79 | 80 | Change the parent of the control 81 | 82 | 83 | **Arguments** 84 | 85 | * parent: UiControl - the new parent of the widget or null to detach it. 86 | 87 | 88 | 89 | ## toplevel 90 | 91 | Return whether the control is a top level one or not. 92 | 93 | 94 | 95 | 96 | ## setVisible 97 | 98 | Set the value of property `visible` 99 | 100 | **Arguments** 101 | 102 | * value: Boolean - The new value for `visible` property. 103 | 104 | ## getVisible 105 | 106 | Return the value of property `visible` 107 | 108 | 109 | 110 | ## setEnabled 111 | 112 | Set the value of property `enabled` 113 | 114 | **Arguments** 115 | 116 | * value: Boolean - The new value for `enabled` property. 117 | 118 | ## getEnabled 119 | 120 | Return the value of property `enabled` 121 | 122 | 123 | 124 | ## setValue 125 | 126 | Set the value of property `value` 127 | 128 | **Arguments** 129 | 130 | * value: Number - The new value for `value` property. 131 | 132 | ## getValue 133 | 134 | Return the value of property `value` 135 | 136 | 137 | 138 | --- 139 | 140 | # Events 141 | 142 | See [events implementation](events.md) for generic details on how events are implemented. 143 | 144 | 145 | ### onChanged 146 | 147 | Emitted whenever property `value` change. 148 | 149 | 150 | 151 | 152 | -------------------------------------------------------------------------------- /examples/core-api.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const os = require('os'); 3 | const libui = require('..'); 4 | 5 | const win = new libui.UiWindow('Test window', 800, 600, false); 6 | win.margined = 1; 7 | 8 | const box = new libui.UiVerticalBox(); 9 | const hBox = new libui.UiHorizontalBox(); 10 | const e1 = new libui.UiEntry(); 11 | e1.enabled = 0; 12 | const lblCiao = new libui.UiLabel('ciao'); 13 | hBox.append(lblCiao, false); 14 | 15 | hBox.append(e1, false); 16 | 17 | win.onClosing(() => { 18 | win.close(); 19 | libui.stopLoop(); 20 | }); 21 | 22 | box.append(new libui.UiEntry(), false); 23 | box.append(hBox, false); 24 | 25 | if (os.platform() !== 'darwin') { 26 | box.append(new libui.UiSearchEntry(), false); 27 | } 28 | 29 | box.append(new libui.UiPasswordEntry(), false); 30 | 31 | const cmb = new libui.UiCombobox(); 32 | 33 | cmb.append('item 1'); 34 | cmb.append('item 2'); 35 | cmb.append('item 3'); 36 | 37 | box.append(cmb, false); 38 | const hBox4 = new libui.UiHorizontalBox(); 39 | hBox4.append(new libui.UiDateTimePicker(), false); 40 | hBox4.append(new libui.UiVerticalSeparator(), false); 41 | hBox4.append(new libui.UiEditableCombobox(), false); 42 | hBox4.append(new libui.UiCheckbox('Optionally'), false); 43 | 44 | box.append(hBox4, false); 45 | 46 | const group = new libui.UiGroup('Options'); 47 | const radios = new libui.UiRadioButtons(); 48 | radios.append('option 1'); 49 | radios.append('option 2'); 50 | radios.append('option 3'); 51 | 52 | group.setChild(radios); 53 | box.append(group, true); 54 | 55 | box.append(new libui.UiHorizontalSeparator(), true); 56 | 57 | const hBox2 = new libui.UiHorizontalBox(); 58 | const spin = new libui.UiSpinbox(0, 100); 59 | spin.value = 33; 60 | hBox2.append(new libui.UiLabel('Number'), false); 61 | hBox2.append(spin, true); 62 | box.append(hBox2, false); 63 | 64 | const hBox3 = new libui.UiHorizontalBox(); 65 | const slider = new libui.UiSlider(0, 100); 66 | slider.value = 33; 67 | hBox3.append(new libui.UiLabel('Number'), false); 68 | hBox3.append(slider, false); 69 | box.append(hBox3, false); 70 | 71 | box.append(new libui.UiMultilineEntry(), false); 72 | 73 | const buttons = new libui.UiHorizontalBox(); 74 | buttons.append(new libui.UiButton('Ok'), false); 75 | buttons.append(new libui.UiButton('Maybe'), false); 76 | buttons.append(new libui.UiButton('Cancel'), false); 77 | 78 | box.append(new libui.UiProgressBar(), false); 79 | box.append(new libui.UiFontButton(), false); 80 | 81 | box.append(buttons, false); 82 | 83 | const tabs = new libui.UiTab(); 84 | 85 | tabs.append('controls', box); 86 | tabs.append('text', new libui.UiMultilineEntry()); 87 | 88 | win.setChild(tabs); 89 | 90 | win.show(); 91 | libui.startLoop(); 92 | -------------------------------------------------------------------------------- /src/UiArea/DrawBrush.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "area.h" 3 | #include "ui.h" 4 | 5 | DrawBrush::DrawBrush() { 6 | b = new uiDrawBrush(); 7 | } 8 | 9 | DrawBrush::~DrawBrush() { 10 | if (b->NumStops > 0) { 11 | delete[] b->Stops; 12 | } 13 | delete b; 14 | } 15 | 16 | uiDrawBrush *DrawBrush::toStruct() { 17 | return b; 18 | } 19 | 20 | Color DrawBrush::getColor() { 21 | return Color(b->R, b->G, b->B, b->A); 22 | } 23 | 24 | void DrawBrush::setColor(Color value) { 25 | b->R = value.getR(); 26 | b->G = value.getG(); 27 | b->B = value.getB(); 28 | b->A = value.getA(); 29 | } 30 | 31 | Point DrawBrush::getStart() { 32 | return Point(b->X0, b->Y0); 33 | } 34 | 35 | void DrawBrush::setStart(Point value) { 36 | b->X0 = value.getX(); 37 | b->Y0 = value.getY(); 38 | } 39 | 40 | Point DrawBrush::getEnd() { 41 | return Point(b->X1, b->Y1); 42 | } 43 | 44 | void DrawBrush::setEnd(Point value) { 45 | b->X1 = value.getX(); 46 | b->Y1 = value.getY(); 47 | } 48 | 49 | double DrawBrush::getOuterRadius() { 50 | return b->OuterRadius; 51 | } 52 | 53 | void DrawBrush::setOuterRadius(double r) { 54 | b->OuterRadius = r; 55 | } 56 | 57 | int DrawBrush::getType() { 58 | return b->Type; 59 | } 60 | 61 | void DrawBrush::setType(int value) { 62 | b->Type = value; 63 | } 64 | 65 | std::vector DrawBrush::getStops() { 66 | std::vector v; 67 | v.reserve(b->NumStops); 68 | for (size_t i = 0; i < b->NumStops; i++) { 69 | v.insert(v.begin() + i, 70 | BrushGradientStop(b->Stops[i].Pos, 71 | Color(b->Stops[i].R, b->Stops[i].G, 72 | b->Stops[i].B, b->Stops[i].A))); 73 | } 74 | return v; 75 | } 76 | 77 | void DrawBrush::setStops(std::vector value) { 78 | if (b->NumStops > 0) { 79 | delete[] b->Stops; 80 | } 81 | 82 | b->NumStops = value.size(); 83 | if (b->NumStops > 0) { 84 | b->Stops = new uiDrawBrushGradientStop[b->NumStops]; 85 | 86 | for (size_t i = 0; i < b->NumStops; i++) { 87 | Color c = value[i].getColor(); 88 | b->Stops[i] = {value[i].getPos(), c.getR(), c.getG(), c.getB(), 89 | c.getA()}; 90 | } 91 | } 92 | } 93 | 94 | NBIND_CLASS(DrawBrush) { 95 | construct<>(); 96 | method(getStart); 97 | method(setStart); 98 | method(getColor); 99 | method(setColor); 100 | method(getEnd); 101 | method(setEnd); 102 | method(getOuterRadius); 103 | method(setOuterRadius); 104 | method(getType); 105 | method(setType); 106 | method(setStops); 107 | method(getStops); 108 | 109 | getset(getColor, setColor); 110 | getset(getStart, setStart); 111 | getset(getEnd, setEnd); 112 | getset(getOuterRadius, setOuterRadius); 113 | getset(getType, setType); 114 | getset(getStops, setStops); 115 | } 116 | -------------------------------------------------------------------------------- /examples/area-adv.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /* eslint-disable unicorn/number-literal-case */ 3 | const libui = require('..'); 4 | 5 | const solidBrush = new libui.DrawBrush(); 6 | solidBrush.type = libui.brushType.solid; 7 | solidBrush.color = new libui.Color(1, 0, 0, 1); 8 | 9 | const dashedStroke = new libui.DrawStrokeParams(); 10 | dashedStroke.thickness = 6; 11 | dashedStroke.dashes = [10, 5]; 12 | console.log(dashedStroke.dashes); 13 | 14 | const linearBrush = new libui.DrawBrush(); 15 | linearBrush.type = libui.brushType.linearGradient; 16 | linearBrush.start = new libui.Point(0, 0); 17 | linearBrush.end = new libui.Point(200, 200); 18 | linearBrush.setStops([new libui.BrushGradientStop(0, new libui.Color(1, 0, 0, 1)), new libui.BrushGradientStop(1, new libui.Color(0, 1, 0, 1))]); 19 | 20 | const radialBrush = new libui.DrawBrush(); 21 | radialBrush.type = libui.brushType.radialGradient; 22 | radialBrush.start = new libui.Point(250, 300); 23 | radialBrush.end = new libui.Point(250, 300); 24 | radialBrush.outerRadius = 40; 25 | 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))]); 26 | console.log(radialBrush.getStops()); 27 | 28 | const matrix = new libui.UiDrawMatrix(); 29 | matrix.setIdentity(); 30 | matrix.rotate(70, 280, (Math.PI / 180) * 45) 31 | 32 | function handlerDraw(area, p) { 33 | let path = new libui.UiDrawPath(libui.fillMode.winding); 34 | path.addRectangle(0, 0, 200, 200); 35 | path.end(); 36 | p.getContext().fill(path, linearBrush); 37 | path.freePath(); 38 | 39 | // ------ 40 | 41 | path = new libui.UiDrawPath(libui.fillMode.winding); 42 | path.newFigure(0, 0); 43 | path.arcTo(250, 300, 50, 0, 2 * Math.PI, false); 44 | path.end(); 45 | p.getContext().fill(path, radialBrush); 46 | path.freePath(); 47 | 48 | path = new libui.UiDrawPath(libui.fillMode.winding); 49 | path.newFigure(250, 20); 50 | path.lineTo(300, 150); 51 | path.end(); 52 | p.getContext().stroke(path, solidBrush, dashedStroke); 53 | path.freePath(); 54 | 55 | path = new libui.UiDrawPath(libui.fillMode.winding); 56 | p.getContext().transform(matrix); 57 | path.addRectangle(20, 230, 100, 100); 58 | path.end(); 59 | p.getContext().fill(path, solidBrush); 60 | path.freePath(); 61 | } 62 | 63 | function noop() {} 64 | 65 | function main() { 66 | const mainwin = new libui.UiWindow('libui textDrawArea Example', 400, 400, 1); 67 | mainwin.margined = true; 68 | mainwin.onClosing(() => { 69 | mainwin.close(); 70 | libui.stopLoop(); 71 | }); 72 | 73 | const textDrawArea = new libui.UiArea(handlerDraw, noop, noop, noop, noop); 74 | const wrapper = new libui.UiVerticalBox(); 75 | wrapper.append(textDrawArea, true); 76 | mainwin.setChild(wrapper); 77 | 78 | mainwin.show(); 79 | 80 | libui.startLoop(); 81 | } 82 | 83 | main(); 84 | -------------------------------------------------------------------------------- /docs/combobox.md: -------------------------------------------------------------------------------- 1 | 2 | # Combobox 3 | 4 | > A drop down combo box that allow list selection only. 5 | 6 | ![UiCombobox example](media/UiCombobox.png) 7 | 8 | ```js 9 | var libui = require('libui'); 10 | 11 | var win = new libui.UiWindow('UiCombobox example', 640, 480, true); 12 | 13 | var widget = new libui.UiCombobox(); 14 | win.setChild(widget); 15 | 16 | win.onClosing(function () { 17 | win.close(); 18 | libui.stopLoop(); 19 | }); 20 | 21 | win.show(); 22 | 23 | libui.startLoop(); 24 | 25 | ``` 26 | 27 | --- 28 | 29 | # Constructor 30 | 31 | > new libui.UiCombobox() 32 | 33 | Create a new UiCombobox object. 34 | 35 | --- 36 | 37 | # Properties 38 | 39 | See [properties implementation](properties.md) for generic details on how properties are implemented. 40 | 41 | 42 | ### visible: Boolean 43 | 44 | Whether the widget should be visible or hidden. 45 | Read write. 46 | Defaults to `true`. 47 | 48 | 49 | 50 | ### enabled: Boolean 51 | 52 | Whether the widget should be enabled or disabled. 53 | Read write. 54 | Defaults to `true`. 55 | 56 | 57 | 58 | ### selected: Number 59 | 60 | Return or set the current selected item by index. 61 | 62 | 63 | 64 | 65 | --- 66 | 67 | # Methods 68 | 69 | 70 | ## append 71 | 72 | Append a new text item to the drop down list. 73 | 74 | 75 | **Arguments** 76 | 77 | * text: String - the text item to append. 78 | 79 | 80 | 81 | ## destroy 82 | 83 | Destroy and free the control. 84 | 85 | 86 | 87 | 88 | ## setParent 89 | 90 | Change the parent of the control 91 | 92 | 93 | **Arguments** 94 | 95 | * parent: UiControl - the new parent of the widget or null to detach it. 96 | 97 | 98 | 99 | ## toplevel 100 | 101 | Return whether the control is a top level one or not. 102 | 103 | 104 | 105 | 106 | ## setVisible 107 | 108 | Set the value of property `visible` 109 | 110 | **Arguments** 111 | 112 | * value: Boolean - The new value for `visible` property. 113 | 114 | ## getVisible 115 | 116 | Return the value of property `visible` 117 | 118 | 119 | 120 | ## setEnabled 121 | 122 | Set the value of property `enabled` 123 | 124 | **Arguments** 125 | 126 | * value: Boolean - The new value for `enabled` property. 127 | 128 | ## getEnabled 129 | 130 | Return the value of property `enabled` 131 | 132 | 133 | 134 | ## setSelected 135 | 136 | Set the value of property `selected` 137 | 138 | **Arguments** 139 | 140 | * value: Number - The new value for `selected` property. 141 | 142 | ## getSelected 143 | 144 | Return the value of property `selected` 145 | 146 | 147 | 148 | --- 149 | 150 | # Events 151 | 152 | See [events implementation](events.md) for generic details on how events are implemented. 153 | 154 | 155 | ### onSelected 156 | 157 | Emitted whenever property `selected` change. 158 | 159 | 160 | 161 | 162 | -------------------------------------------------------------------------------- /src/UiMenu.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "nbind/api.h" 3 | #include "control.h" 4 | #include "ui.h" 5 | 6 | // TODO - document 7 | class UiMenuItem { 8 | DEFINE_EVENT(onClicked) 9 | 10 | private: 11 | uiMenuItem *handle; 12 | 13 | public: 14 | UiMenuItem(uiMenuItem *hnd); 15 | void enable(); 16 | void disable(); 17 | bool getChecked(); 18 | void setChecked(bool checked); 19 | }; 20 | 21 | // TODO - document 22 | class UiMenu { 23 | private: 24 | uiMenu *handle; 25 | 26 | public: 27 | UiMenu(std::string name); 28 | UiMenuItem *appendItem(std::string name); 29 | UiMenuItem *appendCheckItem(std::string name); 30 | UiMenuItem *appendQuitItem(); 31 | UiMenuItem *appendPreferencesItem(); 32 | UiMenuItem *appendAboutItem(); 33 | void appendSeparator(); 34 | }; 35 | 36 | static void UiMenuItem_onClicked(uiMenuItem *sender, uiWindow *window, 37 | void *data) { 38 | nbind::cbFunction *cb = (nbind::cbFunction *)data; 39 | (*cb)(); 40 | } 41 | 42 | void UiMenuItem::onClicked(nbind::cbFunction &cb) { 43 | onClickedCallback = new nbind::cbFunction(cb); 44 | uiMenuItemOnClicked(handle, UiMenuItem_onClicked, onClickedCallback); 45 | } 46 | 47 | UiMenuItem::UiMenuItem(uiMenuItem *hnd) { 48 | handle = hnd; 49 | } 50 | 51 | void UiMenuItem::enable() { 52 | uiMenuItemEnable(handle); 53 | } 54 | 55 | void UiMenuItem::disable() { 56 | uiMenuItemDisable(handle); 57 | } 58 | 59 | bool UiMenuItem::getChecked() { 60 | return uiMenuItemChecked(handle); 61 | } 62 | 63 | void UiMenuItem::setChecked(bool checked) { 64 | uiMenuItemSetChecked(handle, checked); 65 | } 66 | 67 | UiMenu::UiMenu(std::string name) { 68 | handle = uiNewMenu(name.c_str()); 69 | } 70 | 71 | UiMenuItem *UiMenu::appendItem(std::string name) { 72 | return new UiMenuItem(uiMenuAppendItem(handle, name.c_str())); 73 | } 74 | 75 | UiMenuItem *UiMenu::appendCheckItem(std::string name) { 76 | return new UiMenuItem(uiMenuAppendCheckItem(handle, name.c_str())); 77 | } 78 | 79 | UiMenuItem *UiMenu::appendQuitItem() { 80 | return new UiMenuItem(uiMenuAppendQuitItem(handle)); 81 | } 82 | 83 | UiMenuItem *UiMenu::appendPreferencesItem() { 84 | return new UiMenuItem(uiMenuAppendPreferencesItem(handle)); 85 | } 86 | 87 | UiMenuItem *UiMenu::appendAboutItem() { 88 | return new UiMenuItem(uiMenuAppendAboutItem(handle)); 89 | } 90 | 91 | void UiMenu::appendSeparator() { 92 | uiMenuAppendSeparator(handle); 93 | } 94 | 95 | NBIND_CLASS(UiMenu) { 96 | construct(); 97 | method(appendItem); 98 | method(appendCheckItem); 99 | method(appendQuitItem); 100 | method(appendPreferencesItem); 101 | method(appendAboutItem); 102 | method(appendSeparator); 103 | } 104 | 105 | NBIND_CLASS(UiMenuItem) { 106 | construct(); 107 | method(enable); 108 | method(disable); 109 | method(onClicked); 110 | getset(getChecked, setChecked); 111 | } 112 | -------------------------------------------------------------------------------- /docs/radiobuttons.md: -------------------------------------------------------------------------------- 1 | 2 | # RadioButtons 3 | 4 | > A widget that represent a group of radio options. 5 | 6 | ![UiRadioButtons example](media/UiRadioButtons.png) 7 | 8 | ```js 9 | var libui = require('libui'); 10 | 11 | var win = new libui.UiWindow('UiRadioButtons example', 640, 480, true); 12 | 13 | var widget = new libui.UiRadioButtons(); 14 | win.setChild(widget); 15 | 16 | win.onClosing(function () { 17 | win.close(); 18 | libui.stopLoop(); 19 | }); 20 | 21 | win.show(); 22 | 23 | libui.startLoop(); 24 | 25 | ``` 26 | 27 | --- 28 | 29 | # Constructor 30 | 31 | > new libui.UiRadioButtons() 32 | 33 | Create a new UiRadioButtons object. 34 | 35 | --- 36 | 37 | # Properties 38 | 39 | See [properties implementation](properties.md) for generic details on how properties are implemented. 40 | 41 | 42 | ### visible: Boolean 43 | 44 | Whether the widget should be visible or hidden. 45 | Read write. 46 | Defaults to `true`. 47 | 48 | 49 | 50 | ### enabled: Boolean 51 | 52 | Whether the widget should be enabled or disabled. 53 | Read write. 54 | Defaults to `true`. 55 | 56 | 57 | 58 | ### selected: Number 59 | 60 | Return or set the current choosed option by index. 61 | 62 | 63 | 64 | 65 | --- 66 | 67 | # Methods 68 | 69 | 70 | ## append 71 | 72 | Append a new radio option as last one with specified text. 73 | 74 | 75 | **Arguments** 76 | 77 | * text: String - the text to show as radio widget label. 78 | 79 | 80 | 81 | ## destroy 82 | 83 | Destroy and free the control. 84 | 85 | 86 | 87 | 88 | ## setParent 89 | 90 | Change the parent of the control 91 | 92 | 93 | **Arguments** 94 | 95 | * parent: UiControl - the new parent of the widget or null to detach it. 96 | 97 | 98 | 99 | ## toplevel 100 | 101 | Return whether the control is a top level one or not. 102 | 103 | 104 | 105 | 106 | ## setVisible 107 | 108 | Set the value of property `visible` 109 | 110 | **Arguments** 111 | 112 | * value: Boolean - The new value for `visible` property. 113 | 114 | ## getVisible 115 | 116 | Return the value of property `visible` 117 | 118 | 119 | 120 | ## setEnabled 121 | 122 | Set the value of property `enabled` 123 | 124 | **Arguments** 125 | 126 | * value: Boolean - The new value for `enabled` property. 127 | 128 | ## getEnabled 129 | 130 | Return the value of property `enabled` 131 | 132 | 133 | 134 | ## setSelected 135 | 136 | Set the value of property `selected` 137 | 138 | **Arguments** 139 | 140 | * value: Number - The new value for `selected` property. 141 | 142 | ## getSelected 143 | 144 | Return the value of property `selected` 145 | 146 | 147 | 148 | --- 149 | 150 | # Events 151 | 152 | See [events implementation](events.md) for generic details on how events are implemented. 153 | 154 | 155 | ### onSelected 156 | 157 | Emitted whenever property `selected` change. 158 | 159 | 160 | 161 | 162 | -------------------------------------------------------------------------------- /docs/verticalbox.md: -------------------------------------------------------------------------------- 1 | 2 | # VerticalBox 3 | 4 | > A container that stack its chidren vertically. 5 | 6 | ![UiVerticalBox example](media/UiVerticalBox.png) 7 | 8 | ```js 9 | var libui = require('libui'); 10 | 11 | var win = new libui.UiWindow('UiVerticalBox example', 640, 480, true); 12 | 13 | var widget = new libui.UiVerticalBox(); 14 | win.setChild(widget); 15 | 16 | win.onClosing(function () { 17 | win.close(); 18 | libui.stopLoop(); 19 | }); 20 | 21 | win.show(); 22 | 23 | libui.startLoop(); 24 | 25 | ``` 26 | 27 | --- 28 | 29 | # Constructor 30 | 31 | > new libui.UiVerticalBox() 32 | 33 | Create a new UiVerticalBox object. 34 | 35 | --- 36 | 37 | # Properties 38 | 39 | See [properties implementation](properties.md) for generic details on how properties are implemented. 40 | 41 | 42 | ### visible: Boolean 43 | 44 | Whether the widget should be visible or hidden. 45 | Read write. 46 | Defaults to `true`. 47 | 48 | 49 | 50 | ### enabled: Boolean 51 | 52 | Whether the widget should be enabled or disabled. 53 | Read write. 54 | Defaults to `true`. 55 | 56 | 57 | 58 | ### padded: Boolean 59 | 60 | If true, the container insert some space between children. 61 | Defaults to false. 62 | 63 | 64 | 65 | 66 | --- 67 | 68 | # Methods 69 | 70 | 71 | ## append 72 | 73 | Append a new child widget as last one. 74 | 75 | 76 | **Arguments** 77 | 78 | * control: UiControl - the control to append. 79 | * stretchy: Boolean - whether the child should expand to use all available size. 80 | 81 | 82 | 83 | ## deleteAt 84 | 85 | Remove a child widget at specified position. 86 | 87 | 88 | **Arguments** 89 | 90 | * index: Number - the index of the control to remove. 91 | 92 | 93 | 94 | ## destroy 95 | 96 | Destroy and free the control. 97 | 98 | 99 | 100 | 101 | ## setParent 102 | 103 | Change the parent of the control 104 | 105 | 106 | **Arguments** 107 | 108 | * parent: UiControl - the new parent of the widget or null to detach it. 109 | 110 | 111 | 112 | ## toplevel 113 | 114 | Return whether the control is a top level one or not. 115 | 116 | 117 | 118 | 119 | ## setVisible 120 | 121 | Set the value of property `visible` 122 | 123 | **Arguments** 124 | 125 | * value: Boolean - The new value for `visible` property. 126 | 127 | ## getVisible 128 | 129 | Return the value of property `visible` 130 | 131 | 132 | 133 | ## setEnabled 134 | 135 | Set the value of property `enabled` 136 | 137 | **Arguments** 138 | 139 | * value: Boolean - The new value for `enabled` property. 140 | 141 | ## getEnabled 142 | 143 | Return the value of property `enabled` 144 | 145 | 146 | 147 | ## setPadded 148 | 149 | Set the value of property `padded` 150 | 151 | **Arguments** 152 | 153 | * value: Boolean - The new value for `padded` property. 154 | 155 | ## getPadded 156 | 157 | Return the value of property `padded` 158 | 159 | 160 | 161 | 162 | -------------------------------------------------------------------------------- /docs/editablecombobox.md: -------------------------------------------------------------------------------- 1 | 2 | # EditableCombobox 3 | 4 | > A drop down combo box that allow selection from list or free text entry. 5 | 6 | ![UiEditableCombobox example](media/UiEditableCombobox.png) 7 | 8 | ```js 9 | var libui = require('libui'); 10 | 11 | var win = new libui.UiWindow('UiEditableCombobox example', 640, 480, true); 12 | 13 | var widget = new libui.UiEditableCombobox(); 14 | win.setChild(widget); 15 | 16 | win.onClosing(function () { 17 | win.close(); 18 | libui.stopLoop(); 19 | }); 20 | 21 | win.show(); 22 | 23 | libui.startLoop(); 24 | 25 | ``` 26 | 27 | --- 28 | 29 | # Constructor 30 | 31 | > new libui.UiEditableCombobox() 32 | 33 | Create a new UiEditableCombobox object. 34 | 35 | --- 36 | 37 | # Properties 38 | 39 | See [properties implementation](properties.md) for generic details on how properties are implemented. 40 | 41 | 42 | ### visible: Boolean 43 | 44 | Whether the widget should be visible or hidden. 45 | Read write. 46 | Defaults to `true`. 47 | 48 | 49 | 50 | ### enabled: Boolean 51 | 52 | Whether the widget should be enabled or disabled. 53 | Read write. 54 | Defaults to `true`. 55 | 56 | 57 | 58 | ### text: String 59 | 60 | Return or set the current selected text or the text value of the selected item in the list. 61 | 62 | 63 | 64 | 65 | --- 66 | 67 | # Methods 68 | 69 | 70 | ## append 71 | 72 | Append a new text item to the drop down list. 73 | 74 | 75 | **Arguments** 76 | 77 | * text: String - the text item to append. 78 | 79 | 80 | 81 | ## destroy 82 | 83 | Destroy and free the control. 84 | 85 | 86 | 87 | 88 | ## setParent 89 | 90 | Change the parent of the control 91 | 92 | 93 | **Arguments** 94 | 95 | * parent: UiControl - the new parent of the widget or null to detach it. 96 | 97 | 98 | 99 | ## toplevel 100 | 101 | Return whether the control is a top level one or not. 102 | 103 | 104 | 105 | 106 | ## setVisible 107 | 108 | Set the value of property `visible` 109 | 110 | **Arguments** 111 | 112 | * value: Boolean - The new value for `visible` property. 113 | 114 | ## getVisible 115 | 116 | Return the value of property `visible` 117 | 118 | 119 | 120 | ## setEnabled 121 | 122 | Set the value of property `enabled` 123 | 124 | **Arguments** 125 | 126 | * value: Boolean - The new value for `enabled` property. 127 | 128 | ## getEnabled 129 | 130 | Return the value of property `enabled` 131 | 132 | 133 | 134 | ## setText 135 | 136 | Set the value of property `text` 137 | 138 | **Arguments** 139 | 140 | * value: String - The new value for `text` property. 141 | 142 | ## getText 143 | 144 | Return the value of property `text` 145 | 146 | 147 | 148 | --- 149 | 150 | # Events 151 | 152 | See [events implementation](events.md) for generic details on how events are implemented. 153 | 154 | 155 | ### onChanged 156 | 157 | Emitted whenever property `text` change. 158 | 159 | 160 | 161 | 162 | -------------------------------------------------------------------------------- /docs/horizontalbox.md: -------------------------------------------------------------------------------- 1 | 2 | # HorizontalBox 3 | 4 | > A container that stack its chidren horizontally. 5 | 6 | ![UiHorizontalBox example](media/UiHorizontalBox.png) 7 | 8 | ```js 9 | var libui = require('libui'); 10 | 11 | var win = new libui.UiWindow('UiHorizontalBox example', 640, 480, true); 12 | 13 | var widget = new libui.UiHorizontalBox(); 14 | win.setChild(widget); 15 | 16 | win.onClosing(function () { 17 | win.close(); 18 | libui.stopLoop(); 19 | }); 20 | 21 | win.show(); 22 | 23 | libui.startLoop(); 24 | 25 | ``` 26 | 27 | --- 28 | 29 | # Constructor 30 | 31 | > new libui.UiHorizontalBox() 32 | 33 | Create a new UiHorizontalBox object. 34 | 35 | --- 36 | 37 | # Properties 38 | 39 | See [properties implementation](properties.md) for generic details on how properties are implemented. 40 | 41 | 42 | ### visible: Boolean 43 | 44 | Whether the widget should be visible or hidden. 45 | Read write. 46 | Defaults to `true`. 47 | 48 | 49 | 50 | ### enabled: Boolean 51 | 52 | Whether the widget should be enabled or disabled. 53 | Read write. 54 | Defaults to `true`. 55 | 56 | 57 | 58 | ### padded: Boolean 59 | 60 | If true, the container insert some space between children. 61 | Defaults to false. 62 | 63 | 64 | 65 | 66 | --- 67 | 68 | # Methods 69 | 70 | 71 | ## append 72 | 73 | Append a new child widget as last one. 74 | 75 | 76 | **Arguments** 77 | 78 | * control: UiControl - the control to append. 79 | * stretchy: Boolean - whether the child should expand to use all available size. 80 | 81 | 82 | 83 | ## deleteAt 84 | 85 | Remove a child widget at specified position. 86 | 87 | 88 | **Arguments** 89 | 90 | * index: Number - the index of the control to remove. 91 | 92 | 93 | 94 | ## destroy 95 | 96 | Destroy and free the control. 97 | 98 | 99 | 100 | 101 | ## setParent 102 | 103 | Change the parent of the control 104 | 105 | 106 | **Arguments** 107 | 108 | * parent: UiControl - the new parent of the widget or null to detach it. 109 | 110 | 111 | 112 | ## toplevel 113 | 114 | Return whether the control is a top level one or not. 115 | 116 | 117 | 118 | 119 | ## setVisible 120 | 121 | Set the value of property `visible` 122 | 123 | **Arguments** 124 | 125 | * value: Boolean - The new value for `visible` property. 126 | 127 | ## getVisible 128 | 129 | Return the value of property `visible` 130 | 131 | 132 | 133 | ## setEnabled 134 | 135 | Set the value of property `enabled` 136 | 137 | **Arguments** 138 | 139 | * value: Boolean - The new value for `enabled` property. 140 | 141 | ## getEnabled 142 | 143 | Return the value of property `enabled` 144 | 145 | 146 | 147 | ## setPadded 148 | 149 | Set the value of property `padded` 150 | 151 | **Arguments** 152 | 153 | * value: Boolean - The new value for `padded` property. 154 | 155 | ## getPadded 156 | 157 | Return the value of property `padded` 158 | 159 | 160 | 161 | 162 | -------------------------------------------------------------------------------- /src/UiEntry.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "nbind/api.h" 3 | #include "control.h" 4 | #include "ui.h" 5 | 6 | class UiEntryBase : public UiControl { 7 | DEFINE_EVENT(onChanged) 8 | const char *n; 9 | 10 | public: 11 | UiEntryBase(uiControl *, const char *name); 12 | void setText(std::string text); 13 | std::string getText(); 14 | void setReadOnly(bool readOnly); 15 | bool getReadOnly(); 16 | ~UiEntryBase(); 17 | void onDestroy(uiControl *control) override; 18 | }; 19 | 20 | UiEntryBase::~UiEntryBase() { 21 | // printf("%s %p destroyed with wrapper %p.\n", n, getHandle(), this); 22 | } 23 | 24 | void UiEntryBase::onDestroy(uiControl *control) { 25 | /* 26 | freeing event callbacks to allow JS to garbage collect this class 27 | when there are no references to it left in JS code. 28 | */ 29 | DISPOSE_EVENT(onChanged); 30 | } 31 | 32 | class UiEntry : public UiEntryBase { 33 | public: 34 | UiEntry(); 35 | void onChanged(nbind::cbFunction &cb); 36 | }; 37 | 38 | class UiPasswordEntry : public UiEntryBase { 39 | public: 40 | UiPasswordEntry(); 41 | void onChanged(nbind::cbFunction &cb); 42 | }; 43 | 44 | class UiSearchEntry : public UiEntryBase { 45 | public: 46 | UiSearchEntry(); 47 | void onChanged(nbind::cbFunction &cb); 48 | }; 49 | 50 | UiEntryBase::UiEntryBase(uiControl *hnd, const char *name) : UiControl(hnd) { 51 | n = name; 52 | } 53 | 54 | void UiEntryBase::setText(std::string text) { 55 | uiEntrySetText(uiEntry(getHandle()), text.c_str()); 56 | if (onChangedCallback != NULL) { 57 | (*onChangedCallback)(); 58 | } 59 | } 60 | 61 | std::string UiEntryBase::getText() { 62 | char *char_ptr = uiEntryText(uiEntry(getHandle())); 63 | std::string s(char_ptr); 64 | uiFreeText(char_ptr); 65 | return s; 66 | } 67 | 68 | void UiEntryBase::setReadOnly(bool readOnly) { 69 | uiEntrySetReadOnly(uiEntry(getHandle()), readOnly); 70 | } 71 | 72 | bool UiEntryBase::getReadOnly() { 73 | return uiEntryReadOnly(uiEntry(getHandle())); 74 | } 75 | 76 | IMPLEMENT_EVENT(UiEntryBase, uiEntry, onChanged, uiEntryOnChanged) 77 | 78 | UiEntry::UiEntry() : UiEntryBase(uiControl(uiNewEntry()), "UiEntry") {} 79 | 80 | UiPasswordEntry::UiPasswordEntry() 81 | : UiEntryBase(uiControl(uiNewPasswordEntry()), "UiPasswordEntry") {} 82 | 83 | UiSearchEntry::UiSearchEntry() 84 | : UiEntryBase(uiControl(uiNewSearchEntry()), "UiSearchEntry") {} 85 | 86 | NBIND_CLASS(UiEntryBase) { 87 | inherit(UiControl); 88 | getset(getText, setText); 89 | getset(getReadOnly, setReadOnly); 90 | method(onChanged); 91 | method(getText); 92 | method(setText); 93 | method(getReadOnly); 94 | method(setReadOnly); 95 | } 96 | 97 | NBIND_CLASS(UiSearchEntry) { 98 | inherit(UiEntryBase); 99 | construct<>(); 100 | } 101 | 102 | NBIND_CLASS(UiPasswordEntry) { 103 | inherit(UiEntryBase); 104 | construct<>(); 105 | } 106 | 107 | NBIND_CLASS(UiEntry) { 108 | inherit(UiEntryBase); 109 | construct<>(); 110 | } 111 | -------------------------------------------------------------------------------- /docs/form.md: -------------------------------------------------------------------------------- 1 | 2 | # Form 3 | 4 | > A container that organize children as labeled fields. 5 | 6 | ![UiForm example](media/UiForm.png) 7 | 8 | ```js 9 | var libui = require('libui'); 10 | 11 | var win = new libui.UiWindow('UiForm example', 640, 480, true); 12 | 13 | var widget = new libui.UiForm(); 14 | win.setChild(widget); 15 | 16 | win.onClosing(function () { 17 | win.close(); 18 | libui.stopLoop(); 19 | }); 20 | 21 | win.show(); 22 | 23 | libui.startLoop(); 24 | 25 | ``` 26 | 27 | --- 28 | 29 | # Constructor 30 | 31 | > new libui.UiForm() 32 | 33 | Create a new UiForm object. 34 | 35 | --- 36 | 37 | # Properties 38 | 39 | See [properties implementation](properties.md) for generic details on how properties are implemented. 40 | 41 | 42 | ### visible: Boolean 43 | 44 | Whether the widget should be visible or hidden. 45 | Read write. 46 | Defaults to `true`. 47 | 48 | 49 | 50 | ### enabled: Boolean 51 | 52 | Whether the widget should be enabled or disabled. 53 | Read write. 54 | Defaults to `true`. 55 | 56 | 57 | 58 | ### padded: Boolean 59 | 60 | If true, the container insert some space between children. 61 | Defaults to false. 62 | 63 | 64 | 65 | 66 | --- 67 | 68 | # Methods 69 | 70 | 71 | ## append 72 | 73 | Append a new child widget as last field with specified label. 74 | 75 | 76 | **Arguments** 77 | 78 | * label: String - the text to use as label of the field. 79 | * control: UiControl - the control to append. 80 | * stretchy: Boolean - whether the child should expand to use all available size. 81 | 82 | 83 | 84 | ## deleteAt 85 | 86 | Remove a child widget and albel at specified position. 87 | 88 | 89 | **Arguments** 90 | 91 | * index: Number - the index of the control to remove. 92 | 93 | 94 | 95 | ## destroy 96 | 97 | Destroy and free the control. 98 | 99 | 100 | 101 | 102 | ## setParent 103 | 104 | Change the parent of the control 105 | 106 | 107 | **Arguments** 108 | 109 | * parent: UiControl - the new parent of the widget or null to detach it. 110 | 111 | 112 | 113 | ## toplevel 114 | 115 | Return whether the control is a top level one or not. 116 | 117 | 118 | 119 | 120 | ## setVisible 121 | 122 | Set the value of property `visible` 123 | 124 | **Arguments** 125 | 126 | * value: Boolean - The new value for `visible` property. 127 | 128 | ## getVisible 129 | 130 | Return the value of property `visible` 131 | 132 | 133 | 134 | ## setEnabled 135 | 136 | Set the value of property `enabled` 137 | 138 | **Arguments** 139 | 140 | * value: Boolean - The new value for `enabled` property. 141 | 142 | ## getEnabled 143 | 144 | Return the value of property `enabled` 145 | 146 | 147 | 148 | ## setPadded 149 | 150 | Set the value of property `padded` 151 | 152 | **Arguments** 153 | 154 | * value: Boolean - The new value for `padded` property. 155 | 156 | ## getPadded 157 | 158 | Return the value of property `padded` 159 | 160 | 161 | 162 | 163 | -------------------------------------------------------------------------------- /docs/checkbox.md: -------------------------------------------------------------------------------- 1 | 2 | # Checkbox 3 | 4 | > A checkbox widget. 5 | 6 | ![UiCheckbox example](media/UiCheckbox.png) 7 | 8 | ```js 9 | var libui = require('libui'); 10 | 11 | var win = new libui.UiWindow('UiCheckbox example', 640, 480, true); 12 | 13 | var widget = new libui.UiCheckbox(); 14 | win.setChild(widget); 15 | 16 | win.onClosing(function () { 17 | win.close(); 18 | libui.stopLoop(); 19 | }); 20 | 21 | win.show(); 22 | 23 | libui.startLoop(); 24 | 25 | ``` 26 | 27 | --- 28 | 29 | # Constructor 30 | 31 | > new libui.UiCheckbox() 32 | 33 | Create a new UiCheckbox object. 34 | 35 | --- 36 | 37 | # Properties 38 | 39 | See [properties implementation](properties.md) for generic details on how properties are implemented. 40 | 41 | 42 | ### visible: Boolean 43 | 44 | Whether the widget should be visible or hidden. 45 | Read write. 46 | Defaults to `true`. 47 | 48 | 49 | 50 | ### enabled: Boolean 51 | 52 | Whether the widget should be enabled or disabled. 53 | Read write. 54 | Defaults to `true`. 55 | 56 | 57 | 58 | ### checked: Boolean 59 | 60 | Whether the checkbox is checked or unchecked. 61 | Read write. 62 | Defaults to false 63 | 64 | 65 | 66 | ### text: String 67 | 68 | The static text of the button. 69 | Read write. 70 | 71 | 72 | 73 | 74 | --- 75 | 76 | # Methods 77 | 78 | 79 | ## destroy 80 | 81 | Destroy and free the control. 82 | 83 | 84 | 85 | 86 | ## setParent 87 | 88 | Change the parent of the control 89 | 90 | 91 | **Arguments** 92 | 93 | * parent: UiControl - the new parent of the widget or null to detach it. 94 | 95 | 96 | 97 | ## toplevel 98 | 99 | Return whether the control is a top level one or not. 100 | 101 | 102 | 103 | 104 | ## setVisible 105 | 106 | Set the value of property `visible` 107 | 108 | **Arguments** 109 | 110 | * value: Boolean - The new value for `visible` property. 111 | 112 | ## getVisible 113 | 114 | Return the value of property `visible` 115 | 116 | 117 | 118 | ## setEnabled 119 | 120 | Set the value of property `enabled` 121 | 122 | **Arguments** 123 | 124 | * value: Boolean - The new value for `enabled` property. 125 | 126 | ## getEnabled 127 | 128 | Return the value of property `enabled` 129 | 130 | 131 | 132 | ## setChecked 133 | 134 | Set the value of property `checked` 135 | 136 | **Arguments** 137 | 138 | * value: Boolean - The new value for `checked` property. 139 | 140 | ## getChecked 141 | 142 | Return the value of property `checked` 143 | 144 | 145 | 146 | ## setText 147 | 148 | Set the value of property `text` 149 | 150 | **Arguments** 151 | 152 | * value: String - The new value for `text` property. 153 | 154 | ## getText 155 | 156 | Return the value of property `text` 157 | 158 | 159 | 160 | --- 161 | 162 | # Events 163 | 164 | See [events implementation](events.md) for generic details on how events are implemented. 165 | 166 | 167 | ### onToggled 168 | 169 | Emitted whenever property `checked` change. 170 | 171 | 172 | 173 | 174 | -------------------------------------------------------------------------------- /docs/entry.md: -------------------------------------------------------------------------------- 1 | 2 | # Entry 3 | 4 | > A simple, single line text entry widget. 5 | 6 | ![UiEntry example](media/UiEntry.png) 7 | 8 | ```js 9 | var libui = require('libui'); 10 | 11 | var win = new libui.UiWindow('UiEntry example', 640, 480, true); 12 | 13 | var widget = new libui.UiEntry(); 14 | win.setChild(widget); 15 | 16 | win.onClosing(function () { 17 | win.close(); 18 | libui.stopLoop(); 19 | }); 20 | 21 | win.show(); 22 | 23 | libui.startLoop(); 24 | 25 | ``` 26 | 27 | --- 28 | 29 | # Constructor 30 | 31 | > new libui.UiEntry() 32 | 33 | Create a new UiEntry object. 34 | 35 | --- 36 | 37 | # Properties 38 | 39 | See [properties implementation](properties.md) for generic details on how properties are implemented. 40 | 41 | 42 | ### visible: Boolean 43 | 44 | Whether the widget should be visible or hidden. 45 | Read write. 46 | Defaults to `true`. 47 | 48 | 49 | 50 | ### enabled: Boolean 51 | 52 | Whether the widget should be enabled or disabled. 53 | Read write. 54 | Defaults to `true`. 55 | 56 | 57 | 58 | ### readOnly: Boolean 59 | 60 | Whether the user is allowed to change the entry text. 61 | Read write. 62 | Defaults to `true`. 63 | 64 | 65 | 66 | ### text: String 67 | 68 | The current text of the entry. 69 | Read write. 70 | 71 | 72 | 73 | 74 | --- 75 | 76 | # Methods 77 | 78 | 79 | ## destroy 80 | 81 | Destroy and free the control. 82 | 83 | 84 | 85 | 86 | ## setParent 87 | 88 | Change the parent of the control 89 | 90 | 91 | **Arguments** 92 | 93 | * parent: UiControl - the new parent of the widget or null to detach it. 94 | 95 | 96 | 97 | ## toplevel 98 | 99 | Return whether the control is a top level one or not. 100 | 101 | 102 | 103 | 104 | ## setVisible 105 | 106 | Set the value of property `visible` 107 | 108 | **Arguments** 109 | 110 | * value: Boolean - The new value for `visible` property. 111 | 112 | ## getVisible 113 | 114 | Return the value of property `visible` 115 | 116 | 117 | 118 | ## setEnabled 119 | 120 | Set the value of property `enabled` 121 | 122 | **Arguments** 123 | 124 | * value: Boolean - The new value for `enabled` property. 125 | 126 | ## getEnabled 127 | 128 | Return the value of property `enabled` 129 | 130 | 131 | 132 | ## setReadOnly 133 | 134 | Set the value of property `readOnly` 135 | 136 | **Arguments** 137 | 138 | * value: Boolean - The new value for `readOnly` property. 139 | 140 | ## getReadOnly 141 | 142 | Return the value of property `readOnly` 143 | 144 | 145 | 146 | ## setText 147 | 148 | Set the value of property `text` 149 | 150 | **Arguments** 151 | 152 | * value: String - The new value for `text` property. 153 | 154 | ## getText 155 | 156 | Return the value of property `text` 157 | 158 | 159 | 160 | --- 161 | 162 | # Events 163 | 164 | See [events implementation](events.md) for generic details on how events are implemented. 165 | 166 | 167 | ### onChanged 168 | 169 | Emitted whenever property `text` change. 170 | 171 | 172 | 173 | 174 | -------------------------------------------------------------------------------- /docs/readme.md: -------------------------------------------------------------------------------- 1 | # libui-node 2 | 3 | These pages document the `libui-node` classes. 4 | 5 | If you are new to the framework, you should start reading basic documentation on how it work: 6 | 7 | * [Initialization & Event Loop](initialization.md) - explains how to initialize the framework and how the event loop works. 8 | * [Properties](properties.md) - explains how widgets properties are implemented by `libui-node`. 9 | * [Events](events.md) - explains how widgets events are implemented by `libui-node`. 10 | * [Containers](containers.md) - explains how you can group widgets in tree hierarchies using different layout strategies. 11 | * [Attributed Strings](attributedstring.md) - explains how you can style text (font, color, underline, ...) 12 | 13 | 14 | ## Containers widgets 15 | * [UiWindow](window.md) - explains how to create and manage OS windows. 16 | * [UiForm](form.md) - A container that organize children as labeled fields. 17 | * [UiGrid](grid.md) - A powerful container that allow to specify size and position of each children. 18 | * [UiVerticalBox](verticalbox.md) - A container that stack its chidren vertically. 19 | * [UiTab](tab.md) - A container that show each chidren in a separate tab. 20 | * [UiHorizontalBox](horizontalbox.md) - A container that stack its chidren horizontally. 21 | * [UiGroup](group.md) - A container for a single widget that provide a caption and visually group it's children. 22 | ## Data entry widgets 23 | 24 | * [UiEntry](entry.md) - A simple, single line text entry widget. 25 | * [UiPasswordEntry](passwordentry.md) - A single line text entry widget that mask the input, useful to edit passwords or other sensible data. 26 | * [UiSearchEntry](searchentry.md) - A single line text entry widget to search text. 27 | * [UiMultilineEntry](multilineentry.md) - A multiline text entry widget. 28 | * [UiDatePicker](datepicker.md) - A widgets to edit dates. 29 | * [UiTimePicker](timepicker.md) - A widgets to edit times. 30 | * [UiDateTimePicker](datetimepicker.md) - A widgets to edit date/times. 31 | * [UiCheckbox](checkbox.md) - A checkbox widget. 32 | * [UiSpinbox](spinbox.md) - An entry widget for numerical values. 33 | * [UiSlider](slider.md) - Horizontal slide to set numerical values. 34 | * [UiCombobox](combobox.md) - A drop down combo box that allow list selection only. 35 | * [UiRadioButtons](radiobuttons.md) - A widget that represent a group of radio options. 36 | * [UiEditableCombobox](editablecombobox.md) - A drop down combo box that allow selection from list or free text entry. 37 | 38 | ## Static widgets 39 | 40 | * [UiLabel](label.md) - A static text label. 41 | * [UiVerticalSeparator](verticalseparator.md) - A vertical line to visually separate widgets. 42 | * [UiHorizontalSeparator](horizontalseparator.md) - An horizontal line to visually separate widgets. 43 | * [UiProgressBar](progressbar.md) - Progress bar widget. 44 | 45 | ## Buttons 46 | 47 | * [UiButton](button.md) - A simple button. 48 | * [UiColorButton](colorbutton.md) - A button that opens a color palette popup. 49 | * [UiFontButton](fontbutton.md) - A button that opens a font chooser. 50 | -------------------------------------------------------------------------------- /docs/searchentry.md: -------------------------------------------------------------------------------- 1 | 2 | # SearchEntry 3 | 4 | > A single line text entry widget to search text. 5 | 6 | 7 | 8 | ```js 9 | var libui = require('libui'); 10 | 11 | var win = new libui.UiWindow('UiSearchEntry example', 640, 480, true); 12 | 13 | var widget = new libui.UiSearchEntry(); 14 | win.setChild(widget); 15 | 16 | win.onClosing(function () { 17 | win.close(); 18 | libui.stopLoop(); 19 | }); 20 | 21 | win.show(); 22 | 23 | libui.startLoop(); 24 | 25 | ``` 26 | 27 | --- 28 | 29 | # Constructor 30 | 31 | > new libui.UiSearchEntry() 32 | 33 | Create a new UiSearchEntry object. 34 | 35 | --- 36 | 37 | # Properties 38 | 39 | See [properties implementation](properties.md) for generic details on how properties are implemented. 40 | 41 | 42 | ### visible: Boolean 43 | 44 | Whether the widget should be visible or hidden. 45 | Read write. 46 | Defaults to `true`. 47 | 48 | 49 | 50 | ### enabled: Boolean 51 | 52 | Whether the widget should be enabled or disabled. 53 | Read write. 54 | Defaults to `true`. 55 | 56 | 57 | 58 | ### readOnly: Boolean 59 | 60 | Whether the user is allowed to change the entry text. 61 | Read write. 62 | Defaults to `true`. 63 | 64 | 65 | 66 | ### text: String 67 | 68 | The current text of the entry. 69 | Read write. 70 | 71 | 72 | 73 | 74 | --- 75 | 76 | # Methods 77 | 78 | 79 | ## destroy 80 | 81 | Destroy and free the control. 82 | 83 | 84 | 85 | 86 | ## setParent 87 | 88 | Change the parent of the control 89 | 90 | 91 | **Arguments** 92 | 93 | * parent: UiControl - the new parent of the widget or null to detach it. 94 | 95 | 96 | 97 | ## toplevel 98 | 99 | Return whether the control is a top level one or not. 100 | 101 | 102 | 103 | 104 | ## setVisible 105 | 106 | Set the value of property `visible` 107 | 108 | **Arguments** 109 | 110 | * value: Boolean - The new value for `visible` property. 111 | 112 | ## getVisible 113 | 114 | Return the value of property `visible` 115 | 116 | 117 | 118 | ## setEnabled 119 | 120 | Set the value of property `enabled` 121 | 122 | **Arguments** 123 | 124 | * value: Boolean - The new value for `enabled` property. 125 | 126 | ## getEnabled 127 | 128 | Return the value of property `enabled` 129 | 130 | 131 | 132 | ## setReadOnly 133 | 134 | Set the value of property `readOnly` 135 | 136 | **Arguments** 137 | 138 | * value: Boolean - The new value for `readOnly` property. 139 | 140 | ## getReadOnly 141 | 142 | Return the value of property `readOnly` 143 | 144 | 145 | 146 | ## setText 147 | 148 | Set the value of property `text` 149 | 150 | **Arguments** 151 | 152 | * value: String - The new value for `text` property. 153 | 154 | ## getText 155 | 156 | Return the value of property `text` 157 | 158 | 159 | 160 | --- 161 | 162 | # Events 163 | 164 | See [events implementation](events.md) for generic details on how events are implemented. 165 | 166 | 167 | ### onChanged 168 | 169 | Emitted whenever property `text` change. 170 | 171 | 172 | 173 | 174 | -------------------------------------------------------------------------------- /examples/node-pad.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const {readFile, writeFile} = require('fs'); 3 | const libui = require('..'); 4 | 5 | const {label, window, tab, menu, multilineEntry} = require('./utils.js'); 6 | 7 | const onClosing = () => libui.stopLoop(); 8 | 9 | libui.Ui.onShouldQuit(() => { 10 | onClosing(); 11 | }); 12 | 13 | const winProps = { 14 | hasMenubar: true, 15 | title: 'Node Pad', 16 | width: 640, 17 | height: 480, 18 | onClosing 19 | }; 20 | 21 | let win = null; 22 | let editor; 23 | let status; 24 | let currentFileName = ''; 25 | 26 | function newFile() { 27 | editor.text = ''; 28 | currentFileName = ''; 29 | status.text = 'Not saved'; 30 | } 31 | 32 | function openFile() { 33 | const filename = libui.UiDialogs.openFile(win); 34 | if (filename) { 35 | readFile(filename, 'utf8', (err, content) => { 36 | if (err) { 37 | return libui.UiDialogs.msgBoxError( 38 | win, 39 | 'Error while reading file', 40 | err.stack); 41 | } 42 | editor.text = content; 43 | status.text = filename; 44 | currentFileName = filename; 45 | }); 46 | } 47 | } 48 | 49 | function saveFileAs() { 50 | const filename = libui.UiDialogs.saveFile(win); 51 | if (filename) { 52 | currentFileName = filename; 53 | writeFile(currentFileName, editor.text, err => { 54 | if (err) { 55 | return libui.UiDialogs.msgBoxError( 56 | win, 57 | 'Error while writing file', 58 | err.stack); 59 | } 60 | }); 61 | } 62 | } 63 | 64 | function saveFile() { 65 | if (!currentFileName) { 66 | return saveFileAs(); 67 | } 68 | 69 | writeFile(currentFileName, editor.text, err => { 70 | if (err) { 71 | return libui.UiDialogs.msgBoxError( 72 | win, 73 | 'Error while writing file', 74 | err.stack); 75 | } 76 | }); 77 | } 78 | 79 | menu([ 80 | { 81 | label: 'File', 82 | submenu: [ 83 | { 84 | label: 'New file', 85 | click: newFile 86 | }, 87 | { 88 | label: 'Open', 89 | click: openFile 90 | }, 91 | // { 92 | // label: 'Close current tab', 93 | // click: () => {} 94 | // }, 95 | { 96 | label: 'Save', 97 | click: saveFile 98 | }, 99 | { 100 | label: 'Save as', 101 | click: saveFileAs 102 | }, 103 | { 104 | role: 'quit' 105 | } 106 | ] 107 | }, 108 | { 109 | label: 'Edit', 110 | submenu: [ 111 | { 112 | label: 'Copy' 113 | }, 114 | { 115 | label: 'Paste' 116 | }, 117 | { 118 | label: 'Cut' 119 | }, 120 | { 121 | label: 'Select all' 122 | } 123 | ] 124 | }, 125 | { 126 | label: 'Help', 127 | submenu: [ 128 | { 129 | label: 'Help', 130 | click: () => {} 131 | }, 132 | { 133 | role: 'about' 134 | } 135 | ] 136 | } 137 | ]); 138 | 139 | win = window( 140 | winProps, 141 | tab( 142 | {stretchy: true}, 143 | (editor = multilineEntry({stretchy: true, tabTitle: 'New file'}))), 144 | (status = label({stretchy: false, text: 'Not saved'}))); 145 | 146 | win.show(); 147 | libui.startLoop(); 148 | -------------------------------------------------------------------------------- /docs/group.md: -------------------------------------------------------------------------------- 1 | 2 | # Group 3 | 4 | > A container for a single widget that provide a caption and visually group it's children. 5 | 6 | ![UiGroup example](media/UiGroup.png) 7 | 8 | ```js 9 | var libui = require('libui'); 10 | 11 | var win = new libui.UiWindow('UiGroup example', 640, 480, true); 12 | 13 | var widget = new libui.UiGroup(); 14 | win.setChild(widget); 15 | 16 | win.onClosing(function () { 17 | win.close(); 18 | libui.stopLoop(); 19 | }); 20 | 21 | win.show(); 22 | 23 | libui.startLoop(); 24 | 25 | ``` 26 | 27 | --- 28 | 29 | # Constructor 30 | 31 | > new libui.UiGroup() 32 | 33 | Create a new UiGroup object. 34 | 35 | --- 36 | 37 | # Properties 38 | 39 | See [properties implementation](properties.md) for generic details on how properties are implemented. 40 | 41 | 42 | ### visible: Boolean 43 | 44 | Whether the widget should be visible or hidden. 45 | Read write. 46 | Defaults to `true`. 47 | 48 | 49 | 50 | ### enabled: Boolean 51 | 52 | Whether the widget should be enabled or disabled. 53 | Read write. 54 | Defaults to `true`. 55 | 56 | 57 | 58 | ### margined: Boolean 59 | 60 | This property specify if the group content area should have a margin or not. 61 | Defaults to false. 62 | 63 | 64 | 65 | ### title: String 66 | 67 | This property specify the caption of the group. 68 | Defaults to empty string. 69 | 70 | 71 | 72 | 73 | --- 74 | 75 | # Methods 76 | 77 | 78 | ## setChild 79 | 80 | Set the child widget of the group. 81 | 82 | 83 | **Arguments** 84 | 85 | * control: UiControl - the control to append. 86 | 87 | 88 | 89 | ## destroy 90 | 91 | Destroy and free the control. 92 | 93 | 94 | 95 | 96 | ## setParent 97 | 98 | Change the parent of the control 99 | 100 | 101 | **Arguments** 102 | 103 | * parent: UiControl - the new parent of the widget or null to detach it. 104 | 105 | 106 | 107 | ## toplevel 108 | 109 | Return whether the control is a top level one or not. 110 | 111 | 112 | 113 | 114 | ## setVisible 115 | 116 | Set the value of property `visible` 117 | 118 | **Arguments** 119 | 120 | * value: Boolean - The new value for `visible` property. 121 | 122 | ## getVisible 123 | 124 | Return the value of property `visible` 125 | 126 | 127 | 128 | ## setEnabled 129 | 130 | Set the value of property `enabled` 131 | 132 | **Arguments** 133 | 134 | * value: Boolean - The new value for `enabled` property. 135 | 136 | ## getEnabled 137 | 138 | Return the value of property `enabled` 139 | 140 | 141 | 142 | ## setMargined 143 | 144 | Set the value of property `margined` 145 | 146 | **Arguments** 147 | 148 | * value: Boolean - The new value for `margined` property. 149 | 150 | ## getMargined 151 | 152 | Return the value of property `margined` 153 | 154 | 155 | 156 | ## setTitle 157 | 158 | Set the value of property `title` 159 | 160 | **Arguments** 161 | 162 | * value: String - The new value for `title` property. 163 | 164 | ## getTitle 165 | 166 | Return the value of property `title` 167 | 168 | 169 | 170 | 171 | -------------------------------------------------------------------------------- /docs/passwordentry.md: -------------------------------------------------------------------------------- 1 | 2 | # PasswordEntry 3 | 4 | > A single line text entry widget that mask the input, useful to edit passwords or other sensible data. 5 | 6 | 7 | 8 | ```js 9 | var libui = require('libui'); 10 | 11 | var win = new libui.UiWindow('UiPasswordEntry example', 640, 480, true); 12 | 13 | var widget = new libui.UiPasswordEntry(); 14 | win.setChild(widget); 15 | 16 | win.onClosing(function () { 17 | win.close(); 18 | libui.stopLoop(); 19 | }); 20 | 21 | win.show(); 22 | 23 | libui.startLoop(); 24 | 25 | ``` 26 | 27 | --- 28 | 29 | # Constructor 30 | 31 | > new libui.UiPasswordEntry() 32 | 33 | Create a new UiPasswordEntry object. 34 | 35 | --- 36 | 37 | # Properties 38 | 39 | See [properties implementation](properties.md) for generic details on how properties are implemented. 40 | 41 | 42 | ### visible: Boolean 43 | 44 | Whether the widget should be visible or hidden. 45 | Read write. 46 | Defaults to `true`. 47 | 48 | 49 | 50 | ### enabled: Boolean 51 | 52 | Whether the widget should be enabled or disabled. 53 | Read write. 54 | Defaults to `true`. 55 | 56 | 57 | 58 | ### readOnly: Boolean 59 | 60 | Whether the user is allowed to change the entry text. 61 | Read write. 62 | Defaults to `true`. 63 | 64 | 65 | 66 | ### text: String 67 | 68 | The current text of the entry. 69 | Read write. 70 | 71 | 72 | 73 | 74 | --- 75 | 76 | # Methods 77 | 78 | 79 | ## destroy 80 | 81 | Destroy and free the control. 82 | 83 | 84 | 85 | 86 | ## setParent 87 | 88 | Change the parent of the control 89 | 90 | 91 | **Arguments** 92 | 93 | * parent: UiControl - the new parent of the widget or null to detach it. 94 | 95 | 96 | 97 | ## toplevel 98 | 99 | Return whether the control is a top level one or not. 100 | 101 | 102 | 103 | 104 | ## setVisible 105 | 106 | Set the value of property `visible` 107 | 108 | **Arguments** 109 | 110 | * value: Boolean - The new value for `visible` property. 111 | 112 | ## getVisible 113 | 114 | Return the value of property `visible` 115 | 116 | 117 | 118 | ## setEnabled 119 | 120 | Set the value of property `enabled` 121 | 122 | **Arguments** 123 | 124 | * value: Boolean - The new value for `enabled` property. 125 | 126 | ## getEnabled 127 | 128 | Return the value of property `enabled` 129 | 130 | 131 | 132 | ## setReadOnly 133 | 134 | Set the value of property `readOnly` 135 | 136 | **Arguments** 137 | 138 | * value: Boolean - The new value for `readOnly` property. 139 | 140 | ## getReadOnly 141 | 142 | Return the value of property `readOnly` 143 | 144 | 145 | 146 | ## setText 147 | 148 | Set the value of property `text` 149 | 150 | **Arguments** 151 | 152 | * value: String - The new value for `text` property. 153 | 154 | ## getText 155 | 156 | Return the value of property `text` 157 | 158 | 159 | 160 | --- 161 | 162 | # Events 163 | 164 | See [events implementation](events.md) for generic details on how events are implemented. 165 | 166 | 167 | ### onChanged 168 | 169 | Emitted whenever property `text` change. 170 | 171 | 172 | 173 | 174 | -------------------------------------------------------------------------------- /docs/multilineentry.md: -------------------------------------------------------------------------------- 1 | 2 | # MultilineEntry 3 | 4 | > A multiline text entry widget. 5 | 6 | ![UiMultilineEntry example](media/UiMultilineEntry.png) 7 | 8 | ```js 9 | var libui = require('libui'); 10 | 11 | var win = new libui.UiWindow('UiMultilineEntry example', 640, 480, true); 12 | 13 | var widget = new libui.UiMultilineEntry(); 14 | win.setChild(widget); 15 | 16 | win.onClosing(function () { 17 | win.close(); 18 | libui.stopLoop(); 19 | }); 20 | 21 | win.show(); 22 | 23 | libui.startLoop(); 24 | 25 | ``` 26 | 27 | --- 28 | 29 | # Constructor 30 | 31 | > new libui.UiMultilineEntry() 32 | 33 | Create a new UiMultilineEntry object. 34 | 35 | --- 36 | 37 | # Properties 38 | 39 | See [properties implementation](properties.md) for generic details on how properties are implemented. 40 | 41 | 42 | ### visible: Boolean 43 | 44 | Whether the widget should be visible or hidden. 45 | Read write. 46 | Defaults to `true`. 47 | 48 | 49 | 50 | ### enabled: Boolean 51 | 52 | Whether the widget should be enabled or disabled. 53 | Read write. 54 | Defaults to `true`. 55 | 56 | 57 | 58 | ### readOnly: Boolean 59 | 60 | Whether the user is allowed to change the entry text. 61 | Read write. 62 | Defaults to `true`. 63 | 64 | 65 | 66 | ### text: String 67 | 68 | The current text of the multiline entry. 69 | Read write. 70 | 71 | 72 | 73 | 74 | --- 75 | 76 | # Methods 77 | 78 | 79 | ## append 80 | 81 | Append specified text to the entry content. 82 | 83 | 84 | **Arguments** 85 | 86 | * text: String - the text to append. 87 | 88 | 89 | 90 | ## destroy 91 | 92 | Destroy and free the control. 93 | 94 | 95 | 96 | 97 | ## setParent 98 | 99 | Change the parent of the control 100 | 101 | 102 | **Arguments** 103 | 104 | * parent: UiControl - the new parent of the widget or null to detach it. 105 | 106 | 107 | 108 | ## toplevel 109 | 110 | Return whether the control is a top level one or not. 111 | 112 | 113 | 114 | 115 | ## setVisible 116 | 117 | Set the value of property `visible` 118 | 119 | **Arguments** 120 | 121 | * value: Boolean - The new value for `visible` property. 122 | 123 | ## getVisible 124 | 125 | Return the value of property `visible` 126 | 127 | 128 | 129 | ## setEnabled 130 | 131 | Set the value of property `enabled` 132 | 133 | **Arguments** 134 | 135 | * value: Boolean - The new value for `enabled` property. 136 | 137 | ## getEnabled 138 | 139 | Return the value of property `enabled` 140 | 141 | 142 | 143 | ## setReadOnly 144 | 145 | Set the value of property `readOnly` 146 | 147 | **Arguments** 148 | 149 | * value: Boolean - The new value for `readOnly` property. 150 | 151 | ## getReadOnly 152 | 153 | Return the value of property `readOnly` 154 | 155 | 156 | 157 | ## setText 158 | 159 | Set the value of property `text` 160 | 161 | **Arguments** 162 | 163 | * value: String - The new value for `text` property. 164 | 165 | ## getText 166 | 167 | Return the value of property `text` 168 | 169 | 170 | 171 | --- 172 | 173 | # Events 174 | 175 | See [events implementation](events.md) for generic details on how events are implemented. 176 | 177 | 178 | ### onChanged 179 | 180 | Emitted whenever property `text` change. 181 | 182 | 183 | 184 | 185 | -------------------------------------------------------------------------------- /src/UiArea/DrawMatrix.cc: -------------------------------------------------------------------------------- 1 | #include "area.h" 2 | #include "ui.h" 3 | 4 | UiDrawMatrix::UiDrawMatrix() { 5 | m = new uiDrawMatrix(); 6 | } 7 | 8 | UiDrawMatrix::~UiDrawMatrix() { 9 | delete m; 10 | } 11 | 12 | double UiDrawMatrix::getM11() { 13 | return m->M11; 14 | } 15 | 16 | uiDrawMatrix *UiDrawMatrix::getStruct() { 17 | return m; 18 | } 19 | 20 | double UiDrawMatrix::getM12() { 21 | return m->M12; 22 | } 23 | 24 | double UiDrawMatrix::getM21() { 25 | return m->M21; 26 | } 27 | 28 | double UiDrawMatrix::getM22() { 29 | return m->M22; 30 | } 31 | 32 | double UiDrawMatrix::getM31() { 33 | return m->M31; 34 | } 35 | 36 | double UiDrawMatrix::getM32() { 37 | return m->M32; 38 | } 39 | 40 | void UiDrawMatrix::setM11(double value) { 41 | m->M11 = value; 42 | } 43 | 44 | void UiDrawMatrix::setM12(double value) { 45 | m->M12 = value; 46 | } 47 | 48 | void UiDrawMatrix::setM21(double value) { 49 | m->M21 = value; 50 | } 51 | 52 | void UiDrawMatrix::setM22(double value) { 53 | m->M22 = value; 54 | } 55 | 56 | void UiDrawMatrix::setM31(double value) { 57 | m->M31 = value; 58 | } 59 | 60 | void UiDrawMatrix::setM32(double value) { 61 | m->M32 = value; 62 | } 63 | 64 | void UiDrawMatrix::setIdentity() { 65 | uiDrawMatrixSetIdentity(m); 66 | } 67 | 68 | void UiDrawMatrix::translate(double x, double y) { 69 | uiDrawMatrixTranslate(m, x, y); 70 | } 71 | 72 | void UiDrawMatrix::scale(double xCenter, double yCenter, double x, double y) { 73 | uiDrawMatrixScale(m, xCenter, yCenter, x, y); 74 | } 75 | 76 | void UiDrawMatrix::rotate(double x, double y, double amount) { 77 | uiDrawMatrixRotate(m, x, y, amount); 78 | } 79 | 80 | void UiDrawMatrix::skew(double x, double y, double xamount, double yamount) { 81 | uiDrawMatrixSkew(m, x, y, xamount, yamount); 82 | } 83 | 84 | void UiDrawMatrix::multiply(UiDrawMatrix *src) { 85 | uiDrawMatrixMultiply(m, src->getStruct()); 86 | } 87 | 88 | int UiDrawMatrix::invertible() { 89 | return uiDrawMatrixInvertible(m); 90 | } 91 | 92 | int UiDrawMatrix::invert() { 93 | return uiDrawMatrixInvert(m); 94 | } 95 | 96 | PointDouble UiDrawMatrix::transformPoint(PointDouble value) { 97 | double x = value.getX(); 98 | double y = value.getY(); 99 | uiDrawMatrixTransformPoint(m, &x, &y); 100 | return PointDouble(x, y); 101 | } 102 | 103 | SizeDouble UiDrawMatrix::transformSize(SizeDouble value) { 104 | double x = value.getWidth(); 105 | double y = value.getHeight(); 106 | uiDrawMatrixTransformSize(m, &x, &y); 107 | return SizeDouble(x, y); 108 | } 109 | 110 | NBIND_CLASS(UiDrawMatrix) { 111 | construct<>(); 112 | method(getM11); 113 | method(getM12); 114 | method(getM21); 115 | method(getM22); 116 | method(getM31); 117 | method(getM32); 118 | method(setM11); 119 | method(setM12); 120 | method(setM21); 121 | method(setM22); 122 | method(setM31); 123 | method(setM32); 124 | 125 | getset(getM11, setM11); 126 | getset(getM12, setM12); 127 | getset(getM21, setM21); 128 | getset(getM22, setM22); 129 | getset(getM31, setM31); 130 | getset(getM32, setM32); 131 | 132 | method(setIdentity); 133 | method(translate); 134 | method(scale); 135 | method(rotate); 136 | method(skew); 137 | method(multiply); 138 | method(invertible); 139 | method(invert); 140 | method(transformPoint); 141 | method(transformSize); 142 | } 143 | -------------------------------------------------------------------------------- /docs/tab.md: -------------------------------------------------------------------------------- 1 | 2 | # Tab 3 | 4 | > A container that show each chidren in a separate tab. 5 | 6 | ![UiTab example](media/UiTab.png) 7 | 8 | ```js 9 | var libui = require('libui'); 10 | 11 | var win = new libui.UiWindow('UiTab example', 640, 480, true); 12 | 13 | var widget = new libui.UiTab(); 14 | win.setChild(widget); 15 | 16 | win.onClosing(function () { 17 | win.close(); 18 | libui.stopLoop(); 19 | }); 20 | 21 | win.show(); 22 | 23 | libui.startLoop(); 24 | 25 | ``` 26 | 27 | --- 28 | 29 | # Constructor 30 | 31 | > new libui.UiTab() 32 | 33 | Create a new UiTab object. 34 | 35 | --- 36 | 37 | # Properties 38 | 39 | See [properties implementation](properties.md) for generic details on how properties are implemented. 40 | 41 | 42 | ### visible: Boolean 43 | 44 | Whether the widget should be visible or hidden. 45 | Read write. 46 | Defaults to `true`. 47 | 48 | 49 | 50 | ### enabled: Boolean 51 | 52 | Whether the widget should be enabled or disabled. 53 | Read write. 54 | Defaults to `true`. 55 | 56 | 57 | 58 | 59 | --- 60 | 61 | # Methods 62 | 63 | 64 | ## append 65 | 66 | Append a new child widget as last tab. 67 | 68 | 69 | **Arguments** 70 | 71 | * label: String - the text to show in the new tab caption. 72 | * control: UiControl - the control to append. 73 | 74 | 75 | 76 | ## insertAt 77 | 78 | Insert a new child widget before specified position. 79 | 80 | 81 | **Arguments** 82 | 83 | * label: String - the text to show in the new tab caption. 84 | * before: Number - the control will be inserted before this position 85 | * control: UiControl - the control to insert. 86 | 87 | 88 | 89 | ## deleteAt 90 | 91 | Remove the tab and widget at specified position. 92 | 93 | 94 | **Arguments** 95 | 96 | * index: Number - the index of the tab to remove. 97 | 98 | 99 | 100 | ## setMargined 101 | 102 | Specifies that a tab should use a margin around its content. 103 | 104 | 105 | **Arguments** 106 | 107 | * page: Number - the index of the tab. 108 | * margined: Boolean - whether to display a margin or not. 109 | 110 | 111 | 112 | ## getMargined 113 | 114 | Return a boolean that indicate if a tab is displaying a margin around its content. 115 | 116 | 117 | **Arguments** 118 | 119 | * page: Number - the index of the tab. 120 | 121 | 122 | 123 | ## numPages 124 | 125 | Return the total number of tab pages contained in the widgets. 126 | 127 | 128 | 129 | 130 | ## destroy 131 | 132 | Destroy and free the control. 133 | 134 | 135 | 136 | 137 | ## setParent 138 | 139 | Change the parent of the control 140 | 141 | 142 | **Arguments** 143 | 144 | * parent: UiControl - the new parent of the widget or null to detach it. 145 | 146 | 147 | 148 | ## toplevel 149 | 150 | Return whether the control is a top level one or not. 151 | 152 | 153 | 154 | 155 | ## setVisible 156 | 157 | Set the value of property `visible` 158 | 159 | **Arguments** 160 | 161 | * value: Boolean - The new value for `visible` property. 162 | 163 | ## getVisible 164 | 165 | Return the value of property `visible` 166 | 167 | 168 | 169 | ## setEnabled 170 | 171 | Set the value of property `enabled` 172 | 173 | **Arguments** 174 | 175 | * value: Boolean - The new value for `enabled` property. 176 | 177 | ## getEnabled 178 | 179 | Return the value of property `enabled` 180 | 181 | 182 | 183 | 184 | -------------------------------------------------------------------------------- /docs/window.md: -------------------------------------------------------------------------------- 1 | # Window 2 | 3 | > Create and control windows. 4 | 5 | ```js 6 | var libui = require('libui'); 7 | 8 | var win = new libui.UiWindow("Example window", 640, 480, true); 9 | 10 | win.onClosing(function () { 11 | libui.stopLoop(); 12 | }); 13 | 14 | libui.startLoop(); 15 | win.show(); 16 | ``` 17 | 18 | The UiWindow class is responsible to show and manage native windows. 19 | UiWindow instance could contains only one control. If you need more, you have to use [Containers](containers.md). 20 | 21 | --- 22 | 23 | # Constructor 24 | 25 | > new libui.UiWindow() 26 | 27 | Create a new UiWindow object. 28 | 29 | ### Arguments 30 | 31 | * title: String - text to show in window title bar. 32 | * width: Number - width of window in pixels 33 | * height: Number - height of window in pixels 34 | * hasMenubar: Boolean - specify that this window has a menu bar. See [Menu](#menubar) 35 | 36 | --- 37 | 38 | # Properties 39 | 40 | See [properties implementation](properties.md) for generic details on how properties are implemented. 41 | 42 | ## margined: Bool 43 | 44 | This property specify if the window content should have a margin or not. 45 | It defaults to false. 46 | 47 | 48 | ![image](https://cloud.githubusercontent.com/assets/11197111/16465935/804a30d4-3e41-11e6-8189-150e8cddc152.png) 49 | 50 | A window with `margined: false` 51 | 52 | 53 | ![image](https://cloud.githubusercontent.com/assets/11197111/16465906/68304cfe-3e41-11e6-8ae0-3123205ee136.png) 54 | 55 | Same window with `margined: true` 56 | 57 | ## title: String 58 | 59 | Set or return the text to show in window title bar. 60 | 61 | ## position: [Point](point.md) 62 | 63 | Set or return the position in pixel relative to the top-left window angle. 64 | 65 | 66 | ## contentSize: [Size](size.md) 67 | 68 | Set or return the size in pixel of the content area of the window. Window decoration size are excluded. This mean that if you set window size to 0,0 you still see title bar and OS window buttons. 69 | 70 | ## fullscreen: Boolean 71 | 72 | Whether the window should show in fullscreen or not. 73 | 74 | ## borderless: Boolean 75 | 76 | Allow to specify that the window is a frameless one, without borders, title bar and OS window control widgets. 77 | 78 | 79 | ![image](https://cloud.githubusercontent.com/assets/11197111/16465986/b1befd0c-3e41-11e6-8421-20c106a096f0.png) 80 | 81 | A window with `borderless: true` 82 | 83 | --- 84 | 85 | # Methods 86 | 87 | ## show 88 | 89 | Show the window. 90 | 91 | 92 | ## close 93 | 94 | Close the window. 95 | 96 | ## setChild 97 | 98 | Allow to specify the control to show in window content area. UiWindow instances can contain only one control. If you need more, you have to use [Containers](containers.md). 99 | 100 | ### Arguments 101 | 102 | * control: UiControl - the control to use in window content area. 103 | 104 | 105 | ## center 106 | 107 | Center the window on screen, both horizontally and vertically. 108 | 109 | --- 110 | 111 | # Events 112 | 113 | See [events implementation](events.md) for generic details on how events are implemented. 114 | 115 | ## onClosing 116 | 117 | Emitted when the OS window close button is clicked. You are responsible to close window in response to this event. 118 | 119 | ```js 120 | win.onClosing(function() { 121 | win.close(); 122 | }); 123 | ``` 124 | 125 | ## onPositionChanged 126 | 127 | Emitted when the window position on screen changed, on when fullscreen state change. 128 | 129 | 130 | ## onContentSizeChanged 131 | 132 | Emitted when window content size change. 133 | -------------------------------------------------------------------------------- /src/Font/AttributedString.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "area.h" 3 | #include "ui.h" 4 | 5 | AttributedString::AttributedString(uiAttributedString *str) { 6 | s = str; 7 | } 8 | 9 | AttributedString::AttributedString(const char *str) { 10 | s = uiNewAttributedString(str); 11 | } 12 | 13 | AttributedString::~AttributedString() { 14 | uiFreeAttributedString(s); 15 | } 16 | 17 | uiAttributedString *AttributedString::getHandle() { 18 | return s; 19 | } 20 | 21 | const char *AttributedString::toString() { 22 | return uiAttributedStringString(s); 23 | } 24 | 25 | size_t AttributedString::toStringLen() { 26 | return uiAttributedStringLen(s); 27 | } 28 | 29 | void AttributedString::appendUnattributed(const char *str) { 30 | uiAttributedStringAppendUnattributed(s, str); 31 | } 32 | 33 | void AttributedString::insertUnattributed(const char *str, size_t at) { 34 | uiAttributedStringInsertAtUnattributed(s, str, at); 35 | } 36 | 37 | void AttributedString::deleteString(size_t start, size_t end) { 38 | uiAttributedStringDelete(s, start, end); 39 | } 40 | 41 | void AttributedString::setAttribute(FontAttribute *attr, size_t start, 42 | size_t end) { 43 | uiAttributedStringSetAttribute(s, attr->getHandle(), start, end); 44 | attr->setAppended(); 45 | } 46 | 47 | typedef struct { 48 | AttributedString *str; 49 | nbind::cbFunction *cb; 50 | } ForEachData; 51 | 52 | static uiForEach AttributedString__forEach(const uiAttributedString *s, 53 | const uiAttribute *a, size_t start, 54 | size_t end, void *d) { 55 | ForEachData *data = (ForEachData *)d; 56 | 57 | FontAttribute f = FontAttribute((uiAttribute *)a); 58 | f.setAppended(); 59 | 60 | unsigned int v = data->cb->call(data->str, f, start, end); 61 | 62 | return v ? uiForEachStop : uiForEachContinue; 63 | } 64 | 65 | void AttributedString::forEach(nbind::cbFunction &cb) { 66 | ForEachData d = {this, &cb}; 67 | uiAttributedStringForEachAttribute(s, AttributedString__forEach, &d); 68 | } 69 | 70 | void AttributedString::appendAttributedInternal( 71 | const char *str, std::vector attrs) { 72 | size_t start = this->toStringLen(); 73 | size_t end = start + strlen(str); 74 | 75 | this->appendUnattributed(str); 76 | for (std::vector::size_type i = 0; i < attrs.size(); i++) { 77 | this->setAttribute(attrs[i], start, end); 78 | } 79 | } 80 | 81 | void AttributedString::insertAttributedInternal( 82 | const char *str, size_t start, std::vector attrs) { 83 | size_t end = start + strlen(str); 84 | 85 | this->insertUnattributed(str, start); 86 | for (std::vector::size_type i = 0; i < attrs.size(); i++) { 87 | this->setAttribute(attrs[i], start, end); 88 | } 89 | } 90 | 91 | size_t AttributedString::numGraphemes() { 92 | return uiAttributedStringNumGraphemes(s); 93 | } 94 | 95 | size_t AttributedString::byteIndexToGrapheme(size_t pos) { 96 | return uiAttributedStringByteIndexToGrapheme(s, pos); 97 | } 98 | 99 | size_t AttributedString::graphemeToByteIndex(size_t pos) { 100 | return uiAttributedStringGraphemeToByteIndex(s, pos); 101 | } 102 | 103 | NBIND_CLASS(AttributedString) { 104 | construct(); 105 | method(toString); 106 | method(toStringLen); 107 | method(appendUnattributed); 108 | method(insertUnattributed); 109 | method(forEach); 110 | method(appendAttributedInternal); 111 | method(insertAttributedInternal); 112 | method(deleteString); 113 | method(setAttribute); 114 | 115 | method(numGraphemes); 116 | method(byteIndexToGrapheme); 117 | method(graphemeToByteIndex); 118 | } 119 | -------------------------------------------------------------------------------- /examples/check-control-destroy.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable unicorn/filename-case */ 2 | 3 | const libui = require('..'); 4 | const mnu = new libui.UiMenu('mnu'); 5 | const mnuItem = mnu.appendItem('click me'); 6 | mnuItem.onClicked(() => { 7 | console.log(`menu clicked ${mnuItem}`); 8 | }); 9 | 10 | function createWindow() { 11 | const win = new libui.UiWindow('UiSpinbox example', 320, 60, true); 12 | 13 | win.margined = true; 14 | 15 | const widget1 = new libui.UiSpinbox(); 16 | widget1.value = 42; 17 | widget1.onChanged(() => { 18 | console.log(`widget1 changed to ${widget1.value}`); 19 | }); 20 | 21 | const widget2 = new libui.UiButton('btn1'); 22 | widget2.onClicked(() => { 23 | widget6.setEnabled(false); 24 | console.log(`${widget2.text} clicked`); 25 | }); 26 | 27 | const widget3 = new libui.UiCheckbox('chk1'); 28 | widget3.onToggled(() => { 29 | console.log(`${widget3.text} toggled`); 30 | }); 31 | 32 | const widget4 = new libui.UiColorButton(); 33 | widget4.onChanged(() => { 34 | console.log(`widget4 changed to ${widget4.color}`); 35 | }); 36 | 37 | const widget5 = new libui.UiCombobox(); 38 | widget5.append('a'); 39 | widget5.append('b'); 40 | widget5.onSelected(() => { 41 | console.log(`widget5 changed to ${widget5.selected}`); 42 | }); 43 | 44 | const widget6 = new libui.UiEditableCombobox(); 45 | widget6.append('sally'); 46 | widget6.append('tati'); 47 | widget6.append('parro'); 48 | widget6.onChanged(() => { 49 | console.log(`widget6 changed to ${widget6.text}`); 50 | }); 51 | 52 | const widget7 = new libui.UiSearchEntry(); 53 | widget7.onChanged(() => { 54 | console.log(`${widget7.text} changed`); 55 | }); 56 | 57 | const widget8 = new libui.UiPasswordEntry(); 58 | widget8.onChanged(() => { 59 | console.log(`${widget8.text} changed`); 60 | }); 61 | 62 | const widget9 = new libui.UiEntry(); 63 | widget9.onChanged(() => { 64 | console.log(`${widget9.text} changed`); 65 | }); 66 | 67 | const widget10 = new libui.UiFontButton(); 68 | widget10.onChanged(() => { 69 | console.log(`${widget10.text} changed`); 70 | }); 71 | 72 | const widget11 = new libui.UiMultilineEntry(); 73 | widget11.onChanged(() => { 74 | console.log(`${widget11.text} changed`); 75 | }); 76 | 77 | const widget12 = new libui.UiRadioButtons(); 78 | widget12.append('a'); 79 | widget12.append('b'); 80 | widget12.onSelected(() => { 81 | console.log(`widget12 changed to ${widget12.selected}`); 82 | }); 83 | 84 | const widget13 = new libui.UiSlider(); 85 | widget13.onChanged(() => { 86 | console.log(`widget13 changed to ${widget13.value}`); 87 | }); 88 | 89 | const box = new libui.UiVerticalBox(); 90 | box.append(widget1, true); 91 | box.append(widget2, true); 92 | box.append(widget3, true); 93 | box.append(widget4, true); 94 | box.append(widget5, true); 95 | box.append(widget6, true); 96 | box.append(widget7, true); 97 | box.append(widget8, true); 98 | 99 | const box2 = new libui.UiVerticalBox(); 100 | box2.append(widget9, true); 101 | box2.append(widget10, true); 102 | box2.append(widget11, true); 103 | box2.append(widget12, true); 104 | box2.append(widget13, true); 105 | 106 | const widget14 = new libui.UiGroup(); 107 | widget14.child = new libui.UiEntry(); 108 | 109 | const widget15 = new libui.UiTab(); 110 | widget15.append('xxx', new libui.UiEntry()); 111 | widget15.append('yyy', new libui.UiEntry()); 112 | 113 | const widget16 = new libui.UiForm(); 114 | widget16.append('xxx', new libui.UiEntry(), true); 115 | widget16.append('yyy', new libui.UiEntry(), true); 116 | 117 | box2.append(widget14, true); 118 | box2.append(widget15, true); 119 | box2.append(widget16, true); 120 | 121 | const horz = new libui.UiHorizontalBox(); 122 | horz.append(box, true); 123 | horz.append(box2, true); 124 | 125 | win.setChild(horz); 126 | 127 | win.onClosing(() => { 128 | win.close(); 129 | global.gc(); 130 | libui.stopLoop(); 131 | }); 132 | 133 | return win; 134 | } 135 | 136 | function op() { 137 | global.gc(); 138 | const win = createWindow(); 139 | win.show(); 140 | setTimeout(() => { 141 | win.close(); 142 | op(); 143 | }, 100); 144 | } 145 | 146 | libui.startLoop(); 147 | op(); 148 | --------------------------------------------------------------------------------