Adding Memory window

This commit is contained in:
2021-08-30 02:14:06 +00:00
parent f753f9f59b
commit b2adf1f9dc
20 changed files with 1260 additions and 96 deletions
+15 -6
View File
@@ -39,11 +39,6 @@ Toolkit.Component = class Component {
this.resizeListeners.push(listener);
}
// Remove the component from its parent
remove() {
this.parent && this.parent.remove(this);
}
// Retrieve the bounding box of the element
getBounds() {
return this.element.getBoundingClientRect();
@@ -62,6 +57,14 @@ Toolkit.Component = class Component {
return true;
}
// Specify the location and size of the component
setBounds(left, top, width, height) {
this.setLeft (left );
this.setTop (top );
this.setWidth (width );
this.setHeight(height);
}
// Specify the display CSS property of the visible element
setDisplay(display) {
this.display = display || null;
@@ -90,6 +93,12 @@ Toolkit.Component = class Component {
this.setTop (top );
}
// Specify a localization property value
setProperty(key, value) {
this.properties[key] = value;
this.localize();
}
// Specify both the width and the height of the component
setSize(width, height) {
this.setHeight(height);
@@ -146,7 +155,7 @@ Toolkit.Component = class Component {
onresized() {
let bounds = this.getBounds();
for (let listener of this.resizeListeners)
listener(bounds, this);
listener(bounds);
}
};
+52
View File
@@ -0,0 +1,52 @@
"use strict";
// Display text component
Toolkit.Label = class Label extends Toolkit.Component {
// Object constructor
constructor(application, options) {
super(application, "div", options);
options = options || {};
// Configure instance fields
this.localized = "localized" in options ? !!options.localized : false;
this.text = options.text || "";
// Configure element
this.element.style.cursor = "default";
this.element.style.userSelect = "none";
// Configure properties
this.setText(this.text);
if (this.localized)
this.application.addComponent(this);
}
///////////////////////////// Public Methods //////////////////////////////
// Retrieve the label's display text
getText() {
return this.text;
}
// Specify the label's display text
setText(text) {
this.text = text || "";
this.localize();
}
///////////////////////////// Package Methods /////////////////////////////
// Update display text with localized strings
localize() {
let text = this.text;
if (this.localized && this.application)
text = this.application.translate(text, this);
this.element.innerText = text;
}
};
+9
View File
@@ -17,6 +17,9 @@ Toolkit.Menu = class Menu extends Toolkit.MenuItem {
this.menu.element.style.position = "absolute";
this.menu.element.setAttribute("role", "menu");
this.menu.element.setAttribute("aria-labelledby", this.id);
this.menu.element.addEventListener("pointerdown",e=>this.stopEvent(e));
this.menu.element.addEventListener("pointermove",e=>this.stopEvent(e));
this.menu.element.addEventListener("pointerup" ,e=>this.stopEvent(e));
this.containers.push(this.menu);
this.children = this.menu.children;
@@ -213,4 +216,10 @@ Toolkit.Menu = class Menu extends Toolkit.MenuItem {
e.stopPropagation();
}
// Prevent an event from bubbling
stopEvent(e) {
e.preventDefault();
e.stopPropagation();
}
};
+24 -8
View File
@@ -6,9 +6,9 @@ Toolkit.Panel = class Panel extends Toolkit.Component {
// Object constructor
constructor(application, options) {
super(application, "div", options);
options = options || {};
// Configure instance fields
options = options || {};
this.alignCross = "start";
this.alignMain = "start";
this.application = application;
@@ -22,8 +22,10 @@ Toolkit.Panel = class Panel extends Toolkit.Component {
this.wrap = false;
// Configure element
this.element.style.minHeight = "0";
this.element.style.minWidth = "0";
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
@@ -57,6 +59,11 @@ Toolkit.Panel = class Panel extends Toolkit.Component {
return new Toolkit.Button(this.application, options);
}
// Create a Label and associate it with the application
newLabel(options) {
return new Toolkit.Label(this.application, options);
}
// Create a MenuBar and associate it with the application
newMenuBar(options) {
return new Toolkit.MenuBar(this.application, options);
@@ -141,6 +148,16 @@ Toolkit.Panel = class Panel extends Toolkit.Component {
///////////////////////////// Package Methods /////////////////////////////
// Move a window to the foreground
bringToFront(wnd) {
for (let child of this.children)
child.element.style.zIndex = child == wnd ? "0" : "1";
}
///////////////////////////// Private Methods /////////////////////////////
// Resize event handler
@@ -152,12 +169,13 @@ Toolkit.Panel = class Panel extends Toolkit.Component {
// Ensure all child windows are visible in the viewport
for (let wnd of this.children) {
if (!wnd.isVisible())
continue;
let bounds = wnd.getBounds();
wnd.contain(
desktop,
bounds,
bounds.x - desktop.x,
bounds.y - desktop.y
bounds.y - desktop.y,
desktop, bounds
);
}
@@ -244,8 +262,6 @@ Toolkit.Panel = class Panel extends Toolkit.Component {
this.element.style.removeProperty("grid-template-rows" );
this.element.style.removeProperty("justify-content" );
this.element.style.removeProperty("flex-direction" );
this.element.style.removeProperty("overflow-x" );
this.element.style.removeProperty("overflow-y" );
}
};
+74 -13
View File
@@ -9,11 +9,16 @@ Toolkit.Window = class Window extends Toolkit.Panel {
options = options || {};
// Configure instance fields
this.dragBounds = null;
this.dragCursor = { x: 0, y: 0 };
this.dragEdge = null;
this.lastFocus = this.element;
this.title = options.title || "";
this.closeListeners = [];
this.dragBounds = null;
this.dragCursor = { x: 0, y: 0 };
this.dragEdge = 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", {
@@ -23,6 +28,7 @@ Toolkit.Window = class Window extends Toolkit.Panel {
overflowY : "visible"
});
this.setRole("dialog");
this.setBounds(0, 0, 64, 64);
this.element.style.position = "absolute";
this.element.setAttribute("aria-modal", "false");
this.element.setAttribute("focus" , "false");
@@ -53,6 +59,7 @@ Toolkit.Window = class Window extends Toolkit.Panel {
layout : "flex",
alignCross: "center",
direction : "row",
noShrink : true,
overflowX : "visible",
overflowY : "visible"
}));
@@ -64,7 +71,7 @@ Toolkit.Window = class Window extends Toolkit.Panel {
this.titleIcon.element.style.removeProperty("min-width");
// Configure title text element
this.titleElement = this.titleBar.add(this.newPanel({}));
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";
@@ -81,9 +88,13 @@ Toolkit.Window = class Window extends Toolkit.Panel {
toolTip : "{app.close}"
}));
this.titleClose.element.setAttribute("name", "title-close");
this.titleClose.addClickListener(e=>this.onclose(e));
// Configure client area
this.client = this.body.add(this.newPanel({}));
this.client = this.body.add(this.newPanel({
overflowX: "hidden",
overflowY: "hidden"
}));
this.client.element.style.flexGrow = "1";
this.client.element.setAttribute("name", "client");
this.client.element.addEventListener(
@@ -91,6 +102,8 @@ Toolkit.Window = class Window extends Toolkit.Panel {
// Configure properties
this.setTitle(this.title);
if (this.shown)
this.setClientSize(this.initialHeight, this.initialWidth);
application.addComponent(this);
}
@@ -98,6 +111,12 @@ Toolkit.Window = class Window extends Toolkit.Panel {
///////////////////////////// Public Methods //////////////////////////////
// Add a callback for close events
addCloseListener(listener) {
if (this.closeListeners.indexOf(listener) == -1)
this.closeListeners.push(listener);
}
// Specify the size of the client rectangle in pixels
setClientSize(width, height) {
let bounds = this.getBounds();
@@ -114,6 +133,19 @@ Toolkit.Window = class Window extends Toolkit.Panel {
this.localize();
}
// Specify whether the component is visible
setVisible(visible, focus) {
super.setVisible(visible);
if (this.client === undefined)
return;
if (visible)
this.contain();
if (focus)
this.focus();
if (!this.shown)
this.firstShow();
}
///////////////////////////// Package Methods /////////////////////////////
@@ -123,6 +155,7 @@ Toolkit.Window = class Window extends Toolkit.Panel {
if (this.lastFocus != this)
this.lastFocus.focus();
else this.element.focus();
this.parent.bringToFront(this);
}
@@ -130,9 +163,14 @@ Toolkit.Window = class Window extends Toolkit.Panel {
///////////////////////////// Private Methods /////////////////////////////
// Position the window using a tentative location in the desktop
contain(desktop, bounds, x, y, client) {
bounds = bounds || this.getBounds();
client = client || this.client.getBounds();
contain(x, y, desktop, bounds, client) {
desktop = desktop || this.parent.getBounds();
bounds = bounds || this.getBounds();
client = client || this.client.getBounds();
if (x === undefined)
x = bounds.x - desktop.x;
if (y === undefined)
y = bounds.y - desktop.y;
// Restrict window position
x = Math.min(x, desktop.width - 16);
@@ -172,6 +210,25 @@ Toolkit.Window = class Window extends Toolkit.Panel {
return null;
}
// 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;
@@ -193,6 +250,12 @@ Toolkit.Window = class Window extends Toolkit.Panel {
this.focus();
}
// Window close
onclose(e) {
for (let listener of this.closeListeners)
listener(e);
}
// Focus gained event capture
onfocus(e) {
@@ -284,11 +347,9 @@ Toolkit.Window = class Window extends Toolkit.Panel {
// Move the window
if (this.dragEdge == null) {
this.contain(
desktop,
bounds,
this.dragBounds.x - desktop.x + rX,
this.dragBounds.y - desktop.y + rY,
client
desktop, bounds, client
);
return;
}