Gui Objects.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. namespace EE{
  4. /******************************************************************************/
  5. #define CC4_GOBJ CC4('G','O','B','J')
  6. /******************************************************************************/
  7. // MANAGE
  8. /******************************************************************************/
  9. GuiObjs& GuiObjs::del()
  10. {
  11. _objs .del();
  12. _names.del();
  13. REP(GO_NUM)if(Memb<GuiObj> *objs=T.objs(GUI_OBJ_TYPE(i)))objs->del();
  14. return T;
  15. }
  16. /******************************************************************************/
  17. struct GuiObjsObj : GuiObjs::Obj
  18. {
  19. C GuiObj *go;
  20. void set(Int index, C GuiObj &go, CChar *name, Memc<C Memx<GuiObj>*> &src, Memc<Str> &names)
  21. {
  22. // set object
  23. T.type=go.type(); T.index=index; T.go=&go;
  24. // set parent
  25. parent_type=GO_NONE; parent_index=parent_sub=-1;
  26. if(GuiObj *parent=go.parent())
  27. {
  28. // if objects parent is a Tab, then instead of storing it as child of Tab, we store it as child of Tabs, with index specified to given Tab (this is because there are no single Tab objects in the Gui, but they're always a member of Tabs)
  29. Tab *tab=null; if(parent->type()==GO_TAB){tab=&parent->asTab(); parent=tab->parent();} // use parent of Tab (which is Tabs)
  30. if(parent)if(C Memx<GuiObj> *parent_container=src[parent->type()])
  31. {
  32. parent_index=parent_container->validIndex(parent);
  33. if(parent_index>=0)
  34. {
  35. parent_type=parent->type();
  36. if(parent_type==GO_TABS)parent_sub=parent->asTabs()._tabs.validIndex(tab); // get index of Tab in Tabs
  37. }
  38. }
  39. }
  40. // set name
  41. name_offset=0;
  42. FREPA(names) // order is important
  43. {
  44. if(EqualPath(names[i], name))return; // this name is ok
  45. name_offset+=names[i].length()+1; // proceed to next name and null character
  46. }
  47. names.add(name); // name was not found, we need to add new one, 'name_offset' is already ok
  48. }
  49. };
  50. static Int Compare(C GuiObjsObj &a, C GuiObjsObj &b) // compare in order of creation
  51. {
  52. if(C GuiObj *ga=a.go)
  53. if(C GuiObj *gb=b.go)
  54. {
  55. // do quick checks first which don't require memory allocation
  56. if(ga==gb )return 0;
  57. if(ga->contains(gb))return -1; // if 'a' is parent of 'b', the 'a' must be stored first
  58. if(gb->contains(ga))return +1; // if 'b' is parent of 'a', the 'b' must be stored first
  59. // set history (add all parents starting from self to root)
  60. Memc<C GuiObj*> ah; for(C GuiObj *g=ga; g; g=g->parent())ah.add(g);
  61. Memc<C GuiObj*> bh; for(C GuiObj *g=gb; g; g=g->parent())bh.add(g);
  62. // go from root until different objects are found
  63. for(; ah.elms() && bh.elms(); )
  64. {
  65. C GuiObj *a=ah.pop();
  66. C GuiObj *b=bh.pop();
  67. if(a!=b)return a->compareLevel(*b); // return the order in which elements are stored
  68. }
  69. }
  70. return 0;
  71. }
  72. GuiObjs& GuiObjs::create( // create from objects
  73. C Memx< ObjName< Button > > &button ,
  74. C Memx< ObjName< CheckBox > > &checkbox,
  75. C Memx< ObjName< ComboBox > > &combobox,
  76. C Memx< ObjName< GuiCustom> > &custom ,
  77. C Memx< ObjName< Desktop > > &desktop ,
  78. C Memx< ObjName< GuiImage > > &image ,
  79. C Memx< ObjName<_List > > &list ,
  80. C Memx< ObjName< Menu > > &menu ,
  81. C Memx< ObjName< MenuBar > > &menubar ,
  82. C Memx< ObjName< Progress > > &progress,
  83. C Memx< ObjName< Region > > &region ,
  84. C Memx< ObjName< SlideBar > > &slidebar,
  85. C Memx< ObjName< Slider > > &slider ,
  86. C Memx< ObjName< Tabs > > &tabs ,
  87. C Memx< ObjName< Text > > &text ,
  88. C Memx< ObjName< TextBox > > &textbox ,
  89. C Memx< ObjName< TextLine > > &textline,
  90. C Memx< ObjName< Viewport > > &viewport,
  91. C Memx< ObjName< Window > > &window )
  92. {
  93. del();
  94. Memc<C Memx<GuiObj>*> src; src.setNumZero(GO_NUM);
  95. src[GO_BUTTON ]=&SCAST(C Memx<GuiObj>, button );
  96. src[GO_CHECKBOX]=&SCAST(C Memx<GuiObj>, checkbox);
  97. src[GO_COMBOBOX]=&SCAST(C Memx<GuiObj>, combobox);
  98. src[GO_CUSTOM ]=&SCAST(C Memx<GuiObj>, custom );
  99. src[GO_DESKTOP ]=&SCAST(C Memx<GuiObj>, desktop );
  100. src[GO_IMAGE ]=&SCAST(C Memx<GuiObj>, image );
  101. src[GO_LIST ]=&SCAST(C Memx<GuiObj>, list );
  102. src[GO_MENU ]=&SCAST(C Memx<GuiObj>, menu );
  103. src[GO_MENU_BAR]=&SCAST(C Memx<GuiObj>, menubar );
  104. src[GO_PROGRESS]=&SCAST(C Memx<GuiObj>, progress);
  105. src[GO_REGION ]=&SCAST(C Memx<GuiObj>, region );
  106. src[GO_SLIDEBAR]=&SCAST(C Memx<GuiObj>, slidebar);
  107. src[GO_SLIDER ]=&SCAST(C Memx<GuiObj>, slider );
  108. src[GO_TABS ]=&SCAST(C Memx<GuiObj>, tabs );
  109. src[GO_TEXT ]=&SCAST(C Memx<GuiObj>, text );
  110. src[GO_TEXTBOX ]=&SCAST(C Memx<GuiObj>, textbox );
  111. src[GO_TEXTLINE]=&SCAST(C Memx<GuiObj>, textline);
  112. src[GO_VIEWPORT]=&SCAST(C Memx<GuiObj>, viewport);
  113. src[GO_WINDOW ]=&SCAST(C Memx<GuiObj>, window );
  114. // create objects in dest containers (order is important, so it matches source indexes)
  115. FREPA(button )T._button .New().create(button [i]);
  116. FREPA(checkbox)T._checkbox.New().create(checkbox[i]);
  117. FREPA(combobox)T._combobox.New().create(combobox[i]);
  118. FREPA(menu )T._menu .New().create(menu [i]);
  119. FREPA(custom )T._custom .New().create(custom [i]);
  120. FREPA(desktop )T._desktop .New().create(desktop [i]);
  121. FREPA(image )T._image .New().create(image [i]);
  122. FREPA(list )T._list .New().create(list [i]);
  123. FREPA(menubar )T._menubar .New().create(menubar [i]);
  124. FREPA(progress)T._progress.New().create(progress[i]);
  125. FREPA(region )T._region .New().create(region [i]);
  126. FREPA(slidebar)T._slidebar.New().create(slidebar[i]);
  127. FREPA(slider )T._slider .New().create(slider [i]);
  128. FREPA(tabs )T._tabs .New().create(tabs [i]);
  129. FREPA(text )T._text .New().create(text [i]);
  130. FREPA(textbox )T._textbox .New().create(textbox [i]);
  131. FREPA(textline)T._textline.New().create(textline[i]);
  132. FREPA(viewport)T._viewport.New().create(viewport[i]);
  133. FREPA(window )T._window .New().create(window [i]);
  134. Memc<GuiObjsObj> goi ; // create an array of all gui object types (no specific order)
  135. Memc<Str > names;
  136. FREPA(button )goi.New().set(i, button [i], button [i].name, src, names);
  137. FREPA(checkbox)goi.New().set(i, checkbox[i], checkbox[i].name, src, names);
  138. FREPA(combobox)goi.New().set(i, combobox[i], combobox[i].name, src, names);
  139. FREPA(menu )goi.New().set(i, menu [i], menu [i].name, src, names);
  140. FREPA(custom )goi.New().set(i, custom [i], custom [i].name, src, names);
  141. FREPA(desktop )goi.New().set(i, desktop [i], desktop [i].name, src, names);
  142. FREPA(image )goi.New().set(i, image [i], image [i].name, src, names);
  143. FREPA(list )goi.New().set(i, list [i], list [i].name, src, names);
  144. FREPA(menubar )goi.New().set(i, menubar [i], menubar [i].name, src, names);
  145. FREPA(progress)goi.New().set(i, progress[i], progress[i].name, src, names);
  146. FREPA(region )goi.New().set(i, region [i], region [i].name, src, names);
  147. FREPA(slidebar)goi.New().set(i, slidebar[i], slidebar[i].name, src, names);
  148. FREPA(slider )goi.New().set(i, slider [i], slider [i].name, src, names);
  149. FREPA(tabs )goi.New().set(i, tabs [i], tabs [i].name, src, names);
  150. FREPA(text )goi.New().set(i, text [i], text [i].name, src, names);
  151. FREPA(textbox )goi.New().set(i, textbox [i], textbox [i].name, src, names);
  152. FREPA(textline)goi.New().set(i, textline[i], textline[i].name, src, names);
  153. FREPA(viewport)goi.New().set(i, viewport[i], viewport[i].name, src, names);
  154. FREPA(window )goi.New().set(i, window [i], window [i].name, src, names);
  155. Int name_length=0; REPA(names)name_length+=names[i].length()+1; T._names.setNum(name_length);
  156. name_length=0; FREPA(names){C Str &name=names[i]; FREPA(name)T._names[name_length++]=name[i]; T._names[name_length++]='\0';}
  157. T._objs=goi.sort(Compare); // sort by order of creation
  158. return T;
  159. }
  160. /******************************************************************************/
  161. static GuiObj* GetObj(Memc<Memx<GuiObj>*> &objs, Memc<Int> &offset, GUI_OBJ_TYPE type, Int index, Int sub=-1)
  162. {
  163. if(InRange(type, objs) && InRange(type, offset))if(Memx<GuiObj> *obj=objs[type])
  164. {
  165. index+=offset[type];
  166. if(InRange(index, *obj))
  167. {
  168. GuiObj &go=(*obj)[index];
  169. if(go.type()==GO_TABS && InRange(sub, go.asTabs()))return &go.asTabs().tab(sub);
  170. return &go;
  171. }
  172. }
  173. return null;
  174. }
  175. void GuiObjs::copyTo( // copy self to object containers
  176. Memx< ObjName< Button > > &button ,
  177. Memx< ObjName< CheckBox > > &checkbox,
  178. Memx< ObjName< ComboBox > > &combobox,
  179. Memx< ObjName< GuiCustom> > &custom ,
  180. Memx< ObjName< Desktop > > &desktop ,
  181. Memx< ObjName< GuiImage > > &image ,
  182. Memx< ObjName<_List > > &list ,
  183. Memx< ObjName< Menu > > &menu ,
  184. Memx< ObjName< MenuBar > > &menubar ,
  185. Memx< ObjName< Progress > > &progress,
  186. Memx< ObjName< Region > > &region ,
  187. Memx< ObjName< SlideBar > > &slidebar,
  188. Memx< ObjName< Slider > > &slider ,
  189. Memx< ObjName< Tabs > > &tabs ,
  190. Memx< ObjName< Text > > &text ,
  191. Memx< ObjName< TextBox > > &textbox ,
  192. Memx< ObjName< TextLine > > &textline,
  193. Memx< ObjName< Viewport > > &viewport,
  194. Memx< ObjName< Window > > &window ,
  195. GuiObj *parent )C
  196. {
  197. Memc<Memx<GuiObj>*> dest ; dest .setNumZero(GO_NUM);
  198. Memc<Int > offset; offset.setNumZero(GO_NUM); // offset needed to be applied to object index in the target container, depending on elements present there already (before creating new elements)
  199. dest[GO_BUTTON ]=&SCAST(Memx<GuiObj>, button );
  200. dest[GO_CHECKBOX]=&SCAST(Memx<GuiObj>, checkbox);
  201. dest[GO_COMBOBOX]=&SCAST(Memx<GuiObj>, combobox);
  202. dest[GO_CUSTOM ]=&SCAST(Memx<GuiObj>, custom );
  203. dest[GO_DESKTOP ]=&SCAST(Memx<GuiObj>, desktop );
  204. dest[GO_IMAGE ]=&SCAST(Memx<GuiObj>, image );
  205. dest[GO_LIST ]=&SCAST(Memx<GuiObj>, list );
  206. dest[GO_MENU ]=&SCAST(Memx<GuiObj>, menu );
  207. dest[GO_MENU_BAR]=&SCAST(Memx<GuiObj>, menubar );
  208. dest[GO_PROGRESS]=&SCAST(Memx<GuiObj>, progress);
  209. dest[GO_REGION ]=&SCAST(Memx<GuiObj>, region );
  210. dest[GO_SLIDEBAR]=&SCAST(Memx<GuiObj>, slidebar);
  211. dest[GO_SLIDER ]=&SCAST(Memx<GuiObj>, slider );
  212. dest[GO_TABS ]=&SCAST(Memx<GuiObj>, tabs );
  213. dest[GO_TEXT ]=&SCAST(Memx<GuiObj>, text );
  214. dest[GO_TEXTBOX ]=&SCAST(Memx<GuiObj>, textbox );
  215. dest[GO_TEXTLINE]=&SCAST(Memx<GuiObj>, textline);
  216. dest[GO_VIEWPORT]=&SCAST(Memx<GuiObj>, viewport);
  217. dest[GO_WINDOW ]=&SCAST(Memx<GuiObj>, window );
  218. FREPAO(offset)=(dest[i] ? dest[i]->elms() : 0); // do this before new elm creation
  219. // create objects in dest containers (order is important, so it matches source indexes)
  220. FREPA(T._button )button .New().create(T._button [i]);
  221. FREPA(T._checkbox)checkbox.New().create(T._checkbox[i]);
  222. FREPA(T._combobox)combobox.New().create(T._combobox[i]);
  223. FREPA(T._custom )custom .New().create(T._custom [i]);
  224. FREPA(T._desktop )desktop .New().create(T._desktop [i]);
  225. FREPA(T._image )image .New().create(T._image [i]);
  226. FREPA(T._list )list .New().create(T._list [i]);
  227. FREPA(T._menu )menu .New().create(T._menu [i]);
  228. FREPA(T._menubar )menubar .New().create(T._menubar [i]);
  229. FREPA(T._progress)progress.New().create(T._progress[i]);
  230. FREPA(T._region )region .New().create(T._region [i]);
  231. FREPA(T._slidebar)slidebar.New().create(T._slidebar[i]);
  232. FREPA(T._slider )slider .New().create(T._slider [i]);
  233. FREPA(T._tabs )tabs .New().create(T._tabs [i]);
  234. FREPA(T._text )text .New().create(T._text [i]);
  235. FREPA(T._textbox )textbox .New().create(T._textbox [i]);
  236. FREPA(T._textline)textline.New().create(T._textline[i]);
  237. FREPA(T._viewport)viewport.New().create(T._viewport[i]);
  238. FREPA(T._window )window .New().create(T._window [i]);
  239. // set names and add children to parents
  240. FREPA(_objs) // from start to preserve order in containers
  241. {
  242. C Obj &goi=_objs[i];
  243. if(GuiObj *go=GetObj(dest, offset, goi.type, goi.index))
  244. {
  245. Int dest_index=goi.index+offset[goi.type];
  246. // set name
  247. CChar *name=_names.data()+goi.name_offset;
  248. if( Is(name))switch(goi.type)
  249. {
  250. case GO_BUTTON : button [dest_index].name=name; break;
  251. case GO_CHECKBOX: checkbox[dest_index].name=name; break;
  252. case GO_COMBOBOX: combobox[dest_index].name=name; break;
  253. case GO_CUSTOM : custom [dest_index].name=name; break;
  254. case GO_DESKTOP : desktop [dest_index].name=name; break;
  255. case GO_IMAGE : image [dest_index].name=name; break;
  256. case GO_LIST : list [dest_index].name=name; break;
  257. case GO_MENU : menu [dest_index].name=name; break;
  258. case GO_MENU_BAR: menubar [dest_index].name=name; break;
  259. case GO_PROGRESS: progress[dest_index].name=name; break;
  260. case GO_REGION : region [dest_index].name=name; break;
  261. case GO_SLIDEBAR: slidebar[dest_index].name=name; break;
  262. case GO_SLIDER : slider [dest_index].name=name; break;
  263. case GO_TABS : tabs [dest_index].name=name; break;
  264. case GO_TEXT : text [dest_index].name=name; break;
  265. case GO_TEXTBOX : textbox [dest_index].name=name; break;
  266. case GO_TEXTLINE: textline[dest_index].name=name; break;
  267. case GO_VIEWPORT: viewport[dest_index].name=name; break;
  268. case GO_WINDOW : window [dest_index].name=name; break;
  269. }
  270. // set parent
  271. if(GuiObj *p=GetObj(dest, offset, goi.parent_type, goi.parent_index, goi.parent_sub))*p+=*go;else
  272. if(parent)*parent+=*go;
  273. }
  274. }
  275. }
  276. /******************************************************************************/
  277. // GET
  278. /******************************************************************************/
  279. C MembConst<GuiObj>* GuiObjs::objects(GUI_OBJ_TYPE type)C {return ConstCast(T).objs(type);}
  280. MembConst<GuiObj>* GuiObjs::objs (GUI_OBJ_TYPE type)
  281. {
  282. switch(type)
  283. {
  284. default : return null;
  285. case GO_BUTTON : return &SCAST(MembConst<GuiObj>, _button);
  286. case GO_CHECKBOX: return &SCAST(MembConst<GuiObj>, _checkbox);
  287. case GO_COMBOBOX: return &SCAST(MembConst<GuiObj>, _combobox);
  288. case GO_CUSTOM : return &SCAST(MembConst<GuiObj>, _custom);
  289. case GO_DESKTOP : return &SCAST(MembConst<GuiObj>, _desktop);
  290. case GO_IMAGE : return &SCAST(MembConst<GuiObj>, _image);
  291. case GO_LIST : return &SCAST(MembConst<GuiObj>, _list);
  292. case GO_MENU : return &SCAST(MembConst<GuiObj>, _menu);
  293. case GO_MENU_BAR: return &SCAST(MembConst<GuiObj>, _menubar);
  294. case GO_PROGRESS: return &SCAST(MembConst<GuiObj>, _progress);
  295. case GO_REGION : return &SCAST(MembConst<GuiObj>, _region);
  296. case GO_SLIDEBAR: return &SCAST(MembConst<GuiObj>, _slidebar);
  297. case GO_SLIDER : return &SCAST(MembConst<GuiObj>, _slider);
  298. case GO_TABS : return &SCAST(MembConst<GuiObj>, _tabs);
  299. case GO_TEXT : return &SCAST(MembConst<GuiObj>, _text);
  300. case GO_TEXTBOX : return &SCAST(MembConst<GuiObj>, _textbox);
  301. case GO_TEXTLINE: return &SCAST(MembConst<GuiObj>, _textline);
  302. case GO_VIEWPORT: return &SCAST(MembConst<GuiObj>, _viewport);
  303. case GO_WINDOW : return &SCAST(MembConst<GuiObj>, _window);
  304. }
  305. }
  306. /******************************************************************************/
  307. GuiObj* GuiObjs::go(GUI_OBJ_TYPE type, Int index, Int sub)
  308. {
  309. if(Memb<GuiObj> *objs=T.objs(type))if(InRange(index, *objs))
  310. {
  311. GuiObj &go=(*objs)[index];
  312. if(go.type()==GO_TABS && InRange(sub, go.asTabs()))return &go.asTabs().tab(sub);
  313. return &go;
  314. }
  315. return null;
  316. }
  317. /******************************************************************************/
  318. GuiObj* GuiObjs::find(C Str &name, GUI_OBJ_TYPE type)
  319. {
  320. #if 1 // elements are saved in back to front order, that's why linear searching is required (and not binary)
  321. REPA(_objs)
  322. {
  323. C Obj &goi=_objs[i];
  324. if(goi.type==type && EqualPath(T._names.data()+goi.name_offset, name))return go(goi.type, goi.index);
  325. }
  326. #else // binary search
  327. Int l=0, r=_objs.elms(); for(; l<r; )
  328. {
  329. Int mid=UInt(l+r)/2; Obj &goi=_objs[mid];
  330. Int compare=ComparePath(name, T._names.data()+goi.name_offset);
  331. if(!compare)compare=type-goi.type;
  332. if(!compare)return go(goi.type, goi.index);
  333. if( compare<0)r=mid;
  334. else l=mid+1;
  335. }
  336. #endif
  337. return null;
  338. }
  339. GuiObj& GuiObjs::get(C Str &name, GUI_OBJ_TYPE type)
  340. {
  341. GuiObj *go=find(name, type); if(!go)Exit(MLT(S+"Can't find Gui Object \"" +name+'"',
  342. PL,S+u"Nie można znaleźć Obiektu Gui \""+name+'"'));
  343. return *go;
  344. }
  345. /******************************************************************************/
  346. // OPERATIONS
  347. /******************************************************************************/
  348. GuiObjs& GuiObjs::hide()
  349. {
  350. REPA(_objs)
  351. {
  352. C Obj &goi=_objs[i];
  353. if(!goi.parent_type)if(GuiObj *go=T.go(goi.type, goi.index))go->hide();
  354. }
  355. return T;
  356. }
  357. GuiObjs& GuiObjs::show()
  358. {
  359. REPA(_objs)
  360. {
  361. C Obj &goi=_objs[i];
  362. if(!goi.parent_type)if(GuiObj *go=T.go(goi.type, goi.index))go->show();
  363. }
  364. return T;
  365. }
  366. GuiObjs& GuiObjs::activate()
  367. {
  368. REPA(_objs)
  369. {
  370. C Obj &goi=_objs[i];
  371. if(!goi.parent_type)if(GuiObj *go=T.go(goi.type, goi.index)){go->activate(); break;}
  372. }
  373. return T;
  374. }
  375. GuiObjs& GuiObjs::fadeIn()
  376. {
  377. REPA(_objs)
  378. {
  379. C Obj &goi=_objs[i];
  380. if(!goi.parent_type)if(GuiObj *go=T.go(goi.type, goi.index))if(go->type()==GO_WINDOW)go->asWindow().fadeIn();else go->show();
  381. }
  382. return T;
  383. }
  384. GuiObjs& GuiObjs::fadeOut()
  385. {
  386. REPA(_objs)
  387. {
  388. C Obj &goi=_objs[i];
  389. if(!goi.parent_type)if(GuiObj *go=T.go(goi.type, goi.index))if(go->type()==GO_WINDOW)go->asWindow().fadeOut();else go->hide();
  390. }
  391. return T;
  392. }
  393. /******************************************************************************/
  394. // IO
  395. /******************************************************************************/
  396. struct GuiObjsObj2
  397. {
  398. Char name[48];
  399. GUI_OBJ_TYPE type , parent_type;
  400. Int index, parent_index, parent_sub;
  401. };
  402. struct GuiObjsObj1
  403. {
  404. Char name[48];
  405. GUI_OBJ_TYPE type , parent_type ;
  406. Int index, parent_index;
  407. };
  408. struct GuiObjsObj0
  409. {
  410. Char8 name[24];
  411. GUI_OBJ_TYPE type , parent_type;
  412. Int index, parent_index, desc_pos;
  413. };
  414. Bool GuiObjs::save(File &f, CChar *path)C
  415. {
  416. f.putMulti(UInt(CC4_GOBJ), Byte(3)); // version
  417. _names._saveRaw(f);
  418. _objs ._saveRaw(f);
  419. FREPD(t, GO_NUM)if(C Memb<GuiObj> *objs=T.objects(GUI_OBJ_TYPE(t)))FREPA(*objs)
  420. {
  421. f.putByte(t); if(!(*objs)[i].save(f, path))return false;
  422. }
  423. return f.ok();
  424. }
  425. Bool GuiObjs::load(File &f, CChar *path)
  426. {
  427. del(); if(f.getUInt()==CC4_GOBJ)switch(f.decUIntV()) // version
  428. {
  429. case 3:
  430. {
  431. // Gui Object Info
  432. if(_names._loadRaw(f))
  433. if(_objs ._loadRaw(f))
  434. {
  435. // Gui Object Data
  436. REPA(_objs)
  437. {
  438. if(Memb<GuiObj> *objs=T.objs(GUI_OBJ_TYPE(f.getByte())))
  439. {
  440. if(!objs->New().load(f, path))goto error; // load gui object data
  441. }else goto error; // invalid Gui Object Type
  442. }
  443. // add children to parents
  444. FREPA(_objs) // from start to preserve order in containers
  445. {
  446. C Obj &goi =_objs[i];
  447. if(GuiObj *parent=T.go(goi.parent_type, goi.parent_index, goi.parent_sub))
  448. if(GuiObj *go =T.go(goi.type , goi.index ))*parent+=*go;
  449. }
  450. if(f.ok())return true;
  451. }
  452. }break;
  453. case 2:
  454. {
  455. // Gui Object Info
  456. Mems<GuiObjsObj2> old; if(old._loadRaw(f))
  457. {
  458. Memc<Char> old_names;
  459. _objs.setNum(old.elms());
  460. FREPA(_objs)
  461. {
  462. Obj &dest=_objs[i];
  463. GuiObjsObj2 &src = old [i];
  464. dest.name_offset =old_names.elms(); Int length=Length(src.name); FREP(length)old_names.add(src.name[i]); old_names.add('\0');
  465. dest.type =src.type ;
  466. dest.index =src.index ;
  467. dest.parent_type =src.parent_type ;
  468. dest.parent_index=src.parent_index;
  469. dest.parent_sub =src.parent_sub ;
  470. }
  471. _names=old_names;
  472. // Gui Object Data
  473. REPA(_objs)
  474. {
  475. if(Memb<GuiObj> *objs=T.objs(GUI_OBJ_TYPE(f.getByte())))
  476. {
  477. if(!objs->New().load(f, path))goto error; // load gui object data
  478. }else goto error; // invalid Gui Object Type
  479. }
  480. // add children to parents
  481. FREPA(_objs) // from start to preserve order in containers
  482. {
  483. C Obj &goi =_objs[i];
  484. if(GuiObj *parent=T.go(goi.parent_type, goi.parent_index, goi.parent_sub))
  485. if(GuiObj *go =T.go(goi.type , goi.index ))*parent+=*go;
  486. }
  487. if(f.ok())return true;
  488. }
  489. }break;
  490. case 1:
  491. {
  492. // Gui Object Info
  493. Mems<GuiObjsObj1> old; if(old._loadRaw(f))
  494. {
  495. Memc<Char> old_names;
  496. _objs.setNum(old.elms());
  497. FREPA(_objs)
  498. {
  499. Obj &dest=_objs[i];
  500. GuiObjsObj1 &src = old [i];
  501. dest.name_offset =old_names.elms(); Int length=Length(src.name); FREP(length)old_names.add(src.name[i]); old_names.add('\0');
  502. dest.type =src.type ;
  503. dest.index =src.index ;
  504. dest.parent_type =src.parent_type ;
  505. dest.parent_index=src.parent_index;
  506. dest.parent_sub =-1 ;
  507. }
  508. _names=old_names;
  509. // Gui Object Data
  510. REPA(_objs)
  511. {
  512. if(Memb<GuiObj> *objs=T.objs(GUI_OBJ_TYPE(f.getByte())))
  513. {
  514. if(!objs->New().load(f, path))goto error; // load gui object data
  515. }else goto error; // invalid Gui Object Type
  516. }
  517. // add children to parents
  518. FREPA(_objs) // from start to preserve order in containers
  519. {
  520. C Obj &goi =_objs[i];
  521. if(GuiObj *parent=T.go(goi.parent_type, goi.parent_index))
  522. if(GuiObj *go =T.go(goi.type , goi.index ))*parent+=*go;
  523. }
  524. if(f.ok())return true;
  525. }
  526. }break;
  527. case 0:
  528. {
  529. // helper texts
  530. Mems<Char8> helper; if(helper._loadRaw(f))
  531. {
  532. // Gui Object Info
  533. Mems<GuiObjsObj0> old; if(old._loadRaw(f))
  534. {
  535. Memc<Char> old_names;
  536. _objs.setNum(old.elms());
  537. FREPA(_objs)
  538. {
  539. Obj &dest=_objs[i];
  540. GuiObjsObj0 &src = old [i];
  541. dest.name_offset =old_names.elms(); Int length=Length(src.name); FREP(length)old_names.add(src.name[i]); old_names.add('\0');
  542. dest.type =src.type ;
  543. dest.index =src.index ;
  544. dest.parent_type =src.parent_type ;
  545. dest.parent_index=src.parent_index;
  546. dest.parent_sub =-1 ;
  547. }
  548. _names=old_names;
  549. // Gui Object Data
  550. REPA(_objs)
  551. {
  552. if(Memb<GuiObj> *objs=T.objs(GUI_OBJ_TYPE(f.getByte())))
  553. {
  554. if(!objs->New().load(f, path))goto error; // load gui object data
  555. }else goto error; // invalid Gui Object Type
  556. }
  557. // finalize
  558. FREPA(_objs) // from start to preserve order in containers
  559. {
  560. C Obj &goi=_objs[i];
  561. if(GuiObj *go =T.go(goi.type, goi.index))
  562. {
  563. if(old[i].desc_pos>=0)go->desc(helper.data()+old[i].desc_pos);
  564. if(GuiObj *parent=T.go(goi.parent_type, goi.parent_index))*parent+=*go;
  565. }
  566. }
  567. if(f.ok())return true;
  568. }
  569. }
  570. }break;
  571. }
  572. error:
  573. del(); return false;
  574. }
  575. Bool GuiObjs::save(C Str &name)C
  576. {
  577. File f; if(f.writeTry(name)){if(save(f, _GetPath(name)) && f.flush())return true; f.del(); FDelFile(name);}
  578. return false;
  579. }
  580. Bool GuiObjs::load(C Str &name)
  581. {
  582. File f; if(f.readTry(name))return load(f, _GetPath(name));
  583. del(); return false;
  584. }
  585. void GuiObjs::operator=(C Str &name)
  586. {
  587. if(!load(name))Exit(MLT(S+"Can't load Gui Objects \"" +name+"\"",
  588. PL,S+u"Nie można wczytać obiektów interfejsu \""+name+"\""));
  589. }
  590. Bool GuiObjs::load (C UID &id) {return load(id.valid() ? _EncodeFileName(id) : null);}
  591. void GuiObjs::operator=(C UID &id) { T=(id.valid() ? _EncodeFileName(id) : null);}
  592. /******************************************************************************/
  593. }
  594. /******************************************************************************/