Adding registers panes of CPU window
This commit is contained in:
@@ -200,7 +200,6 @@ Toolkit.Application = class Application extends Toolkit.Panel {
|
||||
|
||||
// A pointer or mouse down even has propagated
|
||||
onpropagation(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
for (let listener of this.propagationListeners)
|
||||
listener(e, this);
|
||||
|
||||
+21
-22
@@ -45,43 +45,51 @@ Toolkit.Button = class Button extends Toolkit.Component {
|
||||
this.clickListeners.push(listener);
|
||||
}
|
||||
|
||||
// The button was activated
|
||||
click(e) {
|
||||
if (!this.enabled)
|
||||
return;
|
||||
for (let listener of this.clickListeners)
|
||||
listener(e);
|
||||
}
|
||||
|
||||
// Request focus on the appropriate element
|
||||
focus() {
|
||||
this.element.focus();
|
||||
}
|
||||
|
||||
// Retrieve the button's accessible name
|
||||
// Retrieve the component's accessible name
|
||||
getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
// Retrieve the button's display text
|
||||
// Retrieve the component's display text
|
||||
getText() {
|
||||
return this.text;
|
||||
}
|
||||
|
||||
// Retrieve the button's tool tip text
|
||||
// Retrieve the component's tool tip text
|
||||
getToolTip() {
|
||||
return this.toolTip;
|
||||
}
|
||||
|
||||
// Determine whether the button is enabled
|
||||
// Determine whether the component is enabled
|
||||
isEnabled() {
|
||||
return this.enabled;
|
||||
}
|
||||
|
||||
// Determine whether the button is focusable
|
||||
// Determine whether the component is focusable
|
||||
isFocusable() {
|
||||
return this.focusable;
|
||||
}
|
||||
|
||||
// Specify whether the button is enabled
|
||||
// Specify whether the component is enabled
|
||||
setEnabled(enabled) {
|
||||
this.enabled = enabled = !!enabled;
|
||||
this.element.setAttribute("aria-disabled", !enabled);
|
||||
}
|
||||
|
||||
// Specify whether the button can receive focus
|
||||
// Specify whether the component can receive focus
|
||||
setFocusable(focusable) {
|
||||
this.focusable = focusable = !!focusable;
|
||||
if (focusable)
|
||||
@@ -89,19 +97,19 @@ Toolkit.Button = class Button extends Toolkit.Component {
|
||||
else this.element.removeAttribute("tabindex");
|
||||
}
|
||||
|
||||
// Specify the button's accessible name
|
||||
// Specify the component's accessible name
|
||||
setName(name) {
|
||||
this.name = name || "";
|
||||
this.localize();
|
||||
}
|
||||
|
||||
// Specify the button's display text
|
||||
// Specify the component's display text
|
||||
setText(text) {
|
||||
this.text = text || "";
|
||||
this.localize();
|
||||
}
|
||||
|
||||
// Specify the button's tool tip text
|
||||
// Specify the component's tool tip text
|
||||
setToolTip(toolTip) {
|
||||
this.toolTip = toolTip || "";
|
||||
this.localize();
|
||||
@@ -133,14 +141,6 @@ Toolkit.Button = class Button extends Toolkit.Component {
|
||||
|
||||
///////////////////////////// Private Methods /////////////////////////////
|
||||
|
||||
// The button was activated
|
||||
activate(e) {
|
||||
if (!this.enabled)
|
||||
return;
|
||||
for (let listener of this.clickListeners)
|
||||
listener(e, this);
|
||||
}
|
||||
|
||||
// Key down event handler
|
||||
onkeydown(e) {
|
||||
|
||||
@@ -152,7 +152,7 @@ Toolkit.Button = class Button extends Toolkit.Component {
|
||||
switch (e.key) {
|
||||
case " ":
|
||||
case "Enter":
|
||||
this.activate(e);
|
||||
this.click(e);
|
||||
break;
|
||||
default: return;
|
||||
}
|
||||
@@ -166,7 +166,6 @@ Toolkit.Button = class Button extends Toolkit.Component {
|
||||
onpointerdown(e) {
|
||||
|
||||
// Configure event
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
// Configure focus
|
||||
@@ -221,11 +220,11 @@ Toolkit.Button = class Button extends Toolkit.Component {
|
||||
// Configure element
|
||||
this.element.releasePointerCapture(e.pointerId);
|
||||
|
||||
// Activate the menu item if it is active
|
||||
// Activate the component if it is active
|
||||
if (!this.element.hasAttribute("active"))
|
||||
return;
|
||||
this.element.removeAttribute("active");
|
||||
this.activate(e);
|
||||
this.click(e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
"use strict";
|
||||
|
||||
// Grouping manager for mutually-exclusive controls
|
||||
Toolkit.ButtonGroup = class ButtonGroup {
|
||||
|
||||
// Object constructor
|
||||
constructor() {
|
||||
this.components = [];
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////// Public Methods //////////////////////////////
|
||||
|
||||
// Add a component to the group
|
||||
add(component) {
|
||||
if (this.components.indexOf(component) != -1)
|
||||
return component;
|
||||
this.components.push(component);
|
||||
if ("setGroup" in component)
|
||||
component.setGroup(this);
|
||||
return component;
|
||||
}
|
||||
|
||||
// Select only one button in the group
|
||||
setChecked(component) {
|
||||
for (let comp of this.components) {
|
||||
if ("setChecked" in comp)
|
||||
comp.setChecked(comp == component, this);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove a component from the group
|
||||
remove(component) {
|
||||
let index = this.components.indexOf(component);
|
||||
if (index == -1)
|
||||
return false;
|
||||
this.components.splice(index, 1);
|
||||
if ("setGroup" in component)
|
||||
component.setGroup(null);
|
||||
return true;
|
||||
}
|
||||
|
||||
};
|
||||
@@ -0,0 +1,190 @@
|
||||
"use strict";
|
||||
|
||||
// On/off toggle checkbox
|
||||
Toolkit.CheckBox = class CheckBox extends Toolkit.Panel {
|
||||
|
||||
// Object constructor
|
||||
constructor(application, options) {
|
||||
super(application, options);
|
||||
options = options || {};
|
||||
|
||||
// Configure instance fields
|
||||
this.changeListeners = [];
|
||||
this.checked = false;
|
||||
this.enabled = "enabled" in options ? !!options.enabled : true;
|
||||
this.text = options.text || "";
|
||||
|
||||
// Configure element
|
||||
this.setLayout("grid", {
|
||||
columns : "max-content max-content"
|
||||
});
|
||||
this.setDisplay("inline-grid");
|
||||
this.setHollow(false);
|
||||
this.setOverflow("visible", "visible");
|
||||
this.element.setAttribute("tabindex", "0");
|
||||
this.element.setAttribute("role", "checkbox");
|
||||
this.element.setAttribute("aria-checked", "false");
|
||||
this.element.style.alignItems = "center";
|
||||
this.element.addEventListener("keydown" , e=>this.onkeydown (e));
|
||||
this.element.addEventListener("pointerdown", e=>this.onpointerdown(e));
|
||||
this.element.addEventListener("pointermove", e=>this.onpointermove(e));
|
||||
this.element.addEventListener("pointerup" , e=>this.onpointerup (e));
|
||||
|
||||
// Configure check box
|
||||
this.check = this.add(this.newLabel());
|
||||
this.check.element.setAttribute("name", "check");
|
||||
this.check.element.setAttribute("aria-hidden", "true");
|
||||
|
||||
// Configure label
|
||||
this.label = this.add(this.newLabel({ localized: true }));
|
||||
this.label.element.setAttribute("name", "label");
|
||||
this.element.setAttribute("aria-labelledby", this.label.id);
|
||||
|
||||
// Configure properties
|
||||
this.setChecked(options.checked);
|
||||
this.setEnabled(this.enabled);
|
||||
this.setText (this.text );
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////// Public Methods //////////////////////////////
|
||||
|
||||
// Add a callback for change events
|
||||
addChangeListener(listener) {
|
||||
if (this.changeListeners.indexOf(listener) == -1)
|
||||
this.changeListeners.push(listener);
|
||||
}
|
||||
|
||||
// Request focus on the appropriate element
|
||||
focus() {
|
||||
this.element.focus();
|
||||
}
|
||||
|
||||
// Determine whether the component is checked
|
||||
isChecked() {
|
||||
return this.checked;
|
||||
}
|
||||
|
||||
// Determine whether the component is enabled
|
||||
isEnabled() {
|
||||
return this.enabled;
|
||||
}
|
||||
|
||||
// Specify whether the component is checked
|
||||
setChecked(checked, e) {
|
||||
checked = !!checked;
|
||||
if (checked == this.checked)
|
||||
return;
|
||||
this.checked = checked;
|
||||
this.element.setAttribute("aria-checked", checked);
|
||||
if (e === undefined)
|
||||
return;
|
||||
for (let listener of this.changeListeners)
|
||||
listener(e);
|
||||
}
|
||||
|
||||
// Specify whether the component is enabled
|
||||
setEnabled(enabled) {
|
||||
this.enabled = enabled = !!enabled;
|
||||
this.element.setAttribute("aria-disabled", !enabled);
|
||||
if (enabled)
|
||||
this.element.setAttribute("tabindex", "0");
|
||||
else this.element.removeAttribute("tabindex");
|
||||
}
|
||||
|
||||
// Specify the component's display text
|
||||
setText(text) {
|
||||
this.text = text = text || "";
|
||||
this.label.setText(text);
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////// Private Methods /////////////////////////////
|
||||
|
||||
// Key down event handler
|
||||
onkeydown(e) {
|
||||
|
||||
// Error checking
|
||||
if (!this.enabled)
|
||||
return;
|
||||
|
||||
// Ignore the key
|
||||
if (e.key != " ")
|
||||
return;
|
||||
|
||||
// Configure event
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
// Toggle the checked state
|
||||
this.setChecked(!this.checked, e);
|
||||
}
|
||||
|
||||
// Pointer down event handler
|
||||
onpointerdown(e) {
|
||||
|
||||
// Configure event
|
||||
//e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
// Configure focus
|
||||
if (this.enabled)
|
||||
this.focus();
|
||||
else return;
|
||||
|
||||
// Error checking
|
||||
if (e.button != 0 || this.element.hasPointerCapture(e.captureId))
|
||||
return;
|
||||
|
||||
// Configure element
|
||||
this.element.setPointerCapture(e.pointerId);
|
||||
this.element.setAttribute("active", "");
|
||||
}
|
||||
|
||||
// Pointer move event handler
|
||||
onpointermove(e) {
|
||||
|
||||
// Error checking
|
||||
if (!this.element.hasPointerCapture(e))
|
||||
return;
|
||||
|
||||
// Configure event
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
// Working variables
|
||||
let bounds = this.getBounds();
|
||||
let active =
|
||||
e.x >= bounds.x && e.x < bounds.x + bounds.width &&
|
||||
e.y >= bounds.y && e.y < bounds.y + bounds.height
|
||||
;
|
||||
|
||||
// Configure element
|
||||
if (active)
|
||||
this.element.setAttribute("active", "");
|
||||
else this.element.removeAttribute("active");
|
||||
}
|
||||
|
||||
// Pointer up event handler
|
||||
onpointerup(e) {
|
||||
|
||||
// Configure event
|
||||
e.stopPropagation();
|
||||
|
||||
// Error checking
|
||||
if (!this.element.hasPointerCapture(e.pointerId))
|
||||
return;
|
||||
|
||||
// Configure element
|
||||
this.element.releasePointerCapture(e.pointerId);
|
||||
|
||||
// Activate the component if it is active
|
||||
if (!this.element.hasAttribute("active"))
|
||||
return;
|
||||
this.element.removeAttribute("active");
|
||||
this.setChecked(!this.checked, e);
|
||||
}
|
||||
|
||||
};
|
||||
+34
-16
@@ -21,6 +21,10 @@ Toolkit.Component = class Component {
|
||||
|
||||
// Configure component
|
||||
this.element.component = this;
|
||||
this.setSize(
|
||||
"width" in options ? options.width : null,
|
||||
"height" in options ? options.height : null
|
||||
);
|
||||
this.setVisible(this.visible);
|
||||
}
|
||||
|
||||
@@ -58,11 +62,11 @@ Toolkit.Component = class Component {
|
||||
}
|
||||
|
||||
// Specify the location and size of the component
|
||||
setBounds(left, top, width, height) {
|
||||
setBounds(left, top, width, height, minimum) {
|
||||
this.setLeft (left );
|
||||
this.setTop (top );
|
||||
this.setWidth (width );
|
||||
this.setHeight(height);
|
||||
this.setWidth (width , minimum);
|
||||
this.setHeight(height, minimum);
|
||||
}
|
||||
|
||||
// Specify the display CSS property of the visible element
|
||||
@@ -71,12 +75,19 @@ Toolkit.Component = class Component {
|
||||
this.setVisible(this.visible);
|
||||
}
|
||||
|
||||
// Specify the height of the element
|
||||
setHeight(height) {
|
||||
if (height === null)
|
||||
// Specify the height of the component
|
||||
setHeight(height, minimum) {
|
||||
if (height === null) {
|
||||
this.element.style.removeProperty("min-height");
|
||||
this.element.style.removeProperty("height");
|
||||
else this.element.style.height =
|
||||
typeof height == "number" ? height + "px" : height
|
||||
} else {
|
||||
height = typeof height == "number" ?
|
||||
Math.max(0, height) + "px" : height;
|
||||
this.element.style.height = height;
|
||||
if (minimum)
|
||||
this.element.style.minHeight = height;
|
||||
else this.element.style.removeProperty("min-height");
|
||||
}
|
||||
}
|
||||
|
||||
// Specify the horizontal position of the component
|
||||
@@ -100,9 +111,9 @@ Toolkit.Component = class Component {
|
||||
}
|
||||
|
||||
// Specify both the width and the height of the component
|
||||
setSize(width, height) {
|
||||
this.setHeight(height);
|
||||
this.setWidth (width );
|
||||
setSize(width, height, minimum) {
|
||||
this.setHeight(height, minimum);
|
||||
this.setWidth (width , minimum);
|
||||
}
|
||||
|
||||
// Specify the vertical position of the component
|
||||
@@ -123,12 +134,19 @@ Toolkit.Component = class Component {
|
||||
} else this.element.style.display = "none";
|
||||
}
|
||||
|
||||
// Specify the width of the element
|
||||
setWidth(width) {
|
||||
if (width === null)
|
||||
// Specify the width of the component
|
||||
setWidth(width, minimum) {
|
||||
if (width === null) {
|
||||
this.element.style.removeProperty("min-width");
|
||||
this.element.style.removeProperty("width");
|
||||
else this.element.style.width =
|
||||
typeof width == "number" ? width + "px" : width ;
|
||||
} else {
|
||||
width = typeof width == "number" ?
|
||||
Math.max(0, width) + "px" : width;
|
||||
this.element.style.width = width;
|
||||
if (minimum)
|
||||
this.element.style.minWidth = width;
|
||||
else this.element.style.removeProperty("min-width");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
+30
-2
@@ -5,10 +5,11 @@ Toolkit.Label = class Label extends Toolkit.Component {
|
||||
|
||||
// Object constructor
|
||||
constructor(application, options) {
|
||||
super(application, "div", options);
|
||||
super(application, options&&options.label ? "label" : "div", options);
|
||||
options = options || {};
|
||||
|
||||
// Configure instance fields
|
||||
this.focusable = "focusable" in options ? !!options.focusable : false;
|
||||
this.localized = "localized" in options ? !!options.localized : false;
|
||||
this.text = options.text || "";
|
||||
|
||||
@@ -17,7 +18,8 @@ Toolkit.Label = class Label extends Toolkit.Component {
|
||||
this.element.style.userSelect = "none";
|
||||
|
||||
// Configure properties
|
||||
this.setText(this.text);
|
||||
this.setFocusable(this.focusable);
|
||||
this.setText (this.text);
|
||||
if (this.localized)
|
||||
this.application.addComponent(this);
|
||||
}
|
||||
@@ -26,17 +28,43 @@ Toolkit.Label = class Label extends Toolkit.Component {
|
||||
|
||||
///////////////////////////// Public Methods //////////////////////////////
|
||||
|
||||
// Request focus on the appropriate element
|
||||
focus() {
|
||||
if (this.focusable)
|
||||
this.element.focus();
|
||||
}
|
||||
|
||||
// Retrieve the label's display text
|
||||
getText() {
|
||||
return this.text;
|
||||
}
|
||||
|
||||
// Determine whether the component is focusable
|
||||
isFocusable() {
|
||||
return this.focusable;
|
||||
}
|
||||
|
||||
// Specify the label's display text
|
||||
setText(text) {
|
||||
this.text = text || "";
|
||||
this.localize();
|
||||
}
|
||||
|
||||
// Specify whether the component is focusable
|
||||
setFocusable(focusable) {
|
||||
this.focusable = focusable = !!focusable;
|
||||
if (focusable) {
|
||||
this.element.setAttribute("tabindex", "0");
|
||||
this.localized && this.application &&
|
||||
this.application.addComponent(this);
|
||||
} else {
|
||||
this.element.removeAttribute("aria-label");
|
||||
this.element.removeAttribute("tabindex");
|
||||
this.localized && this.application &&
|
||||
this.application.removeComponent(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////// Package Methods /////////////////////////////
|
||||
|
||||
@@ -15,7 +15,7 @@ Toolkit.MenuBar = class MenuBar extends Toolkit.Panel {
|
||||
|
||||
// Configure element
|
||||
this.element.style.position = "relative";
|
||||
this.element.style.zIndex = "1";
|
||||
this.element.style.zIndex = "2";
|
||||
this.element.setAttribute("role", "menubar");
|
||||
this.setLayout("flex", {
|
||||
direction: "row",
|
||||
|
||||
+96
-14
@@ -15,22 +15,23 @@ Toolkit.Panel = class Panel extends Toolkit.Component {
|
||||
this.children = [];
|
||||
this.columns = null;
|
||||
this.direction = "row";
|
||||
this.focusable = "focusable" in options ? !!options.focusable:false;
|
||||
this.hollow = "hollow" in options ? !!options.hollow : true;
|
||||
this.layout = null;
|
||||
this.name = options.name || "";
|
||||
this.overflowX = options.overflowX || "hidden";
|
||||
this.overflowY = options.overflowY || "hidden";
|
||||
this.rows = null;
|
||||
this.wrap = false;
|
||||
|
||||
// Configure element
|
||||
if ("noShrink" in options ? !options.noShrink : true) {
|
||||
this.element.style.minHeight = "0";
|
||||
this.element.style.minWidth = "0";
|
||||
}
|
||||
this.setOverflow(this.overflowX, this.overflowY);
|
||||
|
||||
// Configure layout
|
||||
options = options || {};
|
||||
this.setLayout(options.layout || null, options);
|
||||
// Configure properties
|
||||
this.setFocusable(this.focusable);
|
||||
this.setHollow (this.hollow);
|
||||
this.setLayout (options.layout || null, options);
|
||||
this.setName (this.name);
|
||||
this.setOverflow (this.overflowX, this.overflowY);
|
||||
if (this.application && this.focusable)
|
||||
this.application.addComponent(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -54,11 +55,37 @@ Toolkit.Panel = class Panel extends Toolkit.Component {
|
||||
return component;
|
||||
}
|
||||
|
||||
// Request focus on the appropriate element
|
||||
focus() {
|
||||
if (this.focusable)
|
||||
this.element.focus();
|
||||
}
|
||||
|
||||
// Retrieve the component's accessible name
|
||||
getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
// Determine whether the component is focusable
|
||||
isFocusable() {
|
||||
return this.focusable;
|
||||
}
|
||||
|
||||
// Determine whether the component is hollow
|
||||
isHollow() {
|
||||
return this.hollow;
|
||||
}
|
||||
|
||||
// Create a Button and associate it with the application
|
||||
newButton(options) {
|
||||
return new Toolkit.Button(this.application, options);
|
||||
}
|
||||
|
||||
// Create a CheckBox and associate it with the application
|
||||
newCheckBox(options) {
|
||||
return new Toolkit.CheckBox(this.application, options);
|
||||
}
|
||||
|
||||
// Create a Label and associate it with the application
|
||||
newLabel(options) {
|
||||
return new Toolkit.Label(this.application, options);
|
||||
@@ -74,6 +101,21 @@ Toolkit.Panel = class Panel extends Toolkit.Component {
|
||||
return new Toolkit.Panel(this.application, options);
|
||||
}
|
||||
|
||||
// Create a RadioButton and associate it with the application
|
||||
newRadioButton(options) {
|
||||
return new Toolkit.RadioButton(this.application, options);
|
||||
}
|
||||
|
||||
// Create a Splitter and associate it with the application
|
||||
newSplitter(options) {
|
||||
return new Toolkit.Splitter(this.application, options);
|
||||
}
|
||||
|
||||
// Create a TextBox and associate it with the application
|
||||
newTextBox(options) {
|
||||
return new Toolkit.TextBox(this.application, options);
|
||||
}
|
||||
|
||||
// Create a Window and associate it with the application
|
||||
newWindow(options) {
|
||||
return new Toolkit.Window(this.application, options);
|
||||
@@ -115,6 +157,31 @@ Toolkit.Panel = class Panel extends Toolkit.Component {
|
||||
this.children.splice(index, 1);
|
||||
}
|
||||
|
||||
// Specify whether the component is focusable
|
||||
setFocusable(focusable) {
|
||||
this.focusable = focusable = !!focusable;
|
||||
if (focusable) {
|
||||
this.element.setAttribute("tabindex", "0");
|
||||
this.application && this.application.addComponent(this);
|
||||
} else {
|
||||
this.element.removeAttribute("aria-label");
|
||||
this.element.removeAttribute("tabindex");
|
||||
this.application && this.application.removeComponent(this);
|
||||
}
|
||||
}
|
||||
|
||||
// Specify whether the component is hollow
|
||||
setHollow(hollow) {
|
||||
this.hollow = hollow = !!hollow;
|
||||
if (hollow) {
|
||||
this.element.style.minHeight = "0";
|
||||
this.element.style.minWidth = "0";
|
||||
} else {
|
||||
this.element.style.removeProperty("min-height");
|
||||
this.element.style.removeProperty("min-width" );
|
||||
}
|
||||
}
|
||||
|
||||
// Configure the element's layout
|
||||
setLayout(layout, options) {
|
||||
|
||||
@@ -122,6 +189,7 @@ Toolkit.Panel = class Panel extends Toolkit.Component {
|
||||
this.layout = layout;
|
||||
|
||||
// Processing by layout
|
||||
options = options || {};
|
||||
switch (layout) {
|
||||
case "block" : this.setBlockLayout (options); break;
|
||||
case "desktop": this.setDesktopLayout(options); break;
|
||||
@@ -132,11 +200,17 @@ Toolkit.Panel = class Panel extends Toolkit.Component {
|
||||
|
||||
}
|
||||
|
||||
// Specify the component's accessible name
|
||||
setName(name) {
|
||||
this.name = name || "";
|
||||
if (this.focusable)
|
||||
this.localize();
|
||||
}
|
||||
|
||||
// Configure the panel's overflow scrolling behavior
|
||||
setOverflow(x, y) {
|
||||
this.overflowX = x || "hidden";
|
||||
this.overflowY = y || "hidden";
|
||||
this.element.style.overflow = this.overflowX + " " + this.overflowY;
|
||||
this.element.style.overflowX = this.overflowX = x || "hidden";
|
||||
this.element.style.overflowY = this.overflowY = y || this.overflowX;
|
||||
}
|
||||
|
||||
// Specify the semantic role of the panel
|
||||
@@ -153,7 +227,15 @@ Toolkit.Panel = class Panel extends Toolkit.Component {
|
||||
// Move a window to the foreground
|
||||
bringToFront(wnd) {
|
||||
for (let child of this.children)
|
||||
child.element.style.zIndex = child == wnd ? "0" : "1";
|
||||
child.element.style.zIndex = child == wnd ? "1" : "0";
|
||||
}
|
||||
|
||||
// Update display text with localized strings
|
||||
localize() {
|
||||
let name = this.name;
|
||||
if (this.application)
|
||||
name = this.application.translate(name, this);
|
||||
this.element.setAttribute("aria-label", name);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
"use strict";
|
||||
|
||||
// Select-only radio button
|
||||
Toolkit.RadioButton = class RadioButton extends Toolkit.CheckBox {
|
||||
|
||||
// Object constructor
|
||||
constructor(application, options) {
|
||||
super(application, options);
|
||||
options = options || {};
|
||||
|
||||
// Configure instance fields
|
||||
this.group = null;
|
||||
|
||||
// Configure element
|
||||
this.element.setAttribute("role", "radio");
|
||||
|
||||
// Configure properties
|
||||
this.setGroup(options.group || null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////// Public Methods //////////////////////////////
|
||||
|
||||
// Retrieve the enclosing ButtonGroup
|
||||
getGroup() {
|
||||
return this.group;
|
||||
}
|
||||
|
||||
// Specify whether the component is checked (overrides superclass)
|
||||
setChecked(checked, e) {
|
||||
checked = !!checked;
|
||||
if (e instanceof Event && !checked || checked == this.checked)
|
||||
return;
|
||||
|
||||
this.checked = checked;
|
||||
this.element.setAttribute("aria-checked", checked);
|
||||
if (this.group != null && e != this.group)
|
||||
this.group.setChecked(this);
|
||||
|
||||
if (e === undefined)
|
||||
return;
|
||||
for (let listener of this.changeListeners)
|
||||
listener(e);
|
||||
}
|
||||
|
||||
// Specify the enclosing ButtonGroup
|
||||
setGroup(group) {
|
||||
group = group || null;
|
||||
if (group == this.group)
|
||||
return;
|
||||
if (this.group != null)
|
||||
this.group.remove(this);
|
||||
this.group = group;
|
||||
if (group != null)
|
||||
group.add(this);
|
||||
}
|
||||
|
||||
};
|
||||
@@ -0,0 +1,301 @@
|
||||
"use strict";
|
||||
|
||||
// Interactive splitter
|
||||
Toolkit.Splitter = class Splitter extends Toolkit.Component {
|
||||
|
||||
// Object constructor
|
||||
constructor(application, options) {
|
||||
super(application, "div", options);
|
||||
options = options || {};
|
||||
|
||||
// Configure instance fields
|
||||
this.component = options.component || null;
|
||||
this.dragPointer = null;
|
||||
this.dragPos = 0;
|
||||
this.dragSize = 0;
|
||||
this.orientation = options.orientation || "horizontal";
|
||||
this.name = options.name || "";
|
||||
this.edge = options.edge ||
|
||||
(this.orientation == "horizontal" ? "top" : "left");
|
||||
|
||||
// Configure element
|
||||
this.element.setAttribute("role" , "separator");
|
||||
this.element.setAttribute("tabindex" , "0");
|
||||
this.element.setAttribute("aria-valuemin", "0");
|
||||
this.element.addEventListener("keydown" , e=>this.onkeydown (e));
|
||||
this.element.addEventListener("pointerdown", e=>this.onpointerdown(e));
|
||||
this.element.addEventListener("pointermove", e=>this.onpointermove(e));
|
||||
this.element.addEventListener("pointerup" , e=>this.onpointerup (e));
|
||||
|
||||
// Configure properties
|
||||
this.setComponent (this.component );
|
||||
this.setName (this.name );
|
||||
this.setOrientation(this.orientation);
|
||||
this.application.addComponent(this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////// Public Methods //////////////////////////////
|
||||
|
||||
// Request focus on the appropriate element
|
||||
focus() {
|
||||
this.element.focus();
|
||||
}
|
||||
|
||||
// Retrieve the component managed by this Splitter
|
||||
getComponent() {
|
||||
return this.component;
|
||||
}
|
||||
|
||||
// Retrieve the component's accessible name
|
||||
getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
// Retrieve the component's orientation
|
||||
getOrientation() {
|
||||
return this.orientation;
|
||||
}
|
||||
|
||||
// Determine the current and maximum separator values
|
||||
measure() {
|
||||
let max = 0;
|
||||
let now = 0;
|
||||
|
||||
// Mesure the component
|
||||
if (this.component != null && this.parent != null) {
|
||||
let component = this.component.getBounds();
|
||||
let bounds = this.getBounds();
|
||||
let panel = this.parent.getBounds();
|
||||
|
||||
// Horizontal Splitter
|
||||
if (this.orientation == "horizontal") {
|
||||
max = panel.height - bounds.height;
|
||||
now = Math.max(0, Math.min(max, component.height));
|
||||
this.component.setSize(null, now);
|
||||
}
|
||||
|
||||
// Vertical Splitter
|
||||
else {
|
||||
max = panel.width - bounds.width;
|
||||
now = Math.max(0, Math.min(max, component.width));
|
||||
this.component.setSize(now, null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Configure element
|
||||
this.element.setAttribute("aria-valuemax", max);
|
||||
this.element.setAttribute("aria-valuenow", now);
|
||||
}
|
||||
|
||||
// Specify the component managed by this Splitter
|
||||
setComponent(component) {
|
||||
this.component = component = component || null;
|
||||
this.element.setAttribute("aria-controls",
|
||||
component == null ? "" : component.id);
|
||||
this.measure();
|
||||
}
|
||||
|
||||
// Specify the component's accessible name
|
||||
setName(name) {
|
||||
this.name = name || "";
|
||||
this.localize();
|
||||
}
|
||||
|
||||
// Specify the component's orientation
|
||||
setOrientation(orientation) {
|
||||
switch (orientation) {
|
||||
case "horizontal":
|
||||
this.orientation = "horizontal";
|
||||
this.setSize(null, 3, true);
|
||||
this.element.setAttribute("aria-orientation", "horizontal");
|
||||
this.element.style.cursor = "ew-resize";
|
||||
break;
|
||||
case "vertical":
|
||||
this.orientation = "vertical";
|
||||
this.setSize(3, null, true);
|
||||
this.element.setAttribute("aria-orientation", "vertical");
|
||||
this.element.style.cursor = "ns-resize";
|
||||
}
|
||||
this.measure();
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////// Package Methods /////////////////////////////
|
||||
|
||||
// Update display text with localized strings
|
||||
localize() {
|
||||
let name = this.name;
|
||||
if (this.application) {
|
||||
name = this.application.translate(name, this);
|
||||
}
|
||||
this.element.setAttribute("aria-label", name);
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////// Private Methods /////////////////////////////
|
||||
|
||||
// Key press event handler
|
||||
onkeydown(e) {
|
||||
|
||||
// Error checking
|
||||
if (this.component == null)
|
||||
return;
|
||||
|
||||
let pos = this.component.getBounds();
|
||||
let size = this .getBounds();
|
||||
let max = this.parent .getBounds();
|
||||
if (this.orientation == "horizontal") {
|
||||
max = max .height;
|
||||
pos = pos .height;
|
||||
size = size.height;
|
||||
} else {
|
||||
max = max .width;
|
||||
pos = pos .width;
|
||||
size = size.width;
|
||||
}
|
||||
if (this.edge == "top" || this.edge == "left")
|
||||
max -= size;
|
||||
|
||||
// Processing by key
|
||||
if (this.component != null) switch (e.key) {
|
||||
case "ArrowDown":
|
||||
switch (this.edge) {
|
||||
case "bottom":
|
||||
this.component.setSize(null, Math.min(max, pos - 6));
|
||||
break;
|
||||
case "top":
|
||||
this.component.setSize(null, Math.min(max, pos + 6));
|
||||
}
|
||||
break;
|
||||
case "ArrowLeft":
|
||||
switch (this.edge) {
|
||||
case "left":
|
||||
this.component.setSize(Math.min(max, pos - 6), null);
|
||||
break;
|
||||
case "right":
|
||||
this.component.setSize(Math.min(max, pos + 6), null);
|
||||
}
|
||||
break;
|
||||
case "ArrowRight":
|
||||
switch (this.edge) {
|
||||
case "left":
|
||||
this.component.setSize(Math.min(max, pos + 6), null);
|
||||
break;
|
||||
case "right":
|
||||
this.component.setSize(Math.min(max, pos - 6), null);
|
||||
}
|
||||
break;
|
||||
case "ArrowUp":
|
||||
switch (this.edge) {
|
||||
case "bottom":
|
||||
this.component.setSize(null, Math.min(max, pos + 6));
|
||||
break;
|
||||
case "top":
|
||||
this.component.setSize(null, Math.min(max, pos - 6));
|
||||
}
|
||||
break;
|
||||
case "Escape":
|
||||
if (this.dragPointer === null)
|
||||
return;
|
||||
this.element.releasePointerCapture(this.dragPointer);
|
||||
this.dragPointer = null;
|
||||
if (this.orientation == "horizontal")
|
||||
this.component.setHeight(null, this.dragSize);
|
||||
else this.component.setWidth(this.dragSize, null);
|
||||
break;
|
||||
default: return;
|
||||
}
|
||||
|
||||
// Configure event
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
|
||||
// Pointer down event handler
|
||||
onpointerdown(e) {
|
||||
|
||||
// Request focus
|
||||
this.focus();
|
||||
|
||||
// Configure event
|
||||
e.stopPropagation();
|
||||
|
||||
// Error checking
|
||||
if (
|
||||
this.component == null ||
|
||||
e.button != 0 ||
|
||||
this.element.hasPointerCapture(e.pointerId)
|
||||
) return;
|
||||
|
||||
// Capture the pointer
|
||||
this.element.setPointerCapture(e.pointerId);
|
||||
this.dragPointer = e.pointerId;
|
||||
let bounds = this.component.getBounds();
|
||||
if (this.orientation == "horizontal") {
|
||||
this.dragPos = e.y;
|
||||
this.dragSize = bounds.height;
|
||||
} else {
|
||||
this.dragPos = e.x;
|
||||
this.dragSize = bounds.width;
|
||||
}
|
||||
}
|
||||
|
||||
// Pointer move event handler
|
||||
onpointermove(e) {
|
||||
|
||||
// Configure event
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
// Error checking
|
||||
if (
|
||||
this.component == null ||
|
||||
!this.element.hasPointerCapture(e.pointerId)
|
||||
) return;
|
||||
|
||||
// Resize the component
|
||||
let bounds = this.getBounds();
|
||||
let panel = this.parent.getBounds();
|
||||
switch (this.edge) {
|
||||
case "bottom":
|
||||
this.component.setSize(null, Math.max(0, Math.min(
|
||||
this.dragSize - e.y + this.dragPos,
|
||||
panel.height - bounds.height
|
||||
)));
|
||||
break;
|
||||
case "left":
|
||||
this.component.setSize(Math.max(0, Math.min(
|
||||
this.dragSize + e.x - this.dragPos,
|
||||
panel.width - bounds.width
|
||||
)), null);
|
||||
break;
|
||||
case "right":
|
||||
this.component.setSize(Math.max(0, Math.min(
|
||||
this.dragSize - e.x + this.dragPos,
|
||||
panel.width - bounds.width
|
||||
)), null);
|
||||
break;
|
||||
case "top":
|
||||
this.component.setSize(null, Math.max(0, Math.min(
|
||||
this.dragSize + e.y - this.dragPos,
|
||||
panel.height - bounds.height
|
||||
)));
|
||||
break;
|
||||
}
|
||||
this.measure();
|
||||
}
|
||||
|
||||
// Pointer up event handler
|
||||
onpointerup(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
this.element.releasePointerCapture(e.pointerId);
|
||||
this.dragPointer = null;
|
||||
}
|
||||
|
||||
};
|
||||
@@ -0,0 +1,138 @@
|
||||
"use strict";
|
||||
|
||||
Toolkit.TextBox = class TextBox extends Toolkit.Component {
|
||||
|
||||
constructor(application, options) {
|
||||
super(application, "input", options);
|
||||
options = options || {};
|
||||
|
||||
// Configure instance fields
|
||||
this.changeListeners = [];
|
||||
this.commitListeners = [];
|
||||
this.enabled = "enabled" in options ? !!options.enabled : true;
|
||||
this.name = options.name || "";
|
||||
this.lastCommit = "";
|
||||
|
||||
// Configure element
|
||||
this.element.size = 1;
|
||||
this.element.type = "text";
|
||||
this.element.addEventListener("blur" , e=>this.commit (e));
|
||||
this.element.addEventListener("input" , e=>this.onchange (e));
|
||||
this.element.addEventListener("keydown", e=>this.onkeydown(e));
|
||||
|
||||
// Configure properties
|
||||
this.setEnabled(this.enabled);
|
||||
this.setName (this.name );
|
||||
this.setText (options.text || "");
|
||||
this.application.addComponent(this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////// Public Methods //////////////////////////////
|
||||
|
||||
// Add a callback for change events
|
||||
addChangeListener(listener) {
|
||||
if (this.changeListeners.indexOf(listener) == -1)
|
||||
this.changeListeners.push(listener);
|
||||
}
|
||||
|
||||
// Add a callback for commit events
|
||||
addCommitListener(listener) {
|
||||
if (this.commitListeners.indexOf(listener) == -1)
|
||||
this.commitListeners.push(listener);
|
||||
}
|
||||
|
||||
// Request focus on the appropriate element
|
||||
focus() {
|
||||
this.element.focus();
|
||||
}
|
||||
|
||||
// Retrieve the component's accessible name
|
||||
getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
// Retrieve the component's display text
|
||||
getText() {
|
||||
return this.element.value;
|
||||
}
|
||||
|
||||
// Determine whether the component is enabled
|
||||
isEnabled() {
|
||||
return this.enabled;
|
||||
}
|
||||
|
||||
// Specify whether the component is enabled
|
||||
setEnabled(enabled) {
|
||||
this.enabled = enabled = !!enabled;
|
||||
this.element.setAttribute("aria-disabled", !enabled);
|
||||
if (enabled)
|
||||
this.element.removeAttribute("disabled");
|
||||
else this.element.setAttribute("disabled", "");
|
||||
}
|
||||
|
||||
// Specify the component's accessible name
|
||||
setName(name) {
|
||||
this.name = name || "";
|
||||
this.localize();
|
||||
}
|
||||
|
||||
// Specify the component's display text
|
||||
setText(text) {
|
||||
text = !text && text !== 0 ? "" : "" + text;
|
||||
this.lastCommit = text;
|
||||
this.element.value = text;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////// Package Methods /////////////////////////////
|
||||
|
||||
// Update display text with localized strings
|
||||
localize() {
|
||||
let name = this.name;
|
||||
if (this.application)
|
||||
name = this.application.translate(name, this);
|
||||
this.element.setAttribute("aria-label", name);
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////// Private Methods /////////////////////////////
|
||||
|
||||
// Input finalized
|
||||
commit(e) {
|
||||
let text = this.element.value || "";
|
||||
if (!this.enabled || text == this.lastCommit)
|
||||
return;
|
||||
this.lastCommit = text;
|
||||
for (let listener of this.commitListeners)
|
||||
listener(e, this);
|
||||
}
|
||||
|
||||
// Text changed event handler
|
||||
onchange(e) {
|
||||
e.stopPropagation();
|
||||
if (!this.enabled)
|
||||
return;
|
||||
for (let listener of this.changeListeners)
|
||||
listener(e, this);
|
||||
}
|
||||
|
||||
// Key press event handler
|
||||
onkeydown(e) {
|
||||
|
||||
// Configure event
|
||||
e.stopPropagation();
|
||||
|
||||
// Error checking
|
||||
if (!this.enabled)
|
||||
return;
|
||||
|
||||
// The Enter key was pressed
|
||||
if (e.key == "Enter")
|
||||
this.commit(e);
|
||||
}
|
||||
|
||||
};
|
||||
+102
-143
@@ -11,28 +11,22 @@ Toolkit.Window = class Window extends Toolkit.Panel {
|
||||
// Configure instance fields
|
||||
this.closeListeners = [];
|
||||
this.dragBounds = null;
|
||||
this.dragClient = null;
|
||||
this.dragCursor = { x: 0, y: 0 };
|
||||
this.dragEdge = null;
|
||||
this.dragPointer = null;
|
||||
this.initialCenter = "center" in options ? !!options.center : false;
|
||||
this.initialHeight = options.height || 64;
|
||||
this.initialWidth = options.width || 64;
|
||||
this.lastFocus = this.element;
|
||||
this.shown = this.visible;
|
||||
this.title = options.title || "";
|
||||
|
||||
// Configure element
|
||||
this.setLayout("flex", {
|
||||
alignCross: "stretch",
|
||||
direction : "column",
|
||||
overflowX : "visible",
|
||||
overflowY : "visible"
|
||||
});
|
||||
this.setLayout("grid", { columns: "auto" });
|
||||
this.setRole("dialog");
|
||||
this.setBounds(0, 0, 64, 64);
|
||||
this.setLocation(0, 0);
|
||||
this.element.style.position = "absolute";
|
||||
this.element.setAttribute("aria-modal", "false");
|
||||
this.element.setAttribute("focus" , "false");
|
||||
this.element.setAttribute("tabindex" , "-1" );
|
||||
this.element.setAttribute("tabindex" , "0" );
|
||||
this.element.addEventListener(
|
||||
"blur" , e=>this.onblur (e), { capture: true });
|
||||
this.element.addEventListener(
|
||||
@@ -42,69 +36,48 @@ Toolkit.Window = class Window extends Toolkit.Panel {
|
||||
this.element.addEventListener("pointermove", e=>this.onpointermove(e));
|
||||
this.element.addEventListener("pointerup" , e=>this.onpointerup (e));
|
||||
|
||||
// Configure body container
|
||||
// Primary visible container
|
||||
this.body = this.add(this.newPanel({
|
||||
layout : "flex",
|
||||
alignCross: "stretch",
|
||||
direction : "column",
|
||||
overflowX : "visible",
|
||||
overflowY : "visible"
|
||||
layout : "grid",
|
||||
overflowX: "visible",
|
||||
overflowY: "visible",
|
||||
rows : "max-content auto"
|
||||
}));
|
||||
this.body.element.style.flexGrow = "1";
|
||||
this.body.element.style.margin = "3px";
|
||||
this.body.element.setAttribute("name", "body");
|
||||
|
||||
// Configure title bar
|
||||
// Title bar
|
||||
this.titleBar = this.body.add(this.newPanel({
|
||||
layout : "flex",
|
||||
alignCross: "center",
|
||||
direction : "row",
|
||||
noShrink : true,
|
||||
overflowX : "visible",
|
||||
overflowY : "visible"
|
||||
layout : "grid",
|
||||
columns: "max-content auto max-content",
|
||||
hollow : false
|
||||
}));
|
||||
this.titleBar.element.setAttribute("name", "title-bar");
|
||||
|
||||
// Configure title icon element
|
||||
this.titleIcon = this.titleBar.add(this.newPanel({}));
|
||||
this.titleIcon.element.setAttribute("name", "title-icon");
|
||||
this.titleIcon.element.style.removeProperty("min-width");
|
||||
// Title bar icon
|
||||
this.titleIcon = this.titleBar.add(this.newPanel());
|
||||
this.titleIcon.element.setAttribute("name", "icon");
|
||||
this.titleIcon.element.setAttribute("aria-hidden", "true");
|
||||
|
||||
// Configure title text element
|
||||
this.titleElement = this.titleBar.add(this.newLabel({}));
|
||||
this.titleElement.element.setAttribute("name", "title");
|
||||
this.titleElement.element.style.cursor = "default";
|
||||
this.titleElement.element.style.flexGrow = "1";
|
||||
this.titleElement.element.style.userSelect = "none";
|
||||
this.element.setAttribute("aria-labelledby", this.titleElement.id);
|
||||
|
||||
// Configure title close element
|
||||
this.titleCloseBox = this.titleBar.add(this.newPanel({}));
|
||||
this.titleCloseBox.element.setAttribute("name", "title-close-box");
|
||||
this.titleCloseBox.element.style.removeProperty("min-width");
|
||||
this.titleClose = this.titleCloseBox.add(this.newButton({
|
||||
focusable: false,
|
||||
name : "{app.close}",
|
||||
toolTip : "{app.close}"
|
||||
// Title bar title
|
||||
this.title = this.titleBar.add(this.newLabel({
|
||||
localized: true,
|
||||
text : options.title
|
||||
}));
|
||||
this.titleClose.element.setAttribute("name", "title-close");
|
||||
this.title.element.setAttribute("name", "title");
|
||||
this.title.setProperty("sim", "");
|
||||
|
||||
// Title bar close
|
||||
this.titleClose = this.titleBar.add(this.newButton({
|
||||
toolTip: "{app.close}"
|
||||
}));
|
||||
this.titleClose.element.setAttribute("name", "close");
|
||||
this.titleClose.element.setAttribute("aria-hidden", "true");
|
||||
this.titleClose.addClickListener(e=>this.onclose(e));
|
||||
|
||||
// Configure client area
|
||||
this.client = this.body.add(this.newPanel({
|
||||
overflowX: "hidden",
|
||||
overflowY: "hidden"
|
||||
}));
|
||||
this.client.element.style.flexGrow = "1";
|
||||
// Client area
|
||||
this.client = this.body.add(this.newPanel());
|
||||
this.client.element.setAttribute("name", "client");
|
||||
this.client.element.addEventListener(
|
||||
"pointerdown", e=>this.onclientdown(e));
|
||||
|
||||
// Configure properties
|
||||
this.setTitle(this.title);
|
||||
if (this.shown)
|
||||
this.setClientSize(this.initialHeight, this.initialWidth);
|
||||
application.addComponent(this);
|
||||
this.setSize(options.width, options.height);
|
||||
}
|
||||
|
||||
|
||||
@@ -117,20 +90,19 @@ Toolkit.Window = class Window extends Toolkit.Panel {
|
||||
this.closeListeners.push(listener);
|
||||
}
|
||||
|
||||
// Specify the size of the client rectangle in pixels
|
||||
setClientSize(width, height) {
|
||||
let bounds = this.getBounds();
|
||||
let client = this.client.getBounds();
|
||||
this.setSize(
|
||||
width + bounds.width - client.width,
|
||||
height + bounds.height - client.height
|
||||
);
|
||||
// Retrieve the window's title text
|
||||
getTitle() {
|
||||
return this.title.getText();
|
||||
}
|
||||
|
||||
// Specify the height of the component
|
||||
setHeight(height, minimum) {
|
||||
this.client && this.client.setHeight(height, minimum);
|
||||
}
|
||||
|
||||
// Specify the window's title text
|
||||
setTitle(title) {
|
||||
this.title = title || "";
|
||||
this.localize();
|
||||
this.title.setText(title);
|
||||
}
|
||||
|
||||
// Specify whether the component is visible
|
||||
@@ -146,6 +118,12 @@ Toolkit.Window = class Window extends Toolkit.Panel {
|
||||
this.firstShow();
|
||||
}
|
||||
|
||||
// Specify the width of the component
|
||||
setWidth(width, minimum) {
|
||||
this.client && this.client.setWidth(
|
||||
Math.max(64, width || 0), minimum);
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////// Package Methods /////////////////////////////
|
||||
@@ -155,13 +133,23 @@ Toolkit.Window = class Window extends Toolkit.Panel {
|
||||
if (this.lastFocus != this)
|
||||
this.lastFocus.focus();
|
||||
else this.element.focus();
|
||||
this.parent.bringToFront(this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////// Private Methods /////////////////////////////
|
||||
|
||||
// Position the window in the center of the desktop
|
||||
center() {
|
||||
let bounds = this.getBounds();
|
||||
let desktop = this.parent.getBounds();
|
||||
this.contain(
|
||||
Math.floor((desktop.width - bounds.width ) / 2),
|
||||
Math.ceil ((desktop.height - bounds.height) / 2),
|
||||
desktop, bounds
|
||||
);
|
||||
}
|
||||
|
||||
// Position the window using a tentative location in the desktop
|
||||
contain(x, y, desktop, bounds, client) {
|
||||
desktop = desktop || this.parent.getBounds();
|
||||
@@ -213,28 +201,6 @@ Toolkit.Window = class Window extends Toolkit.Panel {
|
||||
// The window is being displayed for the first time
|
||||
firstShow() {
|
||||
this.shown = true;
|
||||
|
||||
// Configure the initial size of the window
|
||||
this.setClientSize(this.initialWidth, this.initialHeight);
|
||||
|
||||
// Configure the initial position of the window
|
||||
if (!this.initialCenter)
|
||||
return;
|
||||
let bounds = this.getBounds();
|
||||
let desktop = this.parent.getBounds();
|
||||
this.contain(
|
||||
Math.floor((desktop.width - bounds.width ) / 2),
|
||||
Math.ceil ((desktop.height - bounds.height) / 2),
|
||||
desktop, bounds
|
||||
);
|
||||
}
|
||||
|
||||
// Update display text with localized strings
|
||||
localize() {
|
||||
let title = this.title;
|
||||
if (this.application)
|
||||
title = this.application.translate(title, this);
|
||||
this.titleElement.element.innerText = title;
|
||||
}
|
||||
|
||||
// Focus lost event capture
|
||||
@@ -243,13 +209,6 @@ Toolkit.Window = class Window extends Toolkit.Panel {
|
||||
this.element.setAttribute("focus", "false");
|
||||
}
|
||||
|
||||
// Client pointer down event handler
|
||||
onclientdown(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
this.focus();
|
||||
}
|
||||
|
||||
// Window close
|
||||
onclose(e) {
|
||||
for (let listener of this.closeListeners)
|
||||
@@ -258,52 +217,45 @@ Toolkit.Window = class Window extends Toolkit.Panel {
|
||||
|
||||
// Focus gained event capture
|
||||
onfocus(e) {
|
||||
|
||||
// Configure element
|
||||
this.element.setAttribute("focus", "true");
|
||||
|
||||
// Working variables
|
||||
let target = e.target;
|
||||
|
||||
// Delegate focus to the most recently focused component
|
||||
if (target == this.element)
|
||||
target = this.lastFocus;
|
||||
|
||||
// The component is not visible: focus on self instead
|
||||
if ("component" in target && !target.component.isVisible())
|
||||
target = this.element;
|
||||
|
||||
// Configure instance fields
|
||||
this.lastFocus = target;
|
||||
|
||||
// Transfer focus to the correct component
|
||||
if (target != e.target)
|
||||
target.focus();
|
||||
this.parent.bringToFront(this);
|
||||
}
|
||||
|
||||
// Key down event handler
|
||||
// Key pressed event handler
|
||||
onkeydown(e) {
|
||||
|
||||
// Processing by key
|
||||
switch (e.key) {
|
||||
default: return;
|
||||
}
|
||||
// Only listening for Escape while dragging
|
||||
if (e.key != "Escape" || this.dragPointer === null)
|
||||
return;
|
||||
|
||||
// Configure event
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
// Restore the window's position
|
||||
let desktop = this.parent.getBounds();
|
||||
this.setLocation(
|
||||
this.dragBounds.x - desktop.x,
|
||||
this.dragBounds.y - desktop.y
|
||||
);
|
||||
|
||||
// Restore the window's size
|
||||
if (this.dragEdge != null)
|
||||
this.setSize(this.dragClient.width, this.dragClient.height);
|
||||
|
||||
// Configure instance fields
|
||||
this.element.releasePointerCapture(this.dragPointer);
|
||||
this.dragPointer = null;
|
||||
}
|
||||
|
||||
// Pointer down event handler
|
||||
onpointerdown(e) {
|
||||
|
||||
// Configure event
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
// Configure element
|
||||
this.focus();
|
||||
|
||||
// Error checking
|
||||
if (
|
||||
e.button != 0 ||
|
||||
@@ -312,12 +264,19 @@ Toolkit.Window = class Window extends Toolkit.Panel {
|
||||
|
||||
// Configure instance fields
|
||||
this.dragBounds = this.getBounds();
|
||||
this.dragEdge = this.edge(e, this.dragBounds);
|
||||
this.dragClient = this.client.getBounds();
|
||||
this.dragCursor.x = e.x;
|
||||
this.dragCursor.y = e.y;
|
||||
this.dragEdge = this.edge(e, this.dragBounds);
|
||||
|
||||
// Don't perform a move if the cursor isn't in the title bar
|
||||
let title = this.titleBar.getBounds();
|
||||
if (this.dragEdge == null && e.y >= title.y + title.height)
|
||||
return;
|
||||
|
||||
// Configure element
|
||||
this.element.setPointerCapture(e.pointerId);
|
||||
this.dragPointer = e.pointerId;
|
||||
}
|
||||
|
||||
// Pointer move event handler
|
||||
@@ -337,12 +296,11 @@ Toolkit.Window = class Window extends Toolkit.Panel {
|
||||
}
|
||||
|
||||
// Working variables
|
||||
let rX = e.x - this.dragCursor.x;
|
||||
let rY = e.y - this.dragCursor.y;
|
||||
let bounds = this.getBounds();
|
||||
let desktop = this.parent.getBounds();
|
||||
let client = this.client.getBounds();
|
||||
let minHeight = bounds.height - client.height;
|
||||
let rX = e.x - this.dragCursor.x;
|
||||
let rY = e.y - this.dragCursor.y;
|
||||
let bounds = this.getBounds();
|
||||
let desktop = this.parent.getBounds();
|
||||
let client = this.client.getBounds();
|
||||
|
||||
// Move the window
|
||||
if (this.dragEdge == null) {
|
||||
@@ -358,7 +316,7 @@ Toolkit.Window = class Window extends Toolkit.Panel {
|
||||
if (this.dragEdge.startsWith("n")) {
|
||||
let maxTop = desktop.height - client.y + bounds.y;
|
||||
let top = this.dragBounds.y - desktop.y + rY;
|
||||
let height = this.dragBounds.height - rY;
|
||||
let height = this.dragClient.height - rY;
|
||||
|
||||
// Restrict window bounds
|
||||
if (top > maxTop) {
|
||||
@@ -369,9 +327,9 @@ Toolkit.Window = class Window extends Toolkit.Panel {
|
||||
height += top;
|
||||
top = 0;
|
||||
}
|
||||
if (height < minHeight) {
|
||||
top -= minHeight - height;
|
||||
height = minHeight;
|
||||
if (height < 0) {
|
||||
top += height;
|
||||
height = 0;
|
||||
}
|
||||
|
||||
// Configure element
|
||||
@@ -383,7 +341,7 @@ Toolkit.Window = class Window extends Toolkit.Panel {
|
||||
if (this.dragEdge.endsWith("w")) {
|
||||
let maxLeft = desktop.width - 16;
|
||||
let left = this.dragBounds.x - desktop.x + rX;
|
||||
let width = this.dragBounds.width - rX;
|
||||
let width = this.dragClient.width - rX;
|
||||
|
||||
// Restrict window bounds
|
||||
if (left > maxLeft) {
|
||||
@@ -402,11 +360,11 @@ Toolkit.Window = class Window extends Toolkit.Panel {
|
||||
|
||||
// Resizing on the east edge
|
||||
if (this.dragEdge.endsWith("e")) {
|
||||
let width = this.dragBounds.width + rX;
|
||||
let width = this.dragClient.width + rX;
|
||||
|
||||
// Restrict window bounds
|
||||
width = Math.max(64, width);
|
||||
width = Math.max(width, -this.dragBounds.x + 16);
|
||||
width = Math.max(width, -this.dragClient.x + 16);
|
||||
|
||||
// Configure element
|
||||
this.setWidth(width);
|
||||
@@ -414,10 +372,10 @@ Toolkit.Window = class Window extends Toolkit.Panel {
|
||||
|
||||
// Resizing on the south edge
|
||||
if (this.dragEdge.startsWith("s")) {
|
||||
let height = this.dragBounds.height + rY;
|
||||
let height = this.dragClient.height + rY;
|
||||
|
||||
// Restrict window bounds
|
||||
height = Math.max(minHeight, height);
|
||||
height = Math.max(0, height);
|
||||
|
||||
// Configure element
|
||||
this.setHeight(height);
|
||||
@@ -438,6 +396,7 @@ Toolkit.Window = class Window extends Toolkit.Panel {
|
||||
|
||||
// Configure element
|
||||
this.element.releasePointerCapture(e.pointerId);
|
||||
this.dragPointer = null;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user