1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
//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;