|
@@ -0,0 +1,346 @@
|
|
1
|
+#ifndef cmUi_h
|
|
2
|
+#define cmUi_h
|
|
3
|
+
|
|
4
|
+#ifdef __cplusplus
|
|
5
|
+extern "C" {
|
|
6
|
+#endif
|
|
7
|
+ /*
|
|
8
|
+ cmUI implements a platform independent UI control manager
|
|
9
|
+ for multiple simultaneous applications. In this context
|
|
10
|
+ an 'application' can be seen as a plug-in style program.
|
|
11
|
+
|
|
12
|
+ The goal of the manager is to support the easy construction
|
|
13
|
+ of panels of graphic user interface controls.
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+ Operation:
|
|
18
|
+
|
|
19
|
+ 1) A cmUi manager is allocated by the master program. See cmUiAlloc().
|
|
20
|
+
|
|
21
|
+ 2) The master program then assigns a 'driver' to implmenent
|
|
22
|
+ the commands issued by cmUi. All commands can be
|
|
23
|
+ described using the cmUiDriverArg_t record.
|
|
24
|
+
|
|
25
|
+ 3) The master program then registers client applications with
|
|
26
|
+ the cmUi manager by calling cmUiCreateApp().
|
|
27
|
+
|
|
28
|
+ 4) Prior to calling any of the client application functions
|
|
29
|
+ the master or client app. must call cmUiSetAppId(). This
|
|
30
|
+ function sets the current application id and thereby slightly
|
|
31
|
+ simplifies the client app interface by not requiring the
|
|
32
|
+ app id be passed with every client app. function call.
|
|
33
|
+
|
|
34
|
+ 5) Once the current app. id is set with cmUiSetAppId()
|
|
35
|
+ the client app can make multiple calls to the cmUi manager
|
|
36
|
+ to create or query controls.
|
|
37
|
+
|
|
38
|
+ 6) Calls to create controls result in callbacks to the
|
|
39
|
+ driver function which manages the actual windowing and
|
|
40
|
+ initial event handling.
|
|
41
|
+
|
|
42
|
+ 7) Events generated by the driver based graphic controls
|
|
43
|
+ are routed back to the cmUi manager through calls to
|
|
44
|
+ cmUiOnDriverEvent().
|
|
45
|
+
|
|
46
|
+ 8) The cmUiOnDriverEvent() internally caches the
|
|
47
|
+ state/value of the control based on the event information
|
|
48
|
+ and calls the 'cbFunc' function registered with the
|
|
49
|
+ cmUi manager by cmUiAlloc(). This call is intended to
|
|
50
|
+ notify the client applications of changes in the state/value
|
|
51
|
+ of a user interface control.
|
|
52
|
+
|
|
53
|
+ Notes:
|
|
54
|
+ 1) Application id's must be unique among all applications.
|
|
55
|
+ Control id's must be unique among all controls assigned
|
|
56
|
+ to the same application. Both application and control id's
|
|
57
|
+ are used internally as array indexes they should therefore
|
|
58
|
+ be the low, positive, and densely packed integers.
|
|
59
|
+
|
|
60
|
+ 2) All communication between the cmUi and the driver,
|
|
61
|
+ and all callbacks from the cmUi to the master app.
|
|
62
|
+ use the cmUiDriverArg_t structure
|
|
63
|
+
|
|
64
|
+ TODO:
|
|
65
|
+ 0) Remove the 'cbArg' from the cmUiDriverArg_t record and
|
|
66
|
+ pass it as a separate paramenter in the cmUiDriverFunc_t calls.
|
|
67
|
+
|
|
68
|
+ 1) The controls should be based on a multilevel tree model
|
|
69
|
+ not the simple two layer panel->controls framework used now.
|
|
70
|
+
|
|
71
|
+ 2) Given that access to the control values can be non-blocked
|
|
72
|
+ and fast many controls won't need to report changes back to
|
|
73
|
+ the client - the client can simply read the control value
|
|
74
|
+ as necessary directly from the cmUi manager. To decrease
|
|
75
|
+ event processing overhead controls should therefore be
|
|
76
|
+ flagged as 'callback/no-callback'. Some controls like
|
|
77
|
+ buttons should default to turning the flag on, while other
|
|
78
|
+ controls, like numbers, should default to turning it off.
|
|
79
|
+
|
|
80
|
+ 3) Implement support for the creation of arrays of controls.
|
|
81
|
+ This can be implemented with a scheme similar to 'next rect'.
|
|
82
|
+ cmUiSetupArray(uiH,panelId,baseCtlId,cnt).
|
|
83
|
+
|
|
84
|
+ 4) Come up with a threading model. For example maybe
|
|
85
|
+ control creation should use a blocking scheme since it is
|
|
86
|
+ generally to time consuming to do during real-time operation
|
|
87
|
+ anyway. If the control flow generated from driver event
|
|
88
|
+ callbacks then allows value, but not structural changes,
|
|
89
|
+ then non blocking will be necessary.
|
|
90
|
+
|
|
91
|
+ 5) The cmUiDriverArg_t structure is used for both
|
|
92
|
+ commands to the driver and callbacks from the driver.
|
|
93
|
+ Many of the fields are not use for event callbacks.
|
|
94
|
+ Which fields are used under which circumstances should
|
|
95
|
+ be documented. This would allow decreasing the size
|
|
96
|
+ of the record during serialization.7
|
|
97
|
+
|
|
98
|
+ 6) Write a serialization/deserialization routines for cmUiDriverArg_t.
|
|
99
|
+ unsigned cmUiDriverArgSerialBufByteCount(const cmUiDriverArg_t* a);
|
|
100
|
+ cmUiRC_t cmUiDriverArgSerialize( const cmUiDriverArg_t* a, char* buf, bufByteCnt );
|
|
101
|
+ cmUiRC_t cmUiDriverArgDeserialize( cmUiDriverArg_t* a, const char* buf, bufByteCnt );
|
|
102
|
+
|
|
103
|
+ 7) There is no duplex model for validating and then displaying the
|
|
104
|
+ value of a control.
|
|
105
|
+
|
|
106
|
+ */
|
|
107
|
+
|
|
108
|
+ typedef cmHandle_t cmUiH_t;
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+ extern cmUiH_t cmUiNullHandle;
|
|
112
|
+
|
|
113
|
+ //=============================================================================================
|
|
114
|
+ //
|
|
115
|
+ // Master program API
|
|
116
|
+ //
|
|
117
|
+
|
|
118
|
+ // Allocate the cmUi manager. If the driver function is not
|
|
119
|
+ // yet available then set drvrFunc to NULL and use
|
|
120
|
+ // cmUiSetDriver() to set the driver function at a later
|
|
121
|
+ // time. cmUiAlloc() stores but does not call the driver
|
|
122
|
+ // and so it is not needed when the cmUI manager is
|
|
123
|
+ // constructed - however it must be set prior to making
|
|
124
|
+ // any other calls to the manager.
|
|
125
|
+ cmUiRC_t cmUiAlloc(
|
|
126
|
+ cmCtx_t* ctx,
|
|
127
|
+ cmUiH_t* hp,
|
|
128
|
+ cmUiDriverFunc_t drvrFunc, // UI driver function
|
|
129
|
+ void* drvrArg,
|
|
130
|
+ cmUiDriverFunc_t cbFunc, // client event callback function
|
|
131
|
+ void* cbArg );
|
|
132
|
+
|
|
133
|
+ // Release all apps but assume that the driver has already
|
|
134
|
+ // been released.
|
|
135
|
+ cmUiRC_t cmUiFree( cmUiH_t* hp );
|
|
136
|
+
|
|
137
|
+ // Validate the cmUiH_t handle.
|
|
138
|
+ bool cmUiIsValid( cmUiH_t h );
|
|
139
|
+
|
|
140
|
+ // Set the driver function. This function allows the driver
|
|
141
|
+ // set in cmUiAlloc() to be replaced or set following the
|
|
142
|
+ // call to cmUiAlloc().
|
|
143
|
+ //
|
|
144
|
+ // By setting the driver function to
|
|
145
|
+ // NULL the application can prevent callback to the driver.
|
|
146
|
+ // This is useful if the driver has been release prior
|
|
147
|
+ // to the UI manager begining destroyed.
|
|
148
|
+ void cmUiSetDriver( cmUiH_t h, cmUiDriverFunc_t drvrFunc, void* drvrArg );
|
|
149
|
+
|
|
150
|
+ // Register a client application with the cmUi manager.
|
|
151
|
+ // 'appId' must not have been used by any other previously registered.
|
|
152
|
+ // application.
|
|
153
|
+ // Automatically sets and restores the ambient appId.
|
|
154
|
+ // In a plug-in context this function is generally called
|
|
155
|
+ // just prior a instantiating a plug-in object.
|
|
156
|
+ cmUiRC_t cmUiCreateApp( cmUiH_t uiH, unsigned appId );
|
|
157
|
+
|
|
158
|
+ // Notify the cmUi manager that the resources associated
|
|
159
|
+ // with a client application can be released.
|
|
160
|
+ // Automatically sets and restores the ambient appId.
|
|
161
|
+ cmUiRC_t cmUiDestroyApp( cmUiH_t uiH, unsigned appId );
|
|
162
|
+
|
|
163
|
+ // Release all apps.
|
|
164
|
+ // Automatically sets and restores the ambient appId.
|
|
165
|
+ cmUiRC_t cmUiDestroyAllApps( cmUiH_t h );
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+ // The master program sets the ambient 'appId' prior to passing control
|
|
169
|
+ // to a client which will make User API calls. By making the
|
|
170
|
+ // 'appId' an ambient parameter the User API calls are slightly
|
|
171
|
+ // simplified because they do not have to include it in each of the
|
|
172
|
+ // function calls.
|
|
173
|
+ cmUiRC_t cmUiSetAppId( cmUiH_t uiH, unsigned appId );
|
|
174
|
+
|
|
175
|
+ // Return the count of app's.
|
|
176
|
+ unsigned cmUiAppCount( cmUiH_t uiH );
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+ // Callbacks from the driver arrive via this function.
|
|
180
|
+ cmUiRC_t cmUiOnDriverEvent( cmUiH_t uiH, const cmUiDriverArg_t* p );
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+ //=============================================================================================
|
|
184
|
+ //
|
|
185
|
+ // Client Application API
|
|
186
|
+ //
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+ cmUiRC_t cmUiCreatePanel( cmUiH_t uiH, unsigned newPanelId, const cmChar_t* label );
|
|
190
|
+
|
|
191
|
+ cmUiRC_t cmUiCreateBtn( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags );
|
|
192
|
+ cmUiRC_t cmUiCreateCheck( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags, bool dflt );
|
|
193
|
+ cmUiRC_t cmUiCreateLabel( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags );
|
|
194
|
+ cmUiRC_t cmUiCreateText( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags, const cmChar_t* text );
|
|
195
|
+ cmUiRC_t cmUiCreateNumber( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags, double min, double max, double incr, double dflt );
|
|
196
|
+ cmUiRC_t cmUiCreateHSlider( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags, double min, double max, double incr, double dflt );
|
|
197
|
+ cmUiRC_t cmUiCreateVSlider( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags, double min, double max, double incr, double dflt );
|
|
198
|
+ cmUiRC_t cmUiCreateProgress( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags, int min, int max, int dflt );
|
|
199
|
+ cmUiRC_t cmUiCreateHMeter( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags, int min, int max, int dflt );
|
|
200
|
+ cmUiRC_t cmUiCreateVMeter( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags, int min, int max, int dflt );
|
|
201
|
+ cmUiRC_t cmUiCreateFileBtn( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags, const cmChar_t* dfltDir, const cmChar_t* patStr );
|
|
202
|
+ cmUiRC_t cmUiCreateDirBtn( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags, const cmChar_t* dfltDir );
|
|
203
|
+ cmUiRC_t cmUiCreateMenuBtn( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags );
|
|
204
|
+ cmUiRC_t cmUiCreateMenuBtnV( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* lavel, unsigned flags, const cmChar_t* label0, unsigned id0, va_list vl );
|
|
205
|
+ cmUiRC_t cmUiCreateMenuBtnA( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* lavel, unsigned flags, const cmChar_t* label0, unsigned id0, ... );
|
|
206
|
+ cmUiRC_t cmUiCreateMenuBtnJson( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* lavel, unsigned flags, const cmJsonNode_t* root, const cmChar_t* memberLabel );
|
|
207
|
+ cmUiRC_t cmUiCreateList( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags, unsigned visibleRowCnt );
|
|
208
|
+ cmUiRC_t cmUiCreateListV( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags, unsigned visibleRowCnt, const cmChar_t* label0, unsigned id0, va_list vl );
|
|
209
|
+ cmUiRC_t cmUiCreateListA( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags, unsigned visibleRowCnt, const cmChar_t* label0, unsigned id0, ... );
|
|
210
|
+ cmUiRC_t cmUiCreateListJson( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags, unsigned visibleRowCnt, const cmJsonNode_t* root, const cmChar_t* memberLabel );
|
|
211
|
+
|
|
212
|
+ // If 'id' identifies a 'list' control use tabs as column separators.
|
|
213
|
+ cmUiRC_t cmUiAppendListEle( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* text, unsigned eleId );
|
|
214
|
+
|
|
215
|
+ // If 'id' identifies a panel then all control belonging to the panel
|
|
216
|
+ // will also be destroyed.
|
|
217
|
+ cmUiRC_t cmUiDestroyCtl( cmUiH_t uiH, unsigned id );
|
|
218
|
+
|
|
219
|
+ // Returns true if the control exists.
|
|
220
|
+ // For panels set id=panelId.
|
|
221
|
+ bool cmUiCtlExists( cmUiH_t uiH, unsigned panelId, unsigned id );
|
|
222
|
+
|
|
223
|
+ // Destroy all the controls in a panel.
|
|
224
|
+ cmUiRC_t cmUiClearPanel( cmUiH_t uiH, unsigned panelId );
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+ // Location:
|
|
228
|
+ // 1) If a 'next rect' is set the control will be placed according to it.
|
|
229
|
+ // 2) If cmUiSetBaseCol() was set then the control will be placed at the
|
|
230
|
+ // base col and base row.
|
|
231
|
+ // 3) If cmUiPlaceRight() or cmUIPlaceBelow() have been called since the
|
|
232
|
+ // previous control was created then the new control will be placed
|
|
233
|
+ // accordingly.
|
|
234
|
+ // 4) The control will be placed according to the 'fill rows' flag.
|
|
235
|
+ // If not set (default) the new control will be placed in the
|
|
236
|
+ // base column below the previous control.
|
|
237
|
+ // If 'fill rows' is set the new control will be placed on the
|
|
238
|
+ // same row to the right of the previous control.
|
|
239
|
+ // If there is no previous control then it will be placed
|
|
240
|
+ // in the base column and base row.
|
|
241
|
+
|
|
242
|
+ // Get/Set the fill directions. If the 'fill columns' flag is enabled
|
|
243
|
+ // then the next control is placed below the previous control otherwise
|
|
244
|
+ // the next control is placed to the right of the next control.
|
|
245
|
+ bool cmUiFillRows( cmUiH_t uiH, unsigned panelId );
|
|
246
|
+ bool cmUiSetFillRows( cmUiH_t uiH, unsigned panelId, bool enableFl );
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+ // Place the next control to the right/below of the previous ctl.
|
|
250
|
+ // These flags override the current fill row/col setting.
|
|
251
|
+ // Note that 'place right' and 'place below' are mutually
|
|
252
|
+ // exclusive. Enabling one disables the other.
|
|
253
|
+ void cmUiPlaceRight( cmUiH_t uiH, unsigned panelId );
|
|
254
|
+ void cmUiPlaceBelow( cmUiH_t uiH, unsigned panelId );
|
|
255
|
+
|
|
256
|
+ // Set current base col and return previous value. Place the next
|
|
257
|
+ // control on the base row.
|
|
258
|
+ int cmUiBaseCol( cmUiH_t uiH, unsigned panelId, int x );
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+ // Set current base row and return previous value.
|
|
262
|
+ int cmUiBaseRow( cmUiH_t uiH, unsigned panelId, int y );
|
|
263
|
+
|
|
264
|
+ // Size:
|
|
265
|
+ // 1) If a 'next rect' is set the control will be placed according
|
|
266
|
+ // to it.
|
|
267
|
+ // 2) If a 'next w/h' is set the control will be placed according
|
|
268
|
+ // to it. The 'next w/h' setting is only active for the
|
|
269
|
+ // next control created.
|
|
270
|
+ // 3) The w/h of the new control will be set to the default w/h.
|
|
271
|
+ //
|
|
272
|
+
|
|
273
|
+ // Get/Set the default control width and height.
|
|
274
|
+ // Set returns previous value.
|
|
275
|
+ int cmUiW( cmUiH_t uiH, unsigned panelId );
|
|
276
|
+ int cmUiH( cmUiH_t uiH, unsigned panelId );
|
|
277
|
+ void cmUiSetWH( cmUiH_t uiH, unsigned panelId, int w, int h );
|
|
278
|
+
|
|
279
|
+ // Get/Set the control width and height for only the next control.
|
|
280
|
+ // Set returns previous value.
|
|
281
|
+ int cmUiNextW( cmUiH_t uiH, unsigned panelId );
|
|
282
|
+ int cmUiNextH( cmUiH_t uiH, unsigned panelId );
|
|
283
|
+ void cmUiSetNextWH( cmUiH_t uiH, unsigned panelId, int w, int h );
|
|
284
|
+
|
|
285
|
+ // Get/Set the default inter-control borders
|
|
286
|
+ // Set returns previous value.
|
|
287
|
+ int cmUiHBorder( cmUiH_t uiH, unsigned panelId );
|
|
288
|
+ int cmUiVBorder( cmUiH_t uiH, unsigned panelId );
|
|
289
|
+ int cmUiSetHBorder( cmUiH_t uiH, unsigned panelId, int w );
|
|
290
|
+ int cmUiSetVBorder( cmUiH_t uiH, unsigned panelId, int h );
|
|
291
|
+
|
|
292
|
+ // Get/Set the 'next' inter-control borders
|
|
293
|
+ // Set returns previous value.
|
|
294
|
+ int cmUiNextHBorder( cmUiH_t uiH, unsigned panelId );
|
|
295
|
+ int cmUiNextVBorder( cmUiH_t uiH, unsigned panelId );
|
|
296
|
+ int cmUiSetNextHBorder( cmUiH_t uiH, unsigned panelId, int w );
|
|
297
|
+ int cmUiSetNextVBorder( cmUiH_t uiH, unsigned panelId, int h );
|
|
298
|
+
|
|
299
|
+ // Place the next control at the following coordinates. The
|
|
300
|
+ // specified coordinates are only active during the next
|
|
301
|
+ // cmUiCreateXXX() call. Setting the 'next rect' overrides all
|
|
302
|
+ // other layout directives.
|
|
303
|
+ cmUiRC_t cmUiNextRect( cmUiH_t uiH, unsigned panelId, int x, int y, int w, int h );
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+ //
|
|
307
|
+ // Get/set the value of UI control.
|
|
308
|
+ //
|
|
309
|
+
|
|
310
|
+ // TODO:
|
|
311
|
+ // 1) Still need functions for setting auxilliary values like
|
|
312
|
+ // min,max,etc..
|
|
313
|
+ // 2) A coherent model needs to be selected for determining
|
|
314
|
+ // how local values get set. As it is local values are
|
|
315
|
+ // only set via callbacs from the UI driver.
|
|
316
|
+
|
|
317
|
+ // Set the value associated with a control.
|
|
318
|
+ // These functions would be better named 'cmUiSendXXX()' since
|
|
319
|
+ // they don't actually set the local value but rather call the
|
|
320
|
+ // driver to set the UI value. The driver may then respond with
|
|
321
|
+ // a callback which will set the local value. One advantage of
|
|
322
|
+ // this is that the value will be filtered according to the
|
|
323
|
+ // ui's rules (e.g. min, max .... )
|
|
324
|
+ cmUiRC_t cmUiSetInt( cmUiH_t uiH, unsigned id, int v );
|
|
325
|
+ cmUiRC_t cmUiSetUInt( cmUiH_t uiH, unsigned id, unsigned v );
|
|
326
|
+ cmUiRC_t cmUiSetDouble( cmUiH_t uiH, unsigned id, double v );
|
|
327
|
+ cmUiRC_t cmUiSetString( cmUiH_t uiH, unsigned id, const cmChar_t* v );
|
|
328
|
+
|
|
329
|
+ // Get the value associated with a control. These functions return
|
|
330
|
+ // the control value cached in the local control, they do not need
|
|
331
|
+ // to call the driver and are therefore very fast.
|
|
332
|
+ int cmUiInt( cmUiH_t uiH, unsigned id );
|
|
333
|
+ unsigned cmUiUInt( cmUiH_t uiH, unsigned id );
|
|
334
|
+ double cmUiDouble( cmUiH_t uiH, unsigned id );
|
|
335
|
+ const cmChar_t* cmUiString( cmUiH_t uiH, unsigned id );
|
|
336
|
+
|
|
337
|
+ // Query/set the current error state.
|
|
338
|
+ cmUiRC_t cmUiLastRC( cmUiH_t uiH );
|
|
339
|
+ cmUiRC_t cmUiSetRC( cmUiH_t uiH, cmUiRC_t rc );
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+#ifdef __cplusplus
|
|
343
|
+}
|
|
344
|
+#endif
|
|
345
|
+
|
|
346
|
+#endif
|