swing-ui 1.0.6 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -9,7 +9,7 @@ Build once, run it on Windows, Linux and macOS in your favorite JavaScript runti
9
9
  ![Windows | macOS | Linux](https://img.shields.io/badge/platform-Windows%20%7C%20macOS%20%7C%20Linux-blue)
10
10
  [![npm license](https://img.shields.io/npm/l/swing-ui.svg)](https://www.npmjs.com/package/swing-ui)
11
11
 
12
- `swing-ui` wraps and upgrades the full Java Swing library so you can write native-looking, cross-platform desktop applications entirely in JavaScript using the JS runtime you already know: Node.js, Bun or Deno 2+.
12
+ `swing-ui` brings a new experience to Java Swing with enhanced components and a simple JavaScript API, allowing you to build native-looking, cross-platform desktop applications entirely in JavaScript using the JS runtime you already know: Node.js, Bun, or Deno 2+.
13
13
 
14
14
  You only write JavaScript and the GUI gets built, or better yet, use our [Visual GUI Designer](https://swing-ui.com/visual-gui-designer/) to skip coding at all.
15
15
 
package/SwingUI.js CHANGED
@@ -72,7 +72,6 @@ export class SwingUI
72
72
 
73
73
  /**
74
74
  * @internal
75
- * @private
76
75
  */
77
76
  _msg = {
78
77
  0: "Calling a function of a destroyed UI component",
@@ -167,7 +166,6 @@ export class SwingUI
167
166
  /**
168
167
  * <b>NOTE:</b> Do not instantiate this class. It's already instantiated and assigned to a global variable `ui`.
169
168
  * @internal
170
- * @private
171
169
  */
172
170
  constructor(module_dir, JBridge)
173
171
  {
@@ -186,6 +184,9 @@ export class SwingUI
186
184
  process.on("SIGHUP", this.exit.bind(this, 0, "SIGHUP"));
187
185
  }
188
186
 
187
+ /**
188
+ * @internal
189
+ */
189
190
  async InitGUIProcess()
190
191
  {
191
192
  if(this.runtime === "bun" || this.os === "darwin") this.#useWorkerThread = true;
@@ -775,6 +776,7 @@ export class SwingUI
775
776
  *
776
777
  * @example <h2>Sending queued messages without compressing:</h2>
777
778
  * ui.sendMessageQueue(false);
779
+ * @internal
778
780
  */
779
781
  sendMessageQueue(compress = true)
780
782
  {
@@ -892,7 +894,7 @@ export class SwingUI
892
894
  */
893
895
  get os()
894
896
  {
895
- let os = "";
897
+ let os;
896
898
 
897
899
  if(this.runtime === "deno")
898
900
  {
@@ -912,8 +914,64 @@ export class SwingUI
912
914
  * Getter property that returns an array of available UI look and feel IDs on your system. For example Windows OS can have a Windows look and feel that linux doesn't have. Use them to set the desired look and feel using ui.ui(id) method.
913
915
  *
914
916
  * @readonly
915
- * @see {@link SwingUI#ui|ui.ui(id)}
916
- * @type {string[]}
917
+ * @see SwingUI#ui
918
+ * @type {object[]}
919
+ * @example <h2>Example of a returned array</h2>
920
+ * [
921
+ * {
922
+ * "name": "Default",
923
+ * "id": "MetalLookAndFeel"
924
+ * },
925
+ * {
926
+ * "name": "OS",
927
+ * "id": "WindowsLookAndFeel"
928
+ * },
929
+ * {
930
+ * "name": "Metal",
931
+ * "dark": false,
932
+ * "id": "MetalLookAndFeel"
933
+ * },
934
+ * {
935
+ * "name": "Nimbus",
936
+ * "dark": false,
937
+ * "id": "NimbusLookAndFeel"
938
+ * },
939
+ * {
940
+ * "name": "CDE/Motif",
941
+ * "dark": false,
942
+ * "id": "MotifLookAndFeel"
943
+ * },
944
+ * {
945
+ * "name": "Windows",
946
+ * "dark": false,
947
+ * "id": "WindowsLookAndFeel"
948
+ * },
949
+ * {
950
+ * "name": "Windows Classic",
951
+ * "dark": false,
952
+ * "id": "WindowsClassicLookAndFeel"
953
+ * },
954
+ * {
955
+ * "name": "FlatLaf Light",
956
+ * "dark": false,
957
+ * "id": "FlatLightLaf"
958
+ * },
959
+ * {
960
+ * "name": "FlatLaf Dark",
961
+ * "dark": true,
962
+ * "id": "FlatDarkLaf"
963
+ * },
964
+ * {
965
+ * "name": "FlatLaf IntelliJ",
966
+ * "dark": false,
967
+ * "id": "FlatIntelliJLaf"
968
+ * },
969
+ * {
970
+ * "name": "FlatLaf Darcula",
971
+ * "dark": true,
972
+ * "id": "FlatDarculaLaf"
973
+ * }
974
+ * ]
917
975
  */
918
976
  get list()
919
977
  {
@@ -982,7 +1040,7 @@ export class SwingUI
982
1040
  }
983
1041
 
984
1042
  /**
985
- * Gets a GUI software license information stored in the package.json file of your project.
1043
+ * Gets a swing-ui software license information including the path on your file system where the license is stored.
986
1044
  *
987
1045
  * @readonly
988
1046
  * @type {Object}
@@ -1211,7 +1269,9 @@ export class SwingUI
1211
1269
  * @return {string|SwingUI} When setting arguments, `this` instance of SwingUI is returned, otherwise current value is returned.
1212
1270
  * @throws Error When argument is invalid.
1213
1271
  * @see SwingUI#list
1214
- * @example <h2>Setting FlatDarkLaf UI with all options</h2>
1272
+ * @example <h2>Setting System's UI Theme</h2>
1273
+ * ui.ui(ui.list.find(t => t.name === "OS").id);
1274
+ * @example <h2>Setting FlatDarkLaf UI theme with all options</h2>
1215
1275
  * ui.ui(
1216
1276
  * "FlatDarkLaf",
1217
1277
  * {
@@ -2630,5 +2690,59 @@ export class SwingUI
2630
2690
  return this;
2631
2691
  }
2632
2692
 
2693
+ /**
2694
+ * Registers, unregisters and retrieves event handler for event emitted by changes to screens on the computer, such as connecting a screen, disconnecting a screen, or changes to screen resolution.
2695
+ *
2696
+ * @param {function(Object):any|null|undefined} [callback] - Function to handle the event, `null` to remove all handlers, or omit to retrieve an array of handlers.
2697
+ * @param {boolean} remove - Removed the callback from this event
2698
+ * @return {SwingUI|function[]} If called without parameters, an array of registered callbacks is returned; otherwise `this` instance of SwingUI class is returned.
2699
+ * @example <h2>Registering screens change event handler:</h2>
2700
+ * ui.onScreensChange(e => {console.log(e.screens});
2701
+ * @see ui#screens
2702
+ */
2703
+ onScreensChange(callback = undefined, remove = false)
2704
+ {
2705
+ const name = "onScreensChange";
2706
+
2707
+ // return callbacks
2708
+ if(callback === undefined) return Array.isArray(this.callback[name]) ? [...this.callback[name]] : [];
2709
+
2710
+ // remove callback
2711
+ if(remove === true || callback === null)
2712
+ {
2713
+ if(!Array.isArray(this.callback[name])) return this;
2714
+
2715
+ if(callback === null)
2716
+ {
2717
+ this.callback[name].length = 0;
2718
+ }
2719
+ else
2720
+ {
2721
+ this.callback[name] = this.callback[name].filter(l => l !== callback);
2722
+ }
2723
+
2724
+ if(this.callback[name].length === 0)
2725
+ {
2726
+ delete this.callback[name]; // delete array
2727
+ this.sendToGUI({system: name, remove: true}); // notify GUI
2728
+ }
2729
+ }
2730
+ // add callback
2731
+ else
2732
+ {
2733
+ if(typeof callback !== "function") throw new Error(`Invalid argument for callback function. Must be a "function" type.`);
2734
+
2735
+ if(!Array.isArray(this.callback[name]))
2736
+ {
2737
+ this.callback[name] = []; // create array
2738
+ this.sendToGUI({system: name, remove: false}); // notify GUI
2739
+ }
2740
+
2741
+ this.callback[name].push(callback); // add callback (don't bind to this here, do it at call)
2742
+ }
2743
+
2744
+ return this;
2745
+ }
2746
+
2633
2747
  //endregion
2634
2748
  }
package/classes/Arc.js CHANGED
@@ -96,7 +96,7 @@ export class Arc extends Shape
96
96
  }
97
97
  else
98
98
  {
99
- return {width: this._size.width, height: this._size.height};
99
+ return {width: this._hole_size.width, height: this._hole_size.height};
100
100
  }
101
101
  }
102
102
 
@@ -31,20 +31,20 @@ export class ComboBox extends TextComponent
31
31
  * @see ListItem
32
32
  * @example
33
33
  * // Creating combo box, then adding each item separately.
34
- * const combo1 = new ComboBox().add("Item 1").add(45).add({text: "Item 2", font:{bolt:true}});
34
+ * const combo1 = new ComboBox().add("Item 1").add(45).add({text: "Item 2", font:{bold:true}});
35
35
  *
36
36
  * // Creating combo box, then adding items as an array.
37
37
  * const combo2 = new ComboBox().items([
38
38
  * "Item 1",
39
39
  * 45,
40
- * {text: "Item 3", font:{bolt:true}}
40
+ * {text: "Item 3", font:{bold:true}}
41
41
  * ]);
42
42
  *
43
43
  * // Creating combo box with items as a string and object. Items can be a mix of strings and objects.
44
44
  * const combo3 = new ComboBox([
45
45
  * "Item 1",
46
46
  * 45,
47
- * {text: "Item 3", font:{bolt:true}}
47
+ * {text: "Item 3", font:{bold:true}}
48
48
  * ]);
49
49
  */
50
50
  constructor(...args) // accepts an optional parameter, array of string for list items
@@ -13,7 +13,13 @@ export class ComponentContainer extends UIComponent
13
13
  #_children = []; // child components of this component
14
14
  #descriptorObject = null;
15
15
 
16
+ /**
17
+ * @internal
18
+ */
16
19
  static preInitProperties = ["position", "size", "innerSize"];
20
+ /**
21
+ * @internal
22
+ */
17
23
  static postInitProperties = ["defaultButton", "state", "visible"]; // state must be applied after all children apply anchor property
18
24
 
19
25
  /**
@@ -129,7 +135,7 @@ export class ComponentContainer extends UIComponent
129
135
  * In loops `for..in`, `for..of` or `component.children.forEach((c, i)=>{...})` it's accessed only once, so you are looping through the same array.
130
136
  *
131
137
  * @readonly
132
- * @type {Object[]}
138
+ * @type {UIComponent[]}
133
139
  * @example <h2>Looping through Window's components</h2>
134
140
  * // method 1
135
141
  * for(child of window.children)
@@ -181,7 +187,7 @@ export class ComponentContainer extends UIComponent
181
187
  /**
182
188
  * Gets or sets the index of a child component within this container. Setting new index changes z-order of the component.
183
189
  *
184
- * @param {Object} child - Child component
190
+ * @param {UIComponent} child - Child component
185
191
  * @param {number} [new_index] - The new index to assign to the child. Moves the component in z-order.
186
192
  * @return {this|null|number} If `new_index` is provided, returns `this` component. If the child is not found in this container, returns `null`. Otherwise, returns the child's current z-index.
187
193
  */
@@ -213,7 +219,7 @@ export class ComponentContainer extends UIComponent
213
219
  /**
214
220
  * Adds a child component to this container component.
215
221
  *
216
- * @param {object} component - UI Component that can be a child of this component.
222
+ * @param {UIComponent} component - UI Component that can be a child of this component.
217
223
  * @param {number|object} [data_or_index] - Argument to pass some extra data (such as Tab Name to add Panel to Tabs), or index at which to insert the child. By default component is added to the end.
218
224
  * @returns {this} Returns an instance of `this` component for chaining.
219
225
  * @see UIComponent#addTo
@@ -319,7 +325,7 @@ export class ComponentContainer extends UIComponent
319
325
  /**
320
326
  * Removes component's child by child object or child index.
321
327
  *
322
- * @param {object|number} child_or_index - Child component object or index of the child.
328
+ * @param {UIComponent|number} child_or_index - Child component object or index of the child.
323
329
  * @param {boolean} [recursive=false] - Boolean indicates if all descendents of this child should also be removed.
324
330
  * @returns {UIComponent|null} The removed child component, or `null` if there is no child at specified index.
325
331
  */
@@ -366,11 +372,11 @@ export class ComponentContainer extends UIComponent
366
372
  * @param {boolean} [recursive=false] - Set to true to also destroy all of its descendants recursively
367
373
  * @returns {void}
368
374
  */
369
- destroy(...args)
375
+ destroy(recursive=false)
370
376
  {
371
377
  if(this.destroyed) return;
372
378
 
373
- const recursive = (args.length > 0 && args[0] === true);
379
+ recursive = (recursive === true);
374
380
 
375
381
  // remove all child components, from last to first (IMPORTANT)
376
382
  for(let i = this.#_children.length - 1; i >= 0; i--)
@@ -389,13 +395,13 @@ export class ComponentContainer extends UIComponent
389
395
  {error(ex);}
390
396
  }
391
397
 
392
- super.destroy(...args);
398
+ super.destroy(recursive);
393
399
  }
394
400
 
395
401
  /**
396
402
  * Checks if passed component is a descendant of this container component.
397
403
  *
398
- * @param descendant - Child component to check.
404
+ * @param {UIComponent} descendant - Child component to check.
399
405
  * @returns {boolean} If the descendant component is inside of this component.
400
406
  * @throws {TypeError} When passed argument is not an instance of UIComponent.
401
407
  * @see UIComponent#insideOf
@@ -821,7 +827,7 @@ export class ComponentContainer extends UIComponent
821
827
  {
822
828
  if(!(event in component))
823
829
  {
824
- error(`${class_name}.${event} is not valid event function for ${class_name} in your .ui.json file:\n\n${common.ui_file}`, false);
830
+ error(`${class_name}.${event} is not a valid event function for ${class_name} in your .ui.json file:\n\n${common.ui_file}`, false);
825
831
  continue;
826
832
  }
827
833
 
@@ -103,7 +103,7 @@ export class ContextMenu extends ComponentContainer
103
103
  /**
104
104
  * Adds this ContextMenu to a specified parent component.
105
105
  *
106
- * @param {object} parent - A valid component that accepts ContextMenu. `parent` must be derived from UIComponent.
106
+ * @param {ComponentContainer} parent - A valid component that accepts ContextMenu. `parent` must be derived from UIComponent.
107
107
  * @return {ContextMenu} Returns an instance of `this` object.
108
108
  */
109
109
  addTo(parent, ...args)
package/classes/List.js CHANGED
@@ -46,20 +46,20 @@ export class List extends ScrollableComponent
46
46
  * @param {Array<string|number|ListItem>} [items] - Items as an Array of ListItem formatted objects, strings or numbers. Can be a mix of these types.
47
47
  * @example
48
48
  * // Creating combo box, then adding each item separately.
49
- * const combo1 = new ComboBox().add("Item 1").add(45).add({text: "Item 2", font:{bolt:true}});
49
+ * const combo1 = new ComboBox().add("Item 1").add(45).add({text: "Item 2", font:{bold:true}});
50
50
  *
51
51
  * // Creating combo box, then adding items as an array.
52
52
  * const combo2 = new ComboBox().items([
53
53
  * "Item 1",
54
54
  * 45,
55
- * {text: "Item 2", font:{bolt:true}}
55
+ * {text: "Item 2", font:{bold:true}}
56
56
  * ]);
57
57
  *
58
58
  * // Creating combo box with items as a string and object. Items can be a mix of strings and objects.
59
59
  * const combo3 = new ComboBox([
60
60
  * "Item 1",
61
61
  * 45,
62
- * {text: "Item 2", font:{bolt:true}}
62
+ * {text: "Item 2", font:{bold:true}}
63
63
  * ]);
64
64
  */
65
65
  constructor(...args)
@@ -2,9 +2,10 @@
2
2
  import {UIComponent} from "./UIComponent.js";
3
3
 
4
4
  /**
5
- * RadioButton is a component used to select of multiple option by clicking on it.
6
- * Multiple RadioButton components must be grouped for selection to work.
7
- * To group them pick one main RadioButton and group other RadioButton components with it.
5
+ * RadioButton is a component used to select one of multiple option by clicking on it.
6
+ *
7
+ * Multiple RadioButton components must be grouped for selection to work. To group them pick one main RadioButton and group other RadioButton components with it.
8
+ *
8
9
  * For example if you have three RadioButton components, you must group second component with first one, then third component with any component that is already grouped (first or second).
9
10
  * Then to detect selection changes add onChange(e => {console.log(e.value);}) to only one of the grouped RadioButton components, and e.value will be the value of currently selected RadioButton.
10
11
  * @class
@@ -2,13 +2,13 @@
2
2
  import {MenuItem} from "./MenuItem.js";
3
3
 
4
4
  /**
5
- * Radio button menu item UI component that extends MenuItem class.
5
+ * Radio button menu item UI component.
6
+ *
7
+ * RadioButtonMenuItem is a component used to select one of multiple option by clicking on it. Multiple RadioButtonMenuItem components must be grouped for selection to work as expected. To group them pick one main RadioButtonMenuItem and group other RadioButtonMenuItem with it.
6
8
  *
7
- * RadioButton is a component used to select of multiple option by clicking on it.
8
- * Multiple RadioButton components must be grouped for selection to work as expected.
9
- * To group them pick one main RadioButtonMenuItem and group other RadioButtonMenuItem with it.
10
9
  * For example if you have three RadioButtonMenuItem components that you want to group, you must group second component with first one, then third component with any component that is already grouped (first or second).
11
- * Then to detect selection changes add onChange(e => {console.log(e.value);}) to only one of the grouped RadioButton components, and e.value will be the value of currently selected RadioButton.
10
+ *
11
+ * Then to detect selection changes add onChange(e => {console.log(e.value);}) to only one of the grouped RadioButton components, and e.value will be the value of currently selected RadioButton in the group.
12
12
  * See example below.
13
13
  *
14
14
  * @class
@@ -38,7 +38,7 @@ class ScrollPane extends ComponentContainer
38
38
  /**
39
39
  * Adds a child component to this container component.
40
40
  *
41
- * @param {Object} component - UI Component that can be a child of this component.
41
+ * @param {UIComponent} component - UI Component that can be a child of this component.
42
42
  * @returns {this} Returns an instance of `this` component.
43
43
  */
44
44
  addChild(component, ...data)
package/classes/Table.js CHANGED
@@ -740,8 +740,6 @@ export class Table extends ScrollableComponent
740
740
  */
741
741
  editingCell(...args)
742
742
  {
743
- let msg = {control: this.id};
744
-
745
743
  if(args.length > 0)
746
744
  {
747
745
  const cell = args[0] == null ? null : (typeof args[0] === "object") ? args[0] : {row: parseInt(args[0]), col: parseInt(args[1])};
@@ -753,6 +751,36 @@ export class Table extends ScrollableComponent
753
751
  return this.property("editingCell", [])
754
752
  }
755
753
  }
754
+
755
+ /**
756
+ * Sets or gets how many quick mouse clicks on editable cells are required to change the cell to editing mode.
757
+ *
758
+ * @param {number} [clicks] - Amount of clicks: 1, 2, or 3. Default is 2 (double-click).
759
+ * @return {number|Table} Returns the current value if no parameters are provided; otherwise, and instance of `this` Table is returned.
760
+ */
761
+ clicksToEdit(...args)
762
+ {
763
+ if(args.length > 0)
764
+ {
765
+ // enforce int
766
+ args[0] = Math.max(1, Number.parseInt(args[0]));
767
+ if(!Number.isSafeInteger(args[0])) throw new TypeError(`Invalid Table.clickToEdit() argument. A positive integer is required.`);
768
+ }
769
+ return this.property("clicksToEdit", args);
770
+ }
771
+
772
+ /**
773
+ * Sets or gets whether to allow row selection with a click of a right mouse button.
774
+ *
775
+ * @param {boolean} [enable] - Boolean value that enables or disables right-click row selection.
776
+ * @return {boolean|List} Returns `this` component instance if at least one argument is provided, otherwise returns current value.
777
+ * @since 1.1.0
778
+ */
779
+ rightClickSelect(...args)
780
+ {
781
+ if(args.length > 0) args[0] = (args[0] === true); // ensure boolean
782
+ return this.property("rightClickSelect", arguments);
783
+ }
756
784
 
757
785
  /**
758
786
  * Sets or gets whether sorting can be toggled to unsorted state.
@@ -886,23 +914,6 @@ export class Table extends ScrollableComponent
886
914
  return ui.sendToGUI({control: this.id, get: "cellAt", data: {x: x, y: y}});
887
915
  }
888
916
 
889
- /**
890
- * Sets or gets how many quick mouse clicks on editable cells are required to change the cell to editing mode.
891
- *
892
- * @param {number} [clicks] - Amount of clicks: 1, 2, or 3. Default is 2 (double-click).
893
- * @return {number|Table} Returns the current value if no parameters are provided; otherwise, and instance of `this` Table is returned.
894
- */
895
- clicksToEdit(...args)
896
- {
897
- if(args.length > 0)
898
- {
899
- // enforce int
900
- args[0] = Math.max(1, Number.parseInt(args[0]));
901
- if(!Number.isSafeInteger(args[0])) throw new TypeError(`Invalid Table.clickToEdit() argument. A positive integer is required.`);
902
- }
903
- return this.property("clicksToEdit", args);
904
- }
905
-
906
917
  //endregion
907
918
 
908
919
  //region Events
@@ -2,7 +2,7 @@
2
2
  import {ComponentContainer} from "./ComponentContainer.js";
3
3
 
4
4
  /**
5
- * A toolbar component that is usually used at the top of window and can hold {@link Label}, {@link Button}, {@link TextField}, {@link ComboBox}, and a {@link Separator} to display useful tools for a user.
5
+ * A toolbar component that is usually used at the top of window and can hold {@link Label}, {@link Button}, {@link TextField}, {@link PasswordField}, {@link Spinner}, {@link ComboBox}, {@link CheckBox}, {@link RadioButton} and a {@link Separator} to display useful tools for a user.
6
6
  *
7
7
  * Toolbar can be draggable and can be detached and displayed in a separate dedicated window. It can also be in horizontal (default) and vertical orientation.
8
8
  *
@@ -57,7 +57,7 @@ export class ToolBar extends ComponentContainer
57
57
  {
58
58
  return this.property("orientation", args);
59
59
  }
60
-
60
+
61
61
  /**
62
62
  * Sets or gets a padding size between edge of the component and items inside it, and spacing between items.
63
63
  *
package/classes/Tree.js CHANGED
@@ -491,6 +491,18 @@ export class Tree extends ScrollableComponent
491
491
  return this.property("clicksToEdit", args.length > 0 ? [parseInt(args[0])] : args);
492
492
  }
493
493
 
494
+ /**
495
+ * Sets or gets whether to allow selecting list items with a click of a right mouse button.
496
+ * @param {boolean} [enable] - Boolean value that enables or disables right-click item selection.
497
+ * @return {boolean|List} Returns `this` component instance if at least one argument is provided, otherwise returns current value.
498
+ * @since 1.1.0
499
+ */
500
+ rightClickSelect(...args)
501
+ {
502
+ if(args.length > 0) args[0] = (args[0] === true); // ensure boolean
503
+ return this.property("rightClickSelect", arguments);
504
+ }
505
+
494
506
  /**
495
507
  * Sets or gets whether Tree nodes' text can be edited by user.
496
508
  *
@@ -399,7 +399,7 @@ class UIComponent
399
399
  * @param {boolean} [recursive=false] - Set to true to also destroy all of its descendants recursively
400
400
  * @returns {void}
401
401
  */
402
- destroy(...args)
402
+ destroy(recursive=false)
403
403
  {
404
404
  if(this.destroyed) return;
405
405
 
package/classes/Window.js CHANGED
@@ -26,7 +26,8 @@ class Window extends ShapeContainer
26
26
  #owner = null; // used only for modal window
27
27
  #prop = {
28
28
  closeOperation: Window.CloseOperation.Exit,
29
- innerOffset: null
29
+ innerOffset: null,
30
+ toolBar:{}
30
31
  };
31
32
 
32
33
  /**
@@ -604,6 +605,46 @@ class Window extends ShapeContainer
604
605
  return this.property("opacity", args);
605
606
  }
606
607
 
608
+ /**
609
+ * Sets a ToolBar to one of locations: `top`, `right`, `bottom` and `left`, or gets a ToolBar at a specified location.
610
+ *
611
+ * @param {string} dockLocation - One of: `top`, `right`, `bottom` and `left`.
612
+ * @param {ToolBar} [toolbar] - ToolBar to set to specified location. Set `null` to remove the toolbar from that location. Omit to get the toolbar already in that location.
613
+ * @returns {ToolBar|null|Window} If only location is specified, a {@link ToolBar} or `null` is returned. When `toolbar` argument is passed, an instance of `this` Window is returned.
614
+ * @since 1.0.8
615
+ */
616
+ toolBar(dockLocation, toolbar = undefined)
617
+ {
618
+ if(typeof dockLocation !== "string")
619
+ {
620
+ return null;
621
+ }
622
+ else if(toolbar === undefined) // gets toolbar
623
+ {
624
+ const id = ui.sendToGUI({control: this.id, get: "toolBar", data: dockLocation});
625
+
626
+ return id === -1 ? null : UIComponent.get(id) ?? null; // in case it was destroyed already
627
+ }
628
+ else if(toolbar === null)
629
+ {
630
+ if(this.#prop.toolBar[dockLocation] instanceof ToolBar)
631
+ {
632
+ this.property("toolBar", [{id: null, location: dockLocation}])
633
+ delete this.#prop.toolBar[dockLocation];
634
+ }
635
+ }
636
+ if(toolbar instanceof ToolBar) // sets toolbar
637
+ {
638
+ if("top right bottom left".includes(dockLocation))
639
+ {
640
+ if(this.#prop.toolBar[dockLocation] instanceof ToolBar) this.property("toolBar", [{id: null, location: dockLocation}])
641
+ this.#prop.toolBar[dockLocation] = toolbar;
642
+
643
+ this.property("toolBar", [{id: toolbar.id, location: dockLocation}])
644
+ }
645
+ }
646
+ return this;
647
+ }
607
648
  }
608
649
 
609
650
  export {Window};
package/functions.js CHANGED
@@ -119,7 +119,7 @@ export function stringify(variable)
119
119
  }
120
120
 
121
121
  /**
122
- * Displays a dialog window with a specified error message and an error icon.
122
+ * Displays a dialog window with a specified message and optional icon.
123
123
  *
124
124
  * @param {string} message - A message to be displayed in the dialog window
125
125
  * @param {string} [title="Message"] - Dialog window title bar text
@@ -212,10 +212,10 @@ export function confirm(message, window = null)
212
212
  *
213
213
  * @param {string} message - String message to user. It can be plain text or HTML.
214
214
  * @param {string} [title=""] - Dialog window title shown in the title bar of the window
215
- * @param {string[]} [buttons=["OK","Cancel"]] - An Array of button names. Indicate a default button by surrounding the text with square brackets like so: "[Cancel]"
215
+ * @param {string[]} [buttons=["[OK]","Cancel"]] - An array of button names. Indicate a default button by surrounding the text with square brackets like so: "[OK]"
216
216
  * @param {MessageIcon|string} [icon=null] - One of MessageIcon icons, or an absolute path to an image from a file system.
217
217
  * @param {Window} [window=null] - Owner window that will be overlaid by this dialog window. If omitted, last created visible Window that's not PopUp will be used.
218
- * @return {number|undefined} Returns a zero-based number of a clicked button, or `null` if the dialog window was closed without clicking provided buttons.
218
+ * @return {number|null} Returns a zero-based number of a clicked button, or `null` if the dialog window was closed without clicking provided buttons.
219
219
  * @global
220
220
  * @example <h2>Usage example</h2>
221
221
  * let response = dialog("Are you ready?", "Confirm readiness", ["Yes", "No", "[Maybe]"], MessageIcon.Question, window);
@@ -229,7 +229,7 @@ export function confirm(message, window = null)
229
229
  * @example <h2>Using custom image</h2>
230
230
  * let response = dialog("Is this you?", "Question #5", ["Yes","[No]"], "C://User/John/profile_icon.jpg", window);
231
231
  */
232
- export function dialog(message, title = "", buttons = ["OK", "Cancel"], icon = null, window = null)
232
+ export function dialog(message, title = "", buttons = ["[OK]", "Cancel"], icon = null, window = null)
233
233
  {
234
234
  // find first visible window
235
235
  if(window == null)
package/icon.png CHANGED
Binary file
package/jar/gui-11.jar CHANGED
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "swing-ui",
3
- "version": "1.0.6",
3
+ "version": "1.1.0",
4
4
  "description": "Cross-platform Graphic User Interface for Node.js, Bun and Deno 2+",
5
5
  "main": "index.js",
6
6
  "scripts": {