*/}}

calculator.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. /*
  2. * Part of LaGUI demonstration programs
  3. * Copyright (C) 2022-2023 Wu Yiming
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include "la_5.h"
  19. extern LA MAIN;
  20. STRUCTURE(Calculator){
  21. laListHandle Item;
  22. laSafeString* Title;
  23. laSafeString* ResultString;
  24. laListHandle Racks;
  25. };
  26. STRUCTURE(CalculatorCollection){
  27. void* base;
  28. laListHandle Calculators;
  29. Calculator* CurrentCalculator;
  30. };
  31. STRUCTURE(CalcRack){
  32. laListItem Item;
  33. laListHandle Nodes;
  34. };
  35. STRUCTURE(CalcNode){
  36. laListItem Item;
  37. int Type;
  38. int Gap;
  39. laNodeOutSocket* OutA;
  40. };
  41. STRUCTURE(CalcOpNode){
  42. CalcNode Base;
  43. int Operation;
  44. laNodeInSocket* inA; real AVal;
  45. laNodeInSocket* inB; real BVal;
  46. };
  47. STRUCTURE(CalcMixNode){
  48. CalcOpNode Base;
  49. laNodeInSocket* inFactor; real Factor;
  50. };
  51. STRUCTURE(CalcNumberNode){
  52. CalcNode Base;
  53. int Mode; // Integer/Real
  54. int iValue;
  55. real rValue;
  56. };
  57. STRUCTURE(CalcResultNode){
  58. CalcNode Base;
  59. laNodeInSocket* inResult;
  60. };
  61. STRUCTURE(CalcRefNode){
  62. CalcNode Base;
  63. Calculator* Reference;
  64. laNodeInSocket* inResult;
  65. };
  66. #define CALC_NODE_GENERIC 0
  67. #define CALC_NODE_NUMBER 1
  68. #define CALC_NODE_ 2
  69. #define CALC_NODE_MIX 3
  70. #define CALC_NODE_RESULT 4
  71. #define CALC_NODE_REF 5
  72. #define CALC__ADD 0
  73. #define CALC__SUB 1
  74. #define CALC__MUL 2
  75. #define CALC__DIV 3
  76. CalculatorCollection* CC=0;
  77. laPropContainer* pcNumber,*pcOp,*pcMix,*pcResult,*pcGeneric,*pcRef;
  78. laTheme* LightTheme, *DarkTheme;
  79. void UiCalcNumberNode(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
  80. laColumn* c=laFirstColumn(uil); laUiItem* b=laBeginRow(uil,c,0,0);
  81. laShowHeightAdjuster(uil,c,This,"base.__gap",0);
  82. laShowItem(uil,c,This,"mode");
  83. laUiItem* b1=laOnConditionThat(uil,c,laEqual(laPropExpression(This,"mode"),laIntExpression(0)));{
  84. laShowItem(uil,c,This,"value_i");
  85. }laElse(uil,b1);{
  86. laShowItem(uil,c,This,"value_r");
  87. }laEndCondition(uil,b1);
  88. laShowSeparator(uil,c)->Expand=1;
  89. laShowNodeSocket(uil,c,This,"base.out_a",0);
  90. laShowLabel(uil,c,"🤙",0,0)->Flags|=LA_TEXT_ALIGN_RIGHT;
  91. laEndRow(uil,b);
  92. }
  93. void UiCalcOpNode(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
  94. laColumn* c=laFirstColumn(uil); laUiItem* b=laBeginRow(uil,c,0,0);
  95. laShowHeightAdjuster(uil,c,This,"base.__gap",0);
  96. laShowNodeSocket(uil,c,This,"in_a",0);
  97. laUiItem* b1=laOnConditionThat(uil,c,laNot(laPropExpression(This,"in_a.source")));{
  98. laShowItem(uil,c,This,"val_a");
  99. }laEndCondition(uil,b1);
  100. laShowNodeSocket(uil,c,This,"in_b",0);
  101. b1=laOnConditionThat(uil,c,laNot(laPropExpression(This,"in_b.source")));{
  102. laShowItem(uil,c,This,"val_b");
  103. }laEndCondition(uil,b1);
  104. laShowItem(uil,c,This,"operation");
  105. laShowSeparator(uil,c)->Expand=1;
  106. laShowNodeSocket(uil,c,This,"base.out_a",0);
  107. laShowLabel(uil,c,"🤔",0,0)->Flags|=LA_TEXT_ALIGN_RIGHT;
  108. laEndRow(uil,b);
  109. }
  110. void UiCalcMixNode(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
  111. laColumn* c=laFirstColumn(uil); laUiItem* b=laBeginRow(uil,c,0,0);
  112. laShowHeightAdjuster(uil,c,This,"base.base.__gap",0);
  113. laShowNodeSocket(uil,c,This,"base.in_a",0);
  114. laUiItem* b1=laOnConditionThat(uil,c,laNot(laPropExpression(This,"base.in_a.source")));{
  115. laShowItem(uil,c,This,"base.val_a");
  116. }laEndCondition(uil,b1);
  117. laShowNodeSocket(uil,c,This,"base.in_b",0);
  118. b1=laOnConditionThat(uil,c,laNot(laPropExpression(This,"base.in_b.source")));{
  119. laShowItem(uil,c,This,"base.val_b");
  120. }laEndCondition(uil,b1);
  121. laShowItem(uil,c,This,"in_factor");
  122. b1=laOnConditionThat(uil,c,laNot(laPropExpression(This,"in_factor.source")));{
  123. laShowItem(uil,c,This,"factor");
  124. }laEndCondition(uil,b1);
  125. laShowSeparator(uil,c)->Expand=1;
  126. laShowNodeSocket(uil,c,This,"base.base.out_a",0);
  127. laShowLabel(uil,c,"🤝",0,0)->Flags|=LA_TEXT_ALIGN_RIGHT;
  128. laEndRow(uil,b);
  129. }
  130. void UiCalcResultNode(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
  131. laColumn* c=laFirstColumn(uil); laUiItem* b=laBeginRow(uil,c,0,0);
  132. laShowHeightAdjuster(uil,c,This,"base.__gap",0);
  133. laShowNodeSocket(uil,c,This,"in_result",0);
  134. laShowSeparator(uil,c)->Expand=1;
  135. laShowLabel(uil,c,"😋",0,0)->Flags|=LA_TEXT_ALIGN_RIGHT;
  136. laEndRow(uil,b);
  137. }
  138. void UiCalcRefNode(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
  139. laColumn* c=laFirstColumn(uil); laUiItem* b=laBeginRow(uil,c,0,0);
  140. laShowHeightAdjuster(uil,c,This,"base.__gap",0);
  141. laShowNodeSocket(uil,c,This,"in_result",0);
  142. laShowSeparator(uil,c)->Expand=1;
  143. laShowLabel(uil,c,"😋",0,0)->Flags|=LA_TEXT_ALIGN_RIGHT;
  144. laEndRow(uil,b);
  145. laShowItemFull(uil,c,This,"ref",LA_WIDGET_COLLECTION_SELECTOR,0,laui_IdentifierOnly,0);
  146. }
  147. void UiRack(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
  148. laColumn* c=laFirstColumn(uil);
  149. laShowItem(uil,c,This,"nodes")->Flags|=LA_UI_FLAGS_NO_DECAL;
  150. laShowItem(uil,c,This,"add_node");
  151. }
  152. void UiCalculator(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
  153. laColumn* c=laFirstColumn(uil);
  154. laShowItem(uil,c,This,"title");
  155. laUiItem*b=laBeginRow(uil,c,0,0);
  156. laShowItemFull(uil,c,This,"add_rack",0,"position=head;",0,0)->Flags|=LA_UI_FLAGS_ICON;
  157. laUiItem* ui=laShowLabel(uil,c,"Racks",0,0); ui->Flags|=LA_TEXT_ALIGN_CENTER; ui->Expand=1;
  158. laShowItemFull(uil,c,This,"add_rack",0,0,0,0)->Flags|=LA_UI_FLAGS_ICON;
  159. laEndRow(uil,b);
  160. laUiItem* g=laMakeGroup(uil,c,"Racks",0);{ g->Flags|=LA_UI_FLAGS_NO_GAP|LA_UI_FLAGS_NO_DECAL|LA_UI_FLAGS_NODE_CONTAINER;
  161. laUiList* gu=g->Page; laColumn* gc=laFirstColumn(gu); gu->AllowScale=1; gu->HeightCoeff=-3; g->State=LA_UI_ACTIVE;
  162. laUiItem* hui=laShowItem(gu,gc,This,"racks"); hui->Expand=15; hui->Flags|=LA_UI_FLAGS_NO_GAP|LA_UI_FLAGS_NO_DECAL;
  163. }
  164. laShowItem(uil,c,This,"result");
  165. }
  166. void CalcPanel(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
  167. laColumn* c=laFirstColumn(uil); laColumn* cl,*cr; laSplitColumn(uil,c,0.5); cl=laLeftColumn(c,0); cr=laRightColumn(c,0);
  168. laShowLabel(uil,c,"You can use \"Data\" panel to see lagui-property structure.",0,0)->Flags|=LA_TEXT_LINE_WRAP;
  169. laShowItemFull(uil,cl,0,"calc.current",LA_WIDGET_COLLECTION_SELECTOR,0,laui_IdentifierOnly,0);
  170. laShowItem(uil,cr,0,"CALC_add_calculator");
  171. laShowItemFull(uil,c,0,"calc.current",LA_WIDGET_COLLECTION_SINGLE,0,0,0)->Flags|=LA_UI_COLLECTION_NO_HIGHLIGHT;
  172. }
  173. void CalcPanelRegular(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
  174. laColumn* c=laFirstColumn(uil);
  175. laShowItemFull(uil,c,0,"calc.current",0,0,laui_SubPropInfoDefault,1);
  176. }
  177. int INV_AddCalculator(laOperator* a, laEvent* e){
  178. Calculator* c=memAcquireHyper(sizeof(Calculator));
  179. strSafeSet(&c->Title, "New Calculator");
  180. lstAppendItem(&CC->Calculators,c);
  181. memAssignRef(CC,&CC->CurrentCalculator,c);
  182. laRecordAndPushProp(0, "calc"); laNotifyUsers("calc"); laPrintDBInstInfo();
  183. return LA_FINISHED;
  184. }
  185. int INV_AddRack(laOperator* a, laEvent* e){
  186. Calculator* c=a->This?a->This->EndInstance:CC->CurrentCalculator; if(!c) return LA_FINISHED;
  187. CalcRack* cr=memAcquire(sizeof(CalcRack));
  188. if(strSame(strGetArgumentString(a->ExtraInstructionsP,"position"),"head")){ lstPushItem(&c->Racks,cr); }
  189. else lstAppendItem(&c->Racks,cr);
  190. laRecordAndPushProp(0, "calc"); laNotifyUsers("calc"); laPrintDBInstInfo();
  191. return LA_FINISHED;
  192. }
  193. void AddNodesPanel(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
  194. laColumn* c=laFirstColumn(uil);
  195. laShowLabel(uil,c,"Select node type:",0,0);
  196. laShowItemFull(uil,c,0,"LA_confirm",0,"icon=🤙;text=Number;feedback=NUMBER;",0,0);
  197. laShowItemFull(uil,c,0,"LA_confirm",0,"icon=🤔;text=Calculate;feedback=CALC;",0,0);
  198. laShowItemFull(uil,c,0,"LA_confirm",0,"icon=🤝;text=Mix;feedback=MIX;",0,0);
  199. laShowItemFull(uil,c,0,"LA_confirm",0,"icon=😋;text=Result;feedback=RESULT;",0,0);
  200. laShowItemFull(uil,c,0,"LA_confirm",0,"icon=🡬;text=Reference;feedback=REF;",0,0);
  201. }
  202. int INV_AddNode_(laOperator* a, laEvent* e){
  203. CalcRack* cr=a->This?a->This->EndInstance:0; if(!cr) return LA_FINISHED;
  204. laEnableOperatorPanel(a, a->This, e->x,e->y,0,0,0,0,0,0,0,0,0,0,e);
  205. return LA_RUNNING;
  206. }
  207. int MOD_AddNode_(laOperator* a, laEvent* e){
  208. if(!a->This){ return LA_FINISHED; }
  209. CalcRack* cr=a->This->EndInstance;
  210. if(a->ConfirmData){
  211. char* str; CalcNode* n=0;
  212. if(strSame(a->ConfirmData->StrData, "NUMBER")){
  213. n=memAcquire(sizeof(CalcNumberNode)); CalcNumberNode* cn=n; n->Type=CALC_NODE_NUMBER;
  214. cn->Base.OutA=laCreateOutSocket(cn, "A", 0);
  215. }elif(strSame(a->ConfirmData->StrData, "CALC")){
  216. n=memAcquire(sizeof(CalcOpNode)); CalcOpNode* cn=n; n->Type=CALC_NODE_;
  217. cn->Base.OutA=laCreateOutSocket(cn, "Out", 0);
  218. cn->inA=laCreateInSocket("A", 0);
  219. cn->inB=laCreateInSocket("B", 0);
  220. }elif(strSame(a->ConfirmData->StrData, "MIX")){
  221. n=memAcquire(sizeof(CalcMixNode)); CalcMixNode*cn=n; n->Type=CALC_NODE_MIX;
  222. cn->Base.Base.OutA=laCreateOutSocket(cn, "Out", 0);
  223. cn->Base.inA=laCreateInSocket("A", 0);
  224. cn->Base.inB=laCreateInSocket("B", 0);
  225. cn->inFactor=laCreateInSocket("Factor", 0);
  226. }elif(strSame(a->ConfirmData->StrData, "RESULT")){
  227. n=memAcquire(sizeof(CalcResultNode)); CalcResultNode*cn=n; n->Type=CALC_NODE_RESULT;
  228. cn->Base.OutA=laCreateOutSocket(cn, "Out", 0);
  229. cn->inResult=laCreateInSocket("Result", 0);
  230. }elif(strSame(a->ConfirmData->StrData, "REF")){
  231. n=memAcquire(sizeof(CalcRefNode)); CalcRefNode*cn=n; n->Type=CALC_NODE_REF;
  232. cn->Base.OutA=laCreateOutSocket(cn, "Out", 0);
  233. cn->inResult=laCreateInSocket("Result", 0);
  234. }
  235. if(n){
  236. lstAppendItem(&cr->Nodes,n);
  237. laRecordAndPushProp(0, "calc"); laNotifyUsers("calc"); laPrintDBInstInfo();
  238. }
  239. return LA_FINISHED_PASS;
  240. }
  241. return LA_RUNNING;
  242. }
  243. laPropContainer* CalcGetNodeType(CalcNode* n){
  244. switch(n->Type){
  245. case CALC_NODE_NUMBER: return pcNumber;
  246. case CALC_NODE_: return pcOp;
  247. case CALC_NODE_MIX: return pcMix;
  248. case CALC_NODE_RESULT: return pcResult;
  249. case CALC_NODE_REF: return pcRef;
  250. default: case CALC_NODE_GENERIC: return pcGeneric;
  251. }
  252. }
  253. void* CalcGetCollection(void* unused,void* unused1){
  254. return CC;
  255. }
  256. void *CalcGetFirstCalculator(void* unusedcc, void* unused){
  257. return CC->Calculators.pFirst;
  258. }
  259. laBoxedTheme* CalcGetTheme(CalcRack* rack_unused, CalcNode* n){
  260. if(n->Type == CALC_NODE_MIX) return (MAIN.CurrentTheme==LightTheme?DarkTheme:LightTheme);
  261. return 0;
  262. }
  263. int CalcGetGap(CalcRack* rack_unused, CalcNode* n){
  264. return n->Gap;
  265. }
  266. void CalcSetGap(CalcNode* n, int gap){
  267. if(gap<0){
  268. int done=0;
  269. CalcNode* nn=n; while(nn){ if(nn->Gap>0){ nn->Gap--; done=1; break; } nn=nn->Item.pPrev; }
  270. if(done){ nn=n->Item.pNext; while(nn){ if(nn->Gap>0){ nn->Gap++; break; } nn=nn->Item.pNext; } }
  271. }
  272. if(gap>0){
  273. n->Gap+=gap;
  274. CalcNode* nn=n->Item.pNext; while(nn){ if(nn->Gap>0){ nn->Gap--; break; } nn=nn->Item.pNext; }
  275. }
  276. }
  277. int RegisterCalculator(){
  278. LightTheme=laGetTheme("Classic Light");
  279. DarkTheme=laGetTheme("Classic Dark");
  280. CC=memAcquire(sizeof(CalculatorCollection));
  281. laRegisterUiTemplate("panel_calc", "Calculator", CalcPanel, 0, 0,0, 0,0,0);
  282. laRegisterUiTemplate("panel_calc_regular", "Data", CalcPanelRegular, 0, 0,0, 0,0,0);
  283. laCreateOperatorType("CALC_add_calculator", "Add Calculator", "Add a calculator", 0,0,0,INV_AddCalculator,0,'+',0);
  284. laCreateOperatorType("CALC_add_rack", "Add Rack", "Add a rack into the calculator", 0,0,0,INV_AddRack,0,'+',0);
  285. laCreateOperatorType("CALC_add_node", "Add Node", "Add a fruit into the basket or bundle", 0,0,0,INV_AddNode_,MOD_AddNode_,'+',0)->UiDefine=AddNodesPanel;
  286. laPropContainer* pc=laDefineRoot();
  287. laAddSubGroup(pc, "calc", "Calculator Collections", "The collection of calculators", "calc_collection",0,0,0,-1,CalcGetCollection,0,0,0,0,0,0,LA_UDF_SINGLE|LA_UDF_LOCAL);
  288. laProp*p;
  289. pc=laAddPropertyContainer("calc_collection", "Calculator Collection", "Collection of calculators", 0, CalcPanel, sizeof(CalculatorCollection), 0, 0, 1|LA_UDF_LOCAL|LA_UDF_SINGLE);
  290. laAddSubGroup(pc, "calculators", "Calculators","Calculators","calculator",0,0,0,offsetof(CalculatorCollection, CurrentCalculator),0,0,0,0,0,0,offsetof(CalculatorCollection,Calculators),0);
  291. laAddSubGroup(pc, "current", "Current Calculator","Current calculator","calculator",0,0,0,offsetof(CalculatorCollection,CurrentCalculator),0,0,0,0,0,0,offsetof(CalculatorCollection,Calculators),LA_UDF_REFER);
  292. laAddOperatorProperty(pc,"add_calculator", "Add Calculator", "Add a calculator", "CALC_add_calculator", 0, 0);
  293. pc=laAddPropertyContainer("calculator", "Calculator", "A node-based calculator", 0, UiCalculator, sizeof(Calculator), 0, 0, 2);
  294. laAddStringProperty(pc,"title","Title","Name of the calculator",0,0,0,0,1,offsetof(Calculator,Title),0,0,0,0,LA_AS_IDENTIFIER);
  295. laAddStringProperty(pc,"result","Result","Result produced by the calculator",0,0,0,0,1,offsetof(Calculator,ResultString),0,0,0,0,0);
  296. laAddSubGroup(pc, "racks", "Racks","Node racks of this calculator","calc_rack",0,0,0,-1,0,0,0,0,0,0,offsetof(Calculator,Racks),0);
  297. laAddOperatorProperty(pc,"add_rack", "Add Rack", "Add a rack into the calculator", "CALC_add_rack", 0, 0);
  298. pc=laAddPropertyContainer("calc_rack", "Rack", "A node rack", 0, UiRack, sizeof(CalcRack), 0, 0, 1);
  299. p= laAddSubGroup(pc, "nodes", "Nodes","Nodes on this rack","calc_node",CalcGetNodeType,0,0,-1,0,0,0,0,0,0,offsetof(CalcRack,Nodes),0);
  300. laSubGroupExtraFunctions(p,0,CalcGetTheme,CalcGetGap,0);
  301. laAddOperatorProperty(pc,"add_node", "Add Node", "Add a node", "CALC_add_node", 0, 0);
  302. pcGeneric=pc=laAddPropertyContainer("calc_node", "Node", "A calculator node", 0, 0, sizeof(CalcNode), 0, 0, 1);
  303. laAddIntProperty(pc,"__gap", "Gap", "Gap of the node", 0,0,0,0,0,0,0,0,offsetof(CalcNode,Gap),0,CalcSetGap,0,0,0,0,0,0,0,0,0);
  304. p=laAddEnumProperty(pc,"type","Type","Type",0,0,0,0,0,offsetof(CalcNode,Type),0,0,0,0,0,0,0,0,0,LA_AS_IDENTIFIER|LA_READ_ONLY);
  305. laAddEnumItemAs(p,"GENERIC","Generic","Generic", CALC_NODE_GENERIC, 0);
  306. laAddEnumItemAs(p,"NUMBER","Number","Number", CALC_NODE_NUMBER, 0);
  307. laAddEnumItemAs(p,"","Op","Op", CALC_NODE_, 0);
  308. laAddEnumItemAs(p,"MIX","Mix","Mix", CALC_NODE_MIX, 0);
  309. laAddEnumItemAs(p,"RESULT","Result","Result", CALC_NODE_RESULT, 0);
  310. laAddEnumItemAs(p,"REF","Reference","Reference", CALC_NODE_REF, 0);
  311. laAddSubGroup(pc, "out_a", "Out A","Out A","la_out_socket",0,0,0,offsetof(CalcNode,OutA),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  312. pcNumber=pc=laAddPropertyContainer("calc_number_node", "Number Node", "A node that outputs a constant number", 0, UiCalcNumberNode, sizeof(CalcNumberNode), 0, 0, 1);
  313. laAddSubGroup(pc, "base", "Base","Base","calc_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
  314. laAddIntProperty(pc,"value_i", "Int Value", "Integer value", 0,0,0,0,0,0,0,0,offsetof(CalcNumberNode,iValue),0,0,0,0,0,0,0,0,0,0,0);
  315. laAddFloatProperty(pc,"value_r", "Real Value", "Real value", 0,0,0,0,0,0,0,0,offsetof(CalcNumberNode,rValue),0,0,0,0,0,0,0,0,0,0,0);
  316. p=laAddEnumProperty(pc,"mode","Mode","Number mode",0,0,0,0,0,offsetof(CalcNumberNode,Mode),0,0,0,0,0,0,0,0,0,0);
  317. laAddEnumItemAs(p,"INT","Integer","Integer", 0, 0);
  318. laAddEnumItemAs(p,"REAL","Real","Real", 1, 0);
  319. pcOp=pc=laAddPropertyContainer("calc_op_node", "Op Node", "A node that does an operation between two values", 0, UiCalcOpNode, sizeof(CalcOpNode), 0, 0, 1);
  320. laAddSubGroup(pc, "base", "Base","Base","calc_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
  321. p=laAddEnumProperty(pc,"operation","Operation","Operation on two values",0,0,0,0,0,offsetof(CalcOpNode,Operation),0,0,0,0,0,0,0,0,0,0);
  322. laAddEnumItemAs(p,"ADD","Add","A + B", CALC__ADD,0);
  323. laAddEnumItemAs(p,"SUB","Subtract","A - B", CALC__SUB,0);
  324. laAddEnumItemAs(p,"MUL","Multiply","A * B", CALC__MUL,0);
  325. laAddEnumItemAs(p,"DIV","Divide","A / B", CALC__DIV,0);
  326. laAddSubGroup(pc, "in_a", "A","Input value A","la_in_socket",0,0,0,offsetof(CalcOpNode,inA),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  327. laAddSubGroup(pc, "in_b", "B","Input value B","la_in_socket",0,0,0,offsetof(CalcOpNode,inB),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  328. laAddFloatProperty(pc,"val_a", "A", "Internal value A", 0,0,0,0,0,0,0,0,offsetof(CalcOpNode,AVal),0,0,0,0,0,0,0,0,0,0,0);
  329. laAddFloatProperty(pc,"val_b", "B", "Internal value B", 0,0,0,0,0,0,0,0,offsetof(CalcOpNode,BVal),0,0,0,0,0,0,0,0,0,0,0);
  330. pcMix=pc=laAddPropertyContainer("calc_mix_node", "Mix Node", "A node that mixes two values", 0, UiCalcMixNode, sizeof(CalcMixNode), 0, 0, 1);
  331. laAddSubGroup(pc, "base", "Base","Base","calc_op_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
  332. laAddSubGroup(pc, "in_factor", "Factor","Input factor","la_in_socket",0,0,0,offsetof(CalcMixNode,inFactor),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  333. laAddFloatProperty(pc,"factor", "Factor", "Internal factor", 0,0,0,0,0,0,0,0,offsetof(CalcMixNode,Factor),0,0,0,0,0,0,0,0,0,0,0);
  334. pcResult=pc=laAddPropertyContainer("calc_result_node", "Result Node", "A node that records the result", 0, UiCalcResultNode, sizeof(CalcResultNode), 0, 0, 1);
  335. laAddSubGroup(pc, "base", "Base","Base","calc_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
  336. laAddSubGroup(pc, "in_result", "Result","Input result","la_in_socket",0,0,0,offsetof(CalcResultNode,inResult),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  337. pcRef=pc=laAddPropertyContainer("calc_ref_node", "Reference Node", "A node that references other calculators", 0, UiCalcRefNode, sizeof(CalcRefNode), 0, 0, 1);
  338. laAddSubGroup(pc, "base", "Base","Base","calc_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
  339. laAddSubGroup(pc, "ref", "Reference","Referenced calculator","calculator",0,0,0,offsetof(CalcRefNode,Reference),CalcGetFirstCalculator,0,laget_ListNext,0,0,0,0,LA_UDF_REFER);
  340. laAddSubGroup(pc, "in_result", "Result","Input result","la_in_socket",0,0,0,offsetof(CalcRefNode,inResult),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  341. laSaveProp("calc");
  342. }
  343. int main(int argc, char *argv[]){
  344. laGetReady();
  345. RegisterCalculator();
  346. laRefreshUDFRegistries();
  347. // Use this to save and load preference when exit and during start up
  348. // laEnsureUserPreferences();
  349. laAddRootDBInst("calc");
  350. laWindow* w = laDesignWindow(-1,-1,600,600);
  351. laLayout* l = laDesignLayout(w, "Settings Layout");
  352. laBlock* b = l->FirstBlock;
  353. laPanel* p=laCreatePanel(b, "LAUI_user_preferences");
  354. l = laDesignLayout(w, "Nodes list");
  355. b = l->FirstBlock;
  356. p=laCreatePanel(b, "panel_calc_help");
  357. p=laCreatePanel(b, "panel_calc_regular");
  358. p=laCreatePanel(b, "panel_calc");
  359. laStartWindow(w);
  360. laMainLoop();
  361. }