diff --git a/src/gui/src/UI/UIWindowTaskManager.js b/src/gui/src/UI/UIWindowTaskManager.js
index 177550658..d7c6ab4d7 100644
--- a/src/gui/src/UI/UIWindowTaskManager.js
+++ b/src/gui/src/UI/UIWindowTaskManager.js
@@ -19,8 +19,7 @@
import { END_HARD, END_SOFT } from "../definitions.js";
import UIAlert from "./UIAlert.js";
import UIContextMenu from "./UIContextMenu.js";
-import { Component, defineComponent } from '../util/Component.js';
-import UIComponentWindow from './UIComponentWindow.js';
+import UIWindow from './UIWindow.js';
const end_process = async (uuid, force) => {
const svc_process = globalThis.services.get('process');
@@ -62,310 +61,122 @@ const end_process = async (uuid, force) => {
process.signal(force ? END_HARD : END_SOFT);
};
-class TaskManagerTable extends Component {
- static ID = 'ui.component.TaskManagerTable';
- static PROPERTIES = {
- tasks: { value: [] },
- };
+const calculate_indent_string = (indent_level, is_last_item_stack, is_last_item) => {
+ // Returns a string of '| ├└'
+ let result = '';
- static CSS = /*css*/`
- :host {
- flex-grow: 1;
- display: flex;
- flex-direction: column;
- background-color: rgba(255,255,255,0.8);
- border: 2px inset rgba(127, 127, 127, 0.3);
- overflow: auto;
- }
+ for ( let i=0; i < indent_level; i++ ) {
+ const last_cell = i === indent_level - 1;
+ const has_trunk = (last_cell && ( ! is_last_item )) ||
+ (!last_cell && !is_last_item_stack[i+1]);
+ const has_branch = last_cell;
- table {
- box-sizing: border-box;
- border-collapse: collapse;
- width: 100%;
+ if (has_trunk && has_branch) {
+ result += '├';
+ } else if (has_trunk) {
+ result += '|';
+ } else if (has_branch) {
+ result += '└';
+ } else {
+ result += ' ';
}
-
- thead th {
- box-shadow: 0 1px 4px -2px rgba(0,0,0,0.2);
- backdrop-filter: blur(2px);
- position: sticky;
- z-index: 100;
- padding:
- calc(10 * var(--scale))
- calc(2.5 * var(--scale))
- calc(5 * var(--scale))
- calc(2.5 * var(--scale));
- top: 0;
- background-color: hsla(0, 0%, 100%, 0.8);
- text-align: left;
- border-bottom: 1px solid #e0e0e0;
- }
-
- thead th:not(:last-of-type) {
- border-right: 1px solid #e0e0e0;
- }
-
- tbody > tr > td {
- border-bottom: 1px solid #e0e0e0;
- padding: 0 calc(2.5 * var(--scale));
- vertical-align: middle;
- }
- `;
-
- #svc_process = globalThis.services.get('process');
-
- create_template ({ template }) {
- $(template).html(`
-
-
-
- | ${i18n('taskmgr_header_name')} |
- ${i18n('taskmgr_header_type')} |
- ${i18n('taskmgr_header_status')} |
-
-
-
-
-
- `);
}
- on_ready ({ listen }) {
- listen('tasks', tasks => {
- const row_data = this.#iter_tasks(tasks, { indent_level: 0, is_last_item_stack: [] });
- const tbody = $(this.dom_).find('.taskmgr-taskarea');
- tbody.empty();
+ return result;
+};
- for (const data of row_data) {
- const row = new TaskManagerRow(data);
- row.attach(tbody[0]);
- }
- });
- }
-
- #calculate_indent_string (indent_level, is_last_item_stack, is_last_item) {
- // Returns a string of '| ├└'
- let result = '';
-
- for ( let i=0; i < indent_level; i++ ) {
- const last_cell = i === indent_level - 1;
- const has_trunk = (last_cell && ( ! is_last_item )) ||
- (!last_cell && !is_last_item_stack[i+1]);
- const has_branch = last_cell;
-
- if (has_trunk && has_branch) {
- result += '├';
- } else if (has_trunk) {
- result += '|';
- } else if (has_branch) {
- result += '└';
- } else {
- result += ' ';
+const generate_task_rows = (items, { indent_level, is_last_item_stack }) => {
+ const svc_process = globalThis.services.get('process');
+ let rows_html = '';
+
+ for (let i = 0; i < items.length; i++) {
+ const item = items[i];
+ const is_last_item = i === items.length - 1;
+ const indentation = calculate_indent_string(indent_level, is_last_item_stack, is_last_item);
+
+ // Generate indentation HTML
+ let indentation_html = '';
+ for (const c of indentation) {
+ indentation_html += ``;
+ switch (c) {
+ case ' ':
+ break;
+ case '|':
+ indentation_html += `
`;
+ break;
+ case '└':
+ indentation_html += `
`;
+ break;
+ case '├':
+ indentation_html += `
`;
+ indentation_html += `
`;
+ break;
}
+ indentation_html += `
`;
}
- return result;
- }
-
- #iter_tasks (items, { indent_level, is_last_item_stack }) {
- const rows = [];
- for (let i = 0; i < items.length; i++) {
- const item = items[i];
- const is_last_item = i === items.length - 1;
- rows.push({
- name: item.name,
- uuid: item.uuid,
- process_type: item.type,
- process_status: item.status.i18n_key,
- indentation: this.#calculate_indent_string(indent_level, is_last_item_stack, is_last_item),
- });
-
- const children = this.#svc_process.get_children_of(item.uuid);
- if (children) {
- rows.push(...this.#iter_tasks(children, {
- indent_level: indent_level + 1,
- is_last_item_stack:
- [ ...is_last_item_stack, is_last_item ],
- }));
- }
- }
- return rows;
- };
-}
-defineComponent(TaskManagerTable);
-
-class TaskManagerRow extends Component {
- static ID = 'ui.component.TaskManagerRow';
-
- static PROPERTIES = {
- name: {},
- uuid: {},
- process_type: {},
- process_status: {},
- indentation: { value: '' },
- };
-
- static CSS = /*css*/`
- :host {
- display: table-row;
- }
-
- td > span {
- padding: 0 calc(2.5 * var(--scale));
- }
-
- .task {
- display: flex;
- height: calc(10 * var(--scale));
- line-height: calc(10 * var(--scale));
- }
-
- .task-name {
- flex-grow: 1;
- padding-left: calc(2.5 * var(--scale));
- }
-
- .task-indentation {
- display: flex;
- }
-
- .indentcell {
- position: relative;
- align-items: right;
- width: calc(10 * var(--scale));
- height: calc(10 * var(--scale));
- }
-
- .indentcell-trunk {
- position: absolute;
- top: 0;
- left: calc(5 * var(--scale));
- width: calc(5 * var(--scale));
- height: calc(10 * var(--scale));
- border-left: 2px solid var(--line-color);
- }
-
- .indentcell-branch {
- position: absolute;
- top: 0;
- left: calc(5 * var(--scale));
- width: calc(5 * var(--scale));
- height: calc(5 * var(--scale));
- border-left: 2px solid var(--line-color);
- border-bottom: 2px solid var(--line-color);
- border-radius: 0 0 0 calc(2.5 * var(--scale));
- }
- `;
-
- create_template ({ template }) {
- template.innerHTML = `
-
-
- |
- |
- |
+ rows_html += `
+
+
+
+ ${indentation_html}
+ ${item.name}
+
+ |
+ ${i18n('process_type_' + item.type)} |
+ ${i18n('process_status_' + item.status.i18n_key)} |
+
`;
- }
- on_ready ({ listen }) {
- listen('name', name => {
- $(this.dom_).find('.task-name').text(name);
- });
- listen('uuid', uuid => {
- this.setAttribute('data-uuid', uuid);
- });
- listen('process_type', type => {
- $(this.dom_).find('.process-type').text(i18n('process_type_' + type));
- });
- listen('process_status', status => {
- $(this.dom_).find('.process-status').text(i18n('process_status_' + status));
- });
- listen('indentation', indentation => {
- const el = $(this.dom_).find('.task-indentation');
- let h = '';
- for (const c of indentation) {
- h += ``;
- switch (c) {
- case ' ':
- break;
- case '|':
- h += `
`;
- break;
- case '└':
- h += `
`;
- break;
- case '├':
- h += `
`;
- h += `
`;
- break;
- }
- h += `
`;
- }
- el.html(h);
- });
-
- $(this).on('contextmenu', () => {
- const uuid = this.get('uuid');
- UIContextMenu({
- items: [
- {
- html: i18n('close'),
- onClick: () => {
- end_process(uuid);
- },
- },
- {
- html: i18n('force_quit'),
- onClick: () => {
- end_process(uuid, true);
- },
- },
- ],
+ const children = svc_process.get_children_of(item.uuid);
+ if (children) {
+ rows_html += generate_task_rows(children, {
+ indent_level: indent_level + 1,
+ is_last_item_stack: [ ...is_last_item_stack, is_last_item ],
});
- });
+ }
}
-}
-defineComponent(TaskManagerRow);
+
+ return rows_html;
+};
const UIWindowTaskManager = async function UIWindowTaskManager () {
const svc_process = globalThis.services.get('process');
- let task_manager_table = new TaskManagerTable({
- tasks: [svc_process.get_init()],
- });
+ let h = '';
- const interval = setInterval(() => {
- const processes = [svc_process.get_init()];
- task_manager_table.set('tasks', processes);
- }, 500);
+ h += ``;
+ h += `
`;
+ h += ``;
+ h += ``;
+ h += `| ${i18n('taskmgr_header_name')} | `;
+ h += `${i18n('taskmgr_header_type')} | `;
+ h += `${i18n('taskmgr_header_status')} | `;
+ h += `
`;
+ h += ``;
+ h += ``;
+ h += ``;
+ h += `
`;
+ h += `
`;
- const w = await UIComponentWindow({
- component: task_manager_table,
- window_class: 'window-task-manager',
+ const el_window = await UIWindow({
title: i18n('task_manager'),
icon: globalThis.icons['cog.svg'],
uid: null,
is_dir: false,
- message: 'message',
single_instance: true,
app: 'taskmgr',
- // body_icon: options.body_icon,
- // backdrop: options.backdrop ?? false,
is_resizable: true,
is_droppable: false,
has_head: true,
selectable_body: true,
draggable_body: false,
allow_context_menu: false,
- // allow_native_ctxmenu: true,
show_in_taskbar: true,
dominant: true,
- body_content: '',
+ body_content: h,
width: 350,
- // parent_uuid: options.parent_uuid,
- // ...options.window_options,
+ window_class: 'window-task-manager',
window_css:{
height: 'initial',
},
@@ -379,17 +190,55 @@ const UIWindowTaskManager = async function UIWindowTaskManager () {
var(--primary-alpha))`,
'backdrop-filter': 'blur(3px)',
'box-sizing': 'border-box',
- // could have been avoided with box-sizing: border-box
height: 'calc(100% - 30px)',
display: 'flex',
'flex-direction': 'column',
'--scale': '2pt',
'--line-color': '#6e6e6ebd',
- },
- on_close: () => {
- clearInterval(interval);
+ padding: '0',
},
});
+
+ const update_tasks = () => {
+ const processes = [svc_process.get_init()];
+ const rows_html = generate_task_rows(processes, { indent_level: 0, is_last_item_stack: [] });
+ $(el_window).find('.taskmgr-taskarea').html(rows_html);
+ };
+
+ // Set up context menu for task rows
+ $(el_window).on('contextmenu', '.task-row', function(e) {
+ e.preventDefault();
+ const uuid = $(this).data('uuid');
+ UIContextMenu({
+ items: [
+ {
+ html: i18n('close'),
+ onClick: () => {
+ end_process(uuid);
+ },
+ },
+ {
+ html: i18n('force_quit'),
+ onClick: () => {
+ end_process(uuid, true);
+ },
+ },
+ ],
+ });
+ });
+
+ // Initial task update
+ update_tasks();
+
+ // Set up interval to refresh tasks
+ const interval = setInterval(update_tasks, 500);
+
+ // Clean up interval when window is closed
+ $(el_window).on('close', () => {
+ clearInterval(interval);
+ });
+
+ return el_window;
}
export default UIWindowTaskManager;
diff --git a/src/gui/src/css/style.css b/src/gui/src/css/style.css
index d0f660cc8..b8cfff317 100644
--- a/src/gui/src/css/style.css
+++ b/src/gui/src/css/style.css
@@ -2525,6 +2525,96 @@ label {
height: 40px;
}
+/*****************************************************
+ * Task Manager
+ *****************************************************/
+
+.task-manager-container {
+ flex-grow: 1;
+ display: flex;
+ flex-direction: column;
+ background-color: rgba(255,255,255,0.8);
+ border: 2px inset rgba(127, 127, 127, 0.3);
+ overflow: auto;
+}
+
+.task-manager-container table {
+ box-sizing: border-box;
+ border-collapse: collapse;
+ width: 100%;
+}
+
+.task-manager-container thead th {
+ box-shadow: 0 1px 4px -2px rgba(0,0,0,0.2);
+ backdrop-filter: blur(2px);
+ position: sticky;
+ z-index: 100;
+ padding: calc(10 * var(--scale)) calc(2.5 * var(--scale)) calc(5 * var(--scale)) calc(2.5 * var(--scale));
+ top: 0;
+ background-color: hsla(0, 0%, 100%, 0.8);
+ text-align: left;
+ border-bottom: 1px solid #e0e0e0;
+ padding: 5px;
+}
+
+.task-manager-container thead th:not(:last-of-type) {
+ border-right: 1px solid #e0e0e0;
+}
+
+.task-manager-container tbody > tr > td {
+ border-bottom: 1px solid #e0e0e0;
+ padding: 0 calc(2.5 * var(--scale));
+ vertical-align: middle;
+ padding-left: 0;
+}
+
+.task-manager-container td > span {
+ padding: 0 calc(2.5 * var(--scale));
+}
+
+.task {
+ display: flex;
+ height: calc(10 * var(--scale));
+ line-height: calc(10 * var(--scale));
+}
+
+.task-name {
+ flex-grow: 1;
+ padding-left: calc(2.5 * var(--scale));
+}
+
+.task-indentation {
+ display: flex;
+}
+
+.indentcell {
+ position: relative;
+ align-items: right;
+ width: calc(10 * var(--scale));
+ height: calc(10 * var(--scale));
+}
+
+.indentcell-trunk {
+ position: absolute;
+ top: 0;
+ left: calc(5 * var(--scale));
+ width: calc(5 * var(--scale));
+ height: calc(10 * var(--scale));
+ border-left: 2px solid var(--line-color);
+}
+
+.indentcell-branch {
+ position: absolute;
+ top: 0;
+ left: calc(5 * var(--scale));
+ width: calc(5 * var(--scale));
+ height: calc(5 * var(--scale));
+ border-left: 2px solid var(--line-color);
+ border-bottom: 2px solid var(--line-color);
+ border-radius: 0 0 0 calc(2.5 * var(--scale));
+}
+
+
#clock {
display: none;
color: white;