//build:20240724 /** * Basic UI components. First, you need to understand some concepts: * 1. Layers: The device has 2 basic layers, the main layer (main) and the top layer (top) The TOP layer is always above the main layer. Switching pages on the main layer won't cover the TOP layer. The TOP layer is suitable for displaying status bars. Multiple pages can be pre-constructed in memory for the main layer, then loaded and switched using loadMain. The TOP layer cannot be switched, only hidden or deleted. * 2. UI Objects: There are many types of UI objects. The most basic is the 'view' object. The root UI object of the main and top layers must be a 'view' object. The rest of the UI objects are children of some UI object. UI objects include common 'button', 'label', 'image', etc. All objects have some common properties and some unique properties. All UI objects have a globally unique id that cannot be duplicated. Common properties also include: - type: Get the UI object type, string - parent: Get the parent node of the UI object, string - children: Get all child object ids of the UI object, string array * 3. dxui files: Files with .dxui extension are UI trees generated by visual drag-and-drop tools. The tool automatically generates corresponding js files that can be imported and operated. */ import logger from './dxLogger.js' import utils from './uiUtils.js' import button from './uiButton.js' import font from './uiFont.js' import image from './uiImage.js' import label from './uiLabel.js' import line from './uiLine.js' import list from './uiList.js' import dropdown from './uiDropdown.js' import checkbox from './uiCheckbox.js' import slider from './uiSlider.js' import _switch from './uiSwitch.js' import textarea from './uiTextarea.js' import keyboard from './uiKeyboard.js' import style from './uiStyle.js' import view from './uiView.js' import buttons from './uiButtons.js' const dxui = {} dxui.Button = button dxui.Font = font dxui.Image = image dxui.Label = label dxui.Line = line dxui.List = list dxui.Dropdown = dropdown dxui.Checkbox = checkbox dxui.Slider = slider dxui.Switch = _switch dxui.Textarea = textarea dxui.Keyboard = keyboard dxui.Style = style dxui.View = view dxui.Utils = utils dxui.Buttons = buttons let orientation = 1 //Default landscape /** * Initialize, must be called at the beginning of the code * @param {object} options Initialization parameters * @param {number} options.orientation Screen orientation, can be 0, 1, 2, 3, representing portrait with screen on left; landscape with screen on top; portrait with screen on right; landscape with screen on bottom * @param {object} context Context, each application has a unique context variable. Different js files can reference dxUi.js, but context must be consistent */ dxui.init = function (options, context = {}) { this.initContext(context) if (options && options.orientation != undefined && options.orientation != null && [0, 1, 2, 3].includes(options.orientation)) { orientation = options.orientation } utils.GG.NativeDisp.lvDispSetRotation(orientation) } /** * Initialize context. Each application has a unique context variable. Different js files can reference dxUi.js, but context must be consistent * Context needs to be initialized before building UI * @param {object} context Initially an empty object {} */ dxui.initContext = function (context) { utils.validateObject(context) dxui.all = context dxui.Button.all = dxui.all dxui.Image.all = dxui.all dxui.Label.all = dxui.all dxui.Line.all = dxui.all dxui.List.all = dxui.all dxui.Dropdown.all = dxui.all dxui.Checkbox.all = dxui.all dxui.Slider.all = dxui.all dxui.Switch.all = dxui.all dxui.Textarea.all = dxui.all dxui.Keyboard.all = dxui.all dxui.View.all = dxui.all dxui.Buttons.all = dxui.all } /** * Get the already built UI object by id * @param {string} id * @returns */ dxui.getUi = function (id) { return dxui.all[id] } /** * External loop needs to call this method */ dxui.handler = function () { return utils.GG.NativeTimer.lvTimerHandler() } /** * Get screen orientation. Different screen orientations may require loading different UI or different processing logic * @returns Can be 0, 1, 2, 3, representing portrait with screen on left; landscape with screen on top; portrait with screen on right; landscape with screen on bottom */ dxui.getOrientation = function () { return orientation; } /** * Create a timer that executes the callback function every ms milliseconds, mainly used to periodically refresh a UI object's value * Can delete the timer (clearInterval) in the callback function to achieve setTimeout effect * @param {string} id Unique identifier for the timer Required * @param {function} callback Callback function (can be anonymous function) * @param {number} ms Milliseconds * @param {object} user_data User data, passed to callback parameter * @returns Timer handle */ dxui.setInterval = function (id, callback, ms, user_data) { if (utils.validateId(dxui.all, id)) if (!callback || (typeof callback != 'function') || !callback.name || callback.name === '') { throw new Error('The callback should not be null and should be named function') } if (!ms || (typeof ms != 'number')) { throw new Error('The interval should not be empty, and should be number') } if (!this.all.__interval) { this.all.__interval = {} } this.all.__interval[id] = utils.GG.NativeTimer.lvTimerCreate(callback, ms, user_data) } /** * When the timer is no longer needed, you can delete this timer * @param {string} id Timer id */ dxui.clearInterval = function (id) { if (!dxui.all[id]) { return } utils.GG.NativeTimer.lvTimerDel(dxui.all[id]) delete dxui.all.__interval[id] } /** * Get the parent object of a UI object * @param {Object} ui */ dxui.getParent = function (ui) { if (ui.parent) { return dxui.getUi(ui.parent) } return null } /** * Delete the current UI object itself */ dxui.del = function (ui) { function recursiveDelete(ui) { // If the object doesn't exist, return directly if (!dxui.all[ui.id]) { return; } // First recursively delete all child objects if (ui.children && Array.isArray(ui.children)) { // Traverse child nodes in reverse order for (let i = ui.children.length - 1; i >= 0; i--) { const childId = ui.children[i]; if (dxui.all[childId]) { recursiveDelete(dxui.all[childId]); } } } // Remove current object from parent object if (ui.parent && dxui.all[ui.parent] && Array.isArray(dxui.all[ui.parent].children)) { const children = dxui.all[ui.parent].children let index = children.indexOf(ui.id); if (index !== -1) { children.splice(index, 1); } } // Delete current object ui.obj.lvObjDel(); delete dxui.all[ui.id]; } // Start recursive deletion recursiveDelete(ui); } /** * Load (switch) an already built UI object on the main layer * @param {object} ui UI object built using the build function */ dxui.loadMain = function (ui) { if (!ui || !ui.obj) { throw new Error("dxui.loadMain:'ui' paramter should not be null") } // Load main screen utils.GG.NativeDisp.lvScrLoad(ui.obj) } /** * Time elapsed since the last user activity (such as click) * @returns Returns the elapsed time since the last activity (milliseconds) */ dxui.getIdleDuration = function () { return utils.GG.NativeDisp.lvDispGetInactiveTime() } /** * Reset the elapsed time of user activity (such as click) */ dxui.trigActivity = function () { utils.GG.NativeDisp.lvDispTrigActivity() } export default dxui;