显示数值控件
LaGUI 的所有数值控件均需要数据源才能显示。因此我们需要为您应用程序的业务数据注册数据的访问方式,这个“访问方式”在 LaGUI 中定义成一条条的属性。
通过您定义的属性,LaGUI 还自动管理数据的撤销和重做,也包括资源文件的读写。交由 LaGUI 撤销系统、修改记录系统和共享资源系统来管理的数据必须使用 LaGUI 的内存调用来分配。在接下来的例子中,我们只需要用到界面显示,因此涉及不到这些复杂用法。
最简单的属性定义例子
例如我们有这样一个全局的 C 定义:
typedef struct My{
int _pad;
laSafeString* Name;
int Age;
int Gender;
real Height;
} My;
My Stats;
在 LaGUI 中,C Struct 相当于 laPropContainer 。我们首先创建一个适用于 My 类型的 laPropContainer :
laPropContainer* my=laAddPropertyContainer("my", "My", "Struct My",0,0,0,0,0,LA_PROP_OTHER_ALLOC);
由于所有 My 实例(在这里只有一个 My Stats;)的内存都不由 LaGUI 分配,因此在最后一个参数必须设置 LA_PROP_OTHER_ALLOC 以告知 LaGUI ,同时由于在这个例子中我们不需要 LaGUI 创建或者删除 My 实例,也不需要赋值 NodeSize 参数。
接下来我们就可以向 my 这个 laPropContainer 中添加各个属性,使用对应的 laAddxxxxProperty() 函数。这个例子足够简单,我们不需要 get/set 回调,因此只需提供成员相对于 My 的首地址偏移量。
laAddStringProperty(my, "name", "Name", "My name",0,0,0,0,1,offsetof(My,Name),0,0,0,0,0);
laAddIntProperty(my, "age", "Age", "My age",0,0,"years old",100,0,1,25,0,offsetof(My,Age),0,0,0,0,0,0,0,0,0,0,0);
laAddFloatProperty(my, "height", "Height", "My height",0,0,"cm",2,0.3,0.01,1.76,0,offsetof(My,Height),0,0,0,0,0,0,0,0,0,0,0);
laProp* ep=laAddEnumProperty(my, "gender","Gender","My gender",0,0,0,0,0,offsetof(My,Gender),0,0,0,0,0,0,0,0,0,0);
laAddEnumItemAs(ep,"MALE","Male","Gender being male",0,L'♂');
laAddEnumItemAs(ep,"FEMALE","female","Gender being female",1,L'♀');
注意到 laSafeString* Name; 不是 char[] ,LaGUI 提供了 laSafeString 的便利功能,只需在注册属性时将 IsSafeString 参数置为非0。
此外,我们要告诉 LaGUI 我们业务数据的根,这样 LaGUI 才能找到第一个 my 的实例(在这个例子中只有一个)。
laPropContainer* root=laDefineRoot();
laAddSubGroup(root,"me","Me","Me root", "my", 0,0,0,0,myget_Stats,0,0,0,0,0,0,0);
属性到这里就注册完成了,现在可以在界面上显示刚才注册的这些属性:
void MyProperties(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
laColumn* c=laFirstColumn(uil);
laShowLabel(uil,c,"Hello world!",0,0);
laShowItem(uil,c,0,"me.name");
laShowItem(uil,c,0,"me.age");
laShowItem(uil,c,0,"me.height");
laShowItem(uil,c,0,"me.gender");
}
属性注册与面板注册的先后顺序无所谓。之后,对 My Stats; 的值初始化之后,就能够运行程序了。你可以通过控件修改这些属性的值,如果通过“🞆”菜单调出一个新的“Properties”面板,你可以观察到两个面板上的属性同步刷新。
属性简易示例程序的代码应该类似于这样:
#include "la_5.h"
extern LA MAIN;
typedef struct My{
int _pad;
laSafeString* Name;
int Age;
int Gender;
real Height;
} My;
My Stats;
void* myget_Stats(void* unused, void* unused1){
return &Stats;
}
void MyProperties(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
laColumn* c=laFirstColumn(uil);
laShowLabel(uil,c,"Hello world!",0,0);
laShowItem(uil,c,0,"me.name");
laShowItem(uil,c,0,"me.age");
laShowItem(uil,c,0,"me.height");
laShowItem(uil,c,0,"me.gender");
}
int main(int argc, char *argv[]){
laGetReady();
Stats.Age=25;
Stats.Gender=0;
Stats.Height=1.76;
strSafeSet(&Stats.Name,"ChengduLittleA");
laPropContainer* root=laDefineRoot();
laAddSubGroup(root,"me","Me","Me root", "my", 0,0,0,0,myget_Stats,0,0,0,0,0,0,0);
laPropContainer* my=laAddPropertyContainer("my", "My", "Struct My",0,0,0,0,0,LA_PROP_OTHER_ALLOC);
laAddStringProperty(my, "name", "Name", "My name",0,0,0,0,1,offsetof(My,Name),0,0,0,0,0);
laAddIntProperty(my, "age", "Age", "My age",0,0,"years old",100,0,1,25,0,offsetof(My,Age),0,0,0,0,0,0,0,0,0,0,0);
laAddFloatProperty(my, "height", "Height", "My height",0,0,"cm",2,0.3,0.01,1.76,0,offsetof(My,Height),0,0,0,0,0,0,0,0,0,0,0);
laProp* ep=laAddEnumProperty(my, "gender","Gender","My gender",0,0,0,0,0,offsetof(My,Gender),0,0,0,0,0,0,0,0,0,0);
laAddEnumItemAs(ep,"MALE","Male","Gender being male",0,L'♂');
laAddEnumItemAs(ep,"FEMALE","female","Gender being female",1,L'♀');
laRegisterUiTemplate("my_properties","Properties", MyProperties,0,0,"Demonstration", 0,0,0);
// Uncomment this to load preferences.
// laEnsureUserPreferences();
if(!MAIN.Windows.pFirst){
laWindow* w = laDesignWindow(-1,-1,600,600);
laLayout* l = laDesignLayout(w,"My Layout");
laCreatePanel(l->FirstBlock,"my_properties");
laStartWindow(w);
}
laMainLoop();
}
属性定义参考
LaGUI 支持的属性类型如下表所示:
属性类型
对应 C 类型
LaGUI 控制的操作
LA_PROP_INT
32位整数
读、写、数组、显示
LA_PROP_FLOAT
64位浮点数
读、写、数组、显示
LA_PROP_ENUM
8/16/32位整数
读、写、数组、显示
LA_PROP_STRING
8位整数数组或 laSafeString*
读、写、显示
LA_PROP_SUB
64位地址或 laListHandle
写指针、读指针和偏移、读写列表、显示列表和成员
LA_PROP_RAW
64位地址
(仅通过回调在文件读写时访问)
LA_PROP_OPERATOR
-
通过 This 的工具调用1
1: 目前属性路径必须仅包含工具属性标识符,否则不工作。
LA_PROP_SUB 属性可递归包含,因此可以以树状方式描述整个应用程序的数据结构。下面这个对照示意解释了一种简易文件树结构的可能注册方式。建议通过各个 LaGUI 示例程序以及“Our Paint”软件的源代码更详细地了解向 LaGUI 描述您业务数据结构的方法。
数据结构 | 属性注册样式
|
struct Folder{ |
laListItem Item; | SUB "folder"
char Name[128]; | STRING "name"
int Privileges; | INT "privileges"
laListHandle SubFolders; | SUB_PROP LIST "folders" of "folder"
laListHandle Files; | SUB_PROP LIST "files" of "file"
}; |
|
struct File{ |
laListItem Item; | SUB "file"
char Name[128]; | STRING "name"
int Size; | INT "size"
void* Data; | RAW "data"
}; |
|
struct FileBrowser{ | SUB "application"
int SomeOtherStuff; | SUB_PROP LIST "folders" of "folder"
laListHandle SubFolders; |
}; |
| SUB "(__LAGUI_ROOT__)"
| SUB_PROP "my_application" of "application"