UIMLView.cpp 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650
  1. #include "UIMLView.h"
  2. #include "Border.h"
  3. #include "Button.h"
  4. #include "Font.h"
  5. #include "Image.h"
  6. #include "RCPointer.h"
  7. #include "Screen.h"
  8. #include "Scroll.h"
  9. #include "Table.h"
  10. #include "TextField.h"
  11. #include "Window.h"
  12. #include "XML.h"
  13. using namespace Framework;
  14. UIMLElement::UIMLElement()
  15. : ReferenceCounter()
  16. {}
  17. UIMLElement::~UIMLElement() {}
  18. //! applies the layout parameters to a Drawable
  19. void UIMLElement::layout(XML::Element& element,
  20. Drawable& z,
  21. int pWidth,
  22. int pHeight,
  23. UIMLContainer& generalLayouter)
  24. {
  25. int width = z.getWidth();
  26. int height = z.getHeight();
  27. if (element.hasAttribute("style"))
  28. {
  29. z.setStyle((__int64)element.getAttributeValue("style"));
  30. }
  31. if (element.hasAttribute("width"))
  32. {
  33. Text w = element.getAttributeValue("width");
  34. if (!w.isEqual("auto"))
  35. {
  36. width = calculateSize(w, pWidth);
  37. }
  38. }
  39. if (element.hasAttribute("height"))
  40. {
  41. Text h = element.getAttributeValue("height");
  42. if (!h.isEqual("auto"))
  43. {
  44. height = calculateSize(h, pHeight);
  45. }
  46. }
  47. z.setSize(width, height);
  48. if (element.hasAttribute("align-x"))
  49. {
  50. Text la = element.getAttributeValue("align-x");
  51. int x = 0;
  52. if (la.isEqual("start"))
  53. x = 0;
  54. else if (la.isEqual("end"))
  55. x = pWidth;
  56. else if (la.isEqual("center"))
  57. x = pWidth / 2 - width / 2;
  58. else
  59. {
  60. XML::Editor ed
  61. = element.zParent()->selectChildsByAttribute("id", la);
  62. if (ed.exists())
  63. {
  64. generalLayouter.layout(*ed.begin().val(),
  65. *generalLayouter.zDrawableById(la),
  66. pWidth,
  67. pHeight,
  68. generalLayouter);
  69. Drawable* laz = generalLayouter.zDrawableById(la);
  70. if (laz) x = laz->getX();
  71. }
  72. }
  73. if (element.hasAttribute("margin-x"))
  74. {
  75. Text mt = element.getAttributeValue("margin-x");
  76. x += calculateSize(mt, pWidth);
  77. }
  78. z.setX(x);
  79. }
  80. else if (element.hasAttribute("align-left"))
  81. {
  82. Text la = element.getAttributeValue("align-left");
  83. int x = 0;
  84. if (la.isEqual("start"))
  85. x = 0;
  86. else if (la.isEqual("end"))
  87. x = pWidth;
  88. else if (la.isEqual("center"))
  89. x = pWidth / 2 - width / 2;
  90. else
  91. {
  92. XML::Editor ed
  93. = element.zParent()->selectChildsByAttribute("id", la);
  94. if (ed.exists())
  95. {
  96. generalLayouter.layout(*ed.begin().val(),
  97. *generalLayouter.zDrawableById(la),
  98. pWidth,
  99. pHeight,
  100. generalLayouter);
  101. Drawable* laz = generalLayouter.zDrawableById(la);
  102. if (laz) x = laz->getX() + laz->getWidth();
  103. }
  104. }
  105. if (element.hasAttribute("margin-left"))
  106. {
  107. Text mt = element.getAttributeValue("margin-left");
  108. x += calculateSize(mt, pWidth);
  109. }
  110. z.setX(x);
  111. }
  112. else if (element.hasAttribute("align-right"))
  113. {
  114. Text ra = element.getAttributeValue("align-right");
  115. int x = 0;
  116. if (ra.isEqual("start"))
  117. x = -z.getWidth();
  118. else if (ra.isEqual("end"))
  119. x = pWidth - z.getWidth();
  120. else if (ra.isEqual("center"))
  121. x = pWidth / 2 - width / 2;
  122. else
  123. {
  124. XML::Editor ed
  125. = element.zParent()->selectChildsByAttribute("id", ra);
  126. if (ed.exists())
  127. {
  128. generalLayouter.layout(*ed.begin().val(),
  129. *generalLayouter.zDrawableById(ra),
  130. pWidth,
  131. pHeight,
  132. generalLayouter);
  133. Drawable* raz = generalLayouter.zDrawableById(ra);
  134. if (raz) x = raz->getX() - z.getWidth();
  135. }
  136. }
  137. if (element.hasAttribute("margin-right"))
  138. {
  139. Text mt = element.getAttributeValue("margin-right");
  140. x -= calculateSize(mt, pWidth);
  141. }
  142. z.setX(x);
  143. }
  144. if (element.hasAttribute("align-y"))
  145. {
  146. Text ta = element.getAttributeValue("align-y");
  147. int y = 0;
  148. if (ta.isEqual("start"))
  149. y = 0;
  150. else if (ta.isEqual("end"))
  151. y = pHeight;
  152. else if (ta.isEqual("center"))
  153. y = pHeight / 2 - height / 2;
  154. else
  155. {
  156. XML::Editor ed
  157. = element.zParent()->selectChildsByAttribute("id", ta);
  158. if (ed.exists())
  159. {
  160. generalLayouter.layout(*ed.begin().val(),
  161. *generalLayouter.zDrawableById(ta),
  162. pWidth,
  163. pHeight,
  164. generalLayouter);
  165. Drawable* taz = generalLayouter.zDrawableById(ta);
  166. if (taz) y = taz->getY();
  167. }
  168. }
  169. if (element.hasAttribute("margin-y"))
  170. {
  171. Text mt = element.getAttributeValue("margin-y");
  172. y += calculateSize(mt, pHeight);
  173. }
  174. z.setY(y);
  175. }
  176. else if (element.hasAttribute("align-top"))
  177. {
  178. Text ta = element.getAttributeValue("align-top");
  179. int y = 0;
  180. if (ta.isEqual("start"))
  181. y = 0;
  182. else if (ta.isEqual("end"))
  183. y = pHeight;
  184. else if (ta.isEqual("center"))
  185. y = pHeight / 2 - height / 2;
  186. else
  187. {
  188. XML::Editor ed
  189. = element.zParent()->selectChildsByAttribute("id", ta);
  190. if (ed.exists())
  191. {
  192. generalLayouter.layout(*ed.begin().val(),
  193. *generalLayouter.zDrawableById(ta),
  194. pWidth,
  195. pHeight,
  196. generalLayouter);
  197. Drawable* taz = generalLayouter.zDrawableById(ta);
  198. if (taz) y = taz->getY() + taz->getHeight();
  199. }
  200. }
  201. if (element.hasAttribute("margin-top"))
  202. {
  203. Text mt = element.getAttributeValue("margin-top");
  204. y += calculateSize(mt, pHeight);
  205. }
  206. z.setY(y);
  207. }
  208. else if (element.hasAttribute("align-bottom"))
  209. {
  210. Text ba = element.getAttributeValue("align-bottom");
  211. int y = 0;
  212. if (ba.isEqual("start"))
  213. y = -z.getHeight();
  214. else if (ba.isEqual("end"))
  215. y = pHeight - z.getHeight();
  216. else if (ba.isEqual("center"))
  217. y = pHeight / 2 - height / 2;
  218. else
  219. {
  220. XML::Editor ed
  221. = element.zParent()->selectChildsByAttribute("id", ba);
  222. if (ed.exists())
  223. {
  224. generalLayouter.layout(*ed.begin().val(),
  225. *generalLayouter.zDrawableById(ba),
  226. pWidth,
  227. pHeight,
  228. generalLayouter);
  229. Drawable* baz = generalLayouter.zDrawableById(ba);
  230. if (baz) y = baz->getY() - z.getHeight();
  231. }
  232. }
  233. if (element.hasAttribute("margin-bottom"))
  234. {
  235. Text mt = element.getAttributeValue("margin-bottom");
  236. y -= calculateSize(mt, pHeight);
  237. }
  238. z.setY(y);
  239. }
  240. int x = z.getX();
  241. int y = z.getY();
  242. if (element.hasAttribute("x"))
  243. {
  244. Text xt = element.getAttributeValue("x");
  245. x = calculateSize(xt, pWidth);
  246. }
  247. if (element.hasAttribute("y"))
  248. {
  249. Text yt = element.getAttributeValue("y");
  250. y = calculateSize(yt, pHeight);
  251. }
  252. z.setPosition(x, y);
  253. DrawableBackground* zh = dynamic_cast<DrawableBackground*>(&z);
  254. if (zh)
  255. {
  256. if (element.hasAttribute("border"))
  257. {
  258. int br = (int)element.getAttributeValue("border");
  259. zh->setStyle(DrawableBackground::Style::Border, br > 0);
  260. zh->setBorderWidth((int)element.getAttributeValue("border"));
  261. }
  262. if (element.hasAttribute("border-color"))
  263. {
  264. zh->setBorderColor((int)element.getAttributeValue("border-color"));
  265. }
  266. }
  267. // recursive layout
  268. pWidth = z.getInnerWidth();
  269. pHeight = z.getInnerHeight();
  270. for (auto i : getChildren(element))
  271. {
  272. Drawable* z = 0;
  273. if (i->hasAttribute("id"))
  274. {
  275. z = generalLayouter.zDrawableById(i->getAttributeValue("id"));
  276. }
  277. if (z)
  278. {
  279. generalLayouter.layout(*i, *z, pWidth, pHeight, generalLayouter);
  280. }
  281. }
  282. }
  283. int Framework::UIMLElement::calculateSize(Text attributeValue, int parentSize)
  284. {
  285. attributeValue.removeWhitespaceAfter(0);
  286. attributeValue.removeWhitespaceBefore(attributeValue.getLength());
  287. if (attributeValue.has('('))
  288. {
  289. int start = -1;
  290. int len = attributeValue.getLength();
  291. for (int i = 0; i < len; i++)
  292. {
  293. if (attributeValue.getText()[i] == '(') start = i;
  294. if (attributeValue.getText()[i] == ')')
  295. {
  296. if (start < 0) return 0;
  297. Text* part = attributeValue.getTeilText(start + 1, i);
  298. int value = calculateSize(*part, parentSize);
  299. part->release();
  300. attributeValue.remove(start, i + 1);
  301. attributeValue.insert(start, Text(value));
  302. return calculateSize(attributeValue, parentSize);
  303. }
  304. }
  305. return 0;
  306. }
  307. else if (attributeValue.has('*') || attributeValue.has('/'))
  308. {
  309. int posD = attributeValue.positionOf('/');
  310. int posM = attributeValue.positionOf('*');
  311. if ((posD >= 0 && posD < posM) || posM < 0)
  312. {
  313. Text* firstPart = attributeValue.getTeilText(0, posD);
  314. Text* secondPart = attributeValue.getTeilText(posD + 1);
  315. int first = calculateSize(*firstPart, parentSize);
  316. int second = calculateSize(*secondPart, parentSize);
  317. firstPart->release();
  318. secondPart->release();
  319. return first / second;
  320. }
  321. else
  322. {
  323. Text* firstPart = attributeValue.getTeilText(0, posM);
  324. Text* secondPart = attributeValue.getTeilText(posM + 1);
  325. int first = calculateSize(*firstPart, parentSize);
  326. int second = calculateSize(*secondPart, parentSize);
  327. firstPart->release();
  328. secondPart->release();
  329. return first * second;
  330. }
  331. }
  332. else if (attributeValue.has('+') || attributeValue.has('-'))
  333. {
  334. int posP = attributeValue.positionOf('+');
  335. int posN = attributeValue.positionOf('-');
  336. if ((posP >= 0 && posP < posN) || posN < 0)
  337. {
  338. Text* firstPart = attributeValue.getTeilText(0, posP);
  339. Text* secondPart = attributeValue.getTeilText(posP + 1);
  340. int first = calculateSize(*firstPart, parentSize);
  341. int second = calculateSize(*secondPart, parentSize);
  342. firstPart->release();
  343. secondPart->release();
  344. return first + second;
  345. }
  346. else
  347. {
  348. Text* firstPart = attributeValue.getTeilText(0, posN);
  349. Text* secondPart = attributeValue.getTeilText(posN + 1);
  350. int first = calculateSize(*firstPart, parentSize);
  351. int second = calculateSize(*secondPart, parentSize);
  352. firstPart->release();
  353. secondPart->release();
  354. return first - second;
  355. }
  356. }
  357. else if (attributeValue.hasAt(attributeValue.getLength() - 1, "%"))
  358. {
  359. return (int)((int)attributeValue * (parentSize / 100.0));
  360. }
  361. else
  362. {
  363. return (int)attributeValue;
  364. }
  365. }
  366. XML::Editor Framework::UIMLElement::getChildren(XML::Element& element)
  367. {
  368. return element.selectChildren();
  369. }
  370. UIMLContainer::UIMLContainer()
  371. : UIMLElement()
  372. {}
  373. UIMLContainer::~UIMLContainer() {}
  374. UIMLTextField::UIMLTextField()
  375. : UIMLElement()
  376. {}
  377. bool UIMLTextField::isApplicableFor(XML::Element& element)
  378. {
  379. return element.getName().isEqual("textfield");
  380. }
  381. Drawable* UIMLTextField::parseElement(
  382. XML::Element& element, UIMLContainer& generalFactory)
  383. {
  384. TextField* t = generalFactory.getFactory().createTextField(
  385. generalFactory.getFactory().initParam);
  386. t->setText(element.getText());
  387. updateElement(element, *t, generalFactory);
  388. return t;
  389. }
  390. bool Framework::UIMLTextField::updateElement(
  391. XML::Element& element, Drawable& z, UIMLContainer& generalFactory)
  392. {
  393. TextField* t = dynamic_cast<TextField*>(&z);
  394. if (!t) return false;
  395. if (!element.hasAttribute("style"))
  396. {
  397. TextField* tmp = generalFactory.getFactory().createTextField(
  398. generalFactory.getFactory().initParam);
  399. tmp->addStyle(TextField::Style::TextField);
  400. t->setStyle(tmp->getStyles());
  401. tmp->release();
  402. }
  403. return true;
  404. }
  405. void UIMLTextField::layout(XML::Element& element,
  406. Drawable& z,
  407. int pWidth,
  408. int pHeight,
  409. UIMLContainer& generalLayouter)
  410. {
  411. TextField* tf = dynamic_cast<TextField*>(&z);
  412. if (element.hasAttribute("font-size"))
  413. {
  414. tf->setFontSize(
  415. (unsigned char)(int)element.getAttributeValue("font-size"));
  416. }
  417. ((TextField*)&z)->setText(element.getText());
  418. if (element.hasAttribute("width"))
  419. {
  420. Text w = element.getAttributeValue("width");
  421. if (w.isEqual("auto"))
  422. {
  423. z.setWidth(((TextField*)&z)->getNeededWidth());
  424. }
  425. }
  426. if (element.hasAttribute("height"))
  427. {
  428. Text h = element.getAttributeValue("height");
  429. if (h.isEqual("auto"))
  430. {
  431. z.setHeight(((TextField*)&z)->getNeededHeight());
  432. }
  433. }
  434. if (element.hasAttribute("text-color"))
  435. {
  436. tf->setFontColor((int)element.getAttributeValue("text-color"));
  437. }
  438. UIMLElement::layout(element, z, pWidth, pHeight, generalLayouter);
  439. if (element.hasAttribute("text-align-horizontal"))
  440. z.setStyle(TextField::Style::HCenter,
  441. element.getAttributeValue("text-align-horizontal")
  442. .isEqual("center"));
  443. if (element.hasAttribute("text-align-vertical"))
  444. z.setStyle(TextField::Style::VCenter,
  445. element.getAttributeValue("text-align-vertical").isEqual("center"));
  446. if (element.hasAttribute("disabled"))
  447. z.removeStyle(TextField::Style::Editable);
  448. if (element.getAttributeValue("vScroll").isEqual("auto"))
  449. {
  450. tf->setStyle(TextField::Style::VScroll,
  451. tf->getNeededHeight() > tf->getInnerHeight());
  452. tf->setVerticalClickScroll(tf->getFontSize());
  453. tf->updateVScroll();
  454. }
  455. if (element.getAttributeValue("hScroll").isEqual("auto"))
  456. {
  457. tf->setStyle(TextField::Style::HScroll,
  458. tf->getNeededWidth() > tf->getInnerWidth());
  459. tf->setHorizontalClickScroll(tf->getFontSize());
  460. tf->updateHScroll();
  461. }
  462. }
  463. UIMLButton::UIMLButton()
  464. : UIMLElement()
  465. {}
  466. bool UIMLButton::isApplicableFor(XML::Element& element)
  467. {
  468. return element.getName().isEqual("button");
  469. }
  470. Drawable* UIMLButton::parseElement(
  471. XML::Element& element, UIMLContainer& generalFactory)
  472. {
  473. Button* k = generalFactory.getFactory().createButton(
  474. generalFactory.getFactory().initParam);
  475. updateElement(element, *k, generalFactory);
  476. return k;
  477. }
  478. bool Framework::UIMLButton::updateElement(
  479. XML::Element& element, Drawable& z, UIMLContainer& generalFactory)
  480. {
  481. Button* k = dynamic_cast<Button*>(&z);
  482. if (!k) return false;
  483. if (!element.hasAttribute("style"))
  484. {
  485. Button* tmp = generalFactory.getFactory().createButton(
  486. generalFactory.getFactory().initParam);
  487. k->setStyle(tmp->getStyles());
  488. tmp->release();
  489. }
  490. return true;
  491. }
  492. void UIMLButton::layout(XML::Element& element,
  493. Drawable& z,
  494. int pWidth,
  495. int pHeight,
  496. UIMLContainer& generalLayouter)
  497. {
  498. if (element.hasAttribute("font-size"))
  499. ((Button*)&z)
  500. ->setFontSize(
  501. (unsigned char)(int)element.getAttributeValue("font-size"));
  502. ((Button*)&z)->setText(element.getText());
  503. UIMLElement::layout(element, z, pWidth, pHeight, generalLayouter);
  504. }
  505. UIMLCheck::UIMLCheck()
  506. : UIMLElement()
  507. {}
  508. bool UIMLCheck::isApplicableFor(XML::Element& element)
  509. {
  510. return element.getName().isEqual("check");
  511. }
  512. Drawable* UIMLCheck::parseElement(
  513. XML::Element& element, UIMLContainer& generalFactory)
  514. {
  515. CheckBox* k = generalFactory.getFactory().createCheckBox(
  516. generalFactory.getFactory().initParam);
  517. updateElement(element, *k, generalFactory);
  518. return k;
  519. }
  520. bool Framework::UIMLCheck::updateElement(
  521. XML::Element& element, Drawable& z, UIMLContainer& generalFactory)
  522. {
  523. CheckBox* k = dynamic_cast<CheckBox*>(&z);
  524. if (!k) return false;
  525. if (!element.hasAttribute("style"))
  526. {
  527. CheckBox* tmp = generalFactory.getFactory().createCheckBox(
  528. generalFactory.getFactory().initParam);
  529. k->setStyle(tmp->getStyles());
  530. tmp->release();
  531. }
  532. return true;
  533. }
  534. void UIMLCheck::layout(XML::Element& element,
  535. Drawable& z,
  536. int pWidth,
  537. int pHeight,
  538. UIMLContainer& generalLayouter)
  539. {
  540. ((CheckBox*)&z)->setText(element.getText());
  541. ((CheckBox*)&z)->setSText(element.getText());
  542. z.setStyle(CheckBox::Style::Selected, element.hasAttribute("selected"));
  543. if (element.hasAttribute("font-size"))
  544. ((CheckBox*)&z)
  545. ->setSSize(
  546. (unsigned char)(int)element.getAttributeValue("font-size"));
  547. UIMLElement::layout(element, z, pWidth, pHeight, generalLayouter);
  548. }
  549. UIMLText::UIMLText()
  550. : UIMLElement()
  551. {}
  552. bool UIMLText::isApplicableFor(XML::Element& element)
  553. {
  554. return element.getName().isEqual("text");
  555. }
  556. Drawable* UIMLText::parseElement(
  557. XML::Element& element, UIMLContainer& generalFactory)
  558. {
  559. TextField* t = generalFactory.getFactory().createTextField(
  560. generalFactory.getFactory().initParam);
  561. t->setText(element.getText());
  562. updateElement(element, *t, generalFactory);
  563. return t;
  564. }
  565. bool Framework::UIMLText::updateElement(
  566. XML::Element& element, Drawable& z, UIMLContainer& generalFactory)
  567. {
  568. TextField* t = dynamic_cast<TextField*>(&z);
  569. if (!t) return false;
  570. if (!element.hasAttribute("style"))
  571. {
  572. TextField* tmp = generalFactory.getFactory().createTextField(
  573. generalFactory.getFactory().initParam);
  574. tmp->addStyle(TextField::Style::Text);
  575. t->setStyle(tmp->getStyles());
  576. tmp->release();
  577. }
  578. return true;
  579. }
  580. void UIMLText::layout(XML::Element& element,
  581. Drawable& z,
  582. int pWidth,
  583. int pHeight,
  584. UIMLContainer& generalLayouter)
  585. {
  586. TextField* tf = dynamic_cast<TextField*>(&z);
  587. if (element.hasAttribute("font-size"))
  588. {
  589. tf->setFontSize(
  590. (unsigned char)(int)element.getAttributeValue("font-size"));
  591. }
  592. tf->setText(element.getText());
  593. if (element.hasAttribute("width"))
  594. {
  595. Text w = element.getAttributeValue("width");
  596. if (w.isEqual("auto"))
  597. {
  598. z.setWidth(tf->getNeededWidth());
  599. }
  600. }
  601. if (element.hasAttribute("height"))
  602. {
  603. Text h = element.getAttributeValue("height");
  604. if (h.isEqual("auto"))
  605. {
  606. z.setHeight(tf->getNeededHeight());
  607. }
  608. }
  609. if (element.hasAttribute("text-color"))
  610. {
  611. tf->setFontColor((int)element.getAttributeValue("text-color"));
  612. }
  613. UIMLElement::layout(element, z, pWidth, pHeight, generalLayouter);
  614. if (element.hasAttribute("text-align-horizontal"))
  615. z.setStyle(TextField::Style::HCenter,
  616. element.getAttributeValue("text-align-horizontal")
  617. .isEqual("center"));
  618. if (element.hasAttribute("text-align-vertical"))
  619. z.setStyle(TextField::Style::VCenter,
  620. element.getAttributeValue("text-align-vertical").isEqual("center"));
  621. if (element.hasAttribute("disabled"))
  622. z.removeStyle(TextField::Style::Editable);
  623. if (element.getAttributeValue("vScroll").isEqual("auto"))
  624. {
  625. tf->setStyle(TextField::Style::VScroll,
  626. tf->getNeededHeight() > tf->getInnerHeight());
  627. tf->setVerticalClickScroll(tf->getFontSize());
  628. tf->updateVScroll();
  629. }
  630. if (element.getAttributeValue("hScroll").isEqual("auto"))
  631. {
  632. tf->setStyle(TextField::Style::HScroll,
  633. tf->getNeededWidth() > tf->getInnerWidth());
  634. tf->setHorizontalClickScroll(tf->getFontSize());
  635. tf->updateHScroll();
  636. }
  637. }
  638. UIMLTextArea::UIMLTextArea()
  639. : UIMLElement()
  640. {}
  641. bool UIMLTextArea::isApplicableFor(XML::Element& element)
  642. {
  643. return element.getName().isEqual("textarea");
  644. }
  645. Drawable* UIMLTextArea::parseElement(
  646. XML::Element& element, UIMLContainer& generalFactory)
  647. {
  648. TextField* t = generalFactory.getFactory().createTextField(
  649. generalFactory.getFactory().initParam);
  650. t->setText(element.getText());
  651. updateElement(element, *t, generalFactory);
  652. return t;
  653. }
  654. bool Framework::UIMLTextArea::updateElement(
  655. XML::Element& element, Drawable& z, UIMLContainer& generalFactory)
  656. {
  657. TextField* t = dynamic_cast<TextField*>(&z);
  658. if (!t) return false;
  659. if (!element.hasAttribute("style"))
  660. {
  661. TextField* tmp = generalFactory.getFactory().createTextField(
  662. generalFactory.getFactory().initParam);
  663. tmp->addStyle(TextField::Style::TextGebiet);
  664. t->setStyle(tmp->getStyles());
  665. tmp->release();
  666. }
  667. return true;
  668. }
  669. void UIMLTextArea::layout(XML::Element& element,
  670. Drawable& z,
  671. int pWidth,
  672. int pHeight,
  673. UIMLContainer& generalLayouter)
  674. {
  675. TextField* tf = dynamic_cast<TextField*>(&z);
  676. if (element.hasAttribute("font-size"))
  677. {
  678. tf->setFontSize(
  679. (unsigned char)(int)element.getAttributeValue("font-size"));
  680. }
  681. if (element.hasAttribute("disabled"))
  682. z.removeStyle(TextField::Style::Editable);
  683. tf->setText(element.getText());
  684. tf->zTextRenderer()->formatText(tf->zText(), z.getInnerWidth());
  685. if (element.hasAttribute("width"))
  686. {
  687. Text w = element.getAttributeValue("width");
  688. if (w.isEqual("auto"))
  689. {
  690. z.setWidth(((TextField*)&z)->getNeededWidth());
  691. }
  692. }
  693. if (element.hasAttribute("height"))
  694. {
  695. Text h = element.getAttributeValue("height");
  696. if (h.isEqual("auto"))
  697. {
  698. z.setHeight(((TextField*)&z)->getNeededHeight());
  699. }
  700. }
  701. if (element.hasAttribute("text-color"))
  702. {
  703. tf->setFontColor((int)element.getAttributeValue("text-color"));
  704. }
  705. UIMLElement::layout(element, z, pWidth, pHeight, generalLayouter);
  706. if (element.hasAttribute("text-align-horizontal"))
  707. z.setStyle(TextField::Style::HCenter,
  708. element.getAttributeValue("text-align-horizontal")
  709. .isEqual("center"));
  710. if (element.hasAttribute("text-align-vertical"))
  711. z.setStyle(TextField::Style::VCenter,
  712. element.getAttributeValue("text-align-vertical").isEqual("center"));
  713. if (element.hasAttribute("font-size"))
  714. if (element.getAttributeValue("vScroll").isEqual("auto"))
  715. {
  716. tf->setStyle(TextField::Style::VScroll,
  717. tf->getNeededHeight() > tf->getInnerHeight());
  718. tf->setVerticalClickScroll(tf->getFontSize());
  719. tf->updateVScroll();
  720. }
  721. if (element.getAttributeValue("hScroll").isEqual("auto"))
  722. {
  723. tf->setStyle(TextField::Style::HScroll,
  724. tf->getNeededWidth() > tf->getInnerWidth());
  725. tf->setHorizontalClickScroll(tf->getFontSize());
  726. tf->updateHScroll();
  727. }
  728. }
  729. UIMLTable::UIMLTable()
  730. : UIMLElement()
  731. {}
  732. bool UIMLTable::isApplicableFor(XML::Element& element)
  733. {
  734. return element.getName().isEqual("table");
  735. }
  736. Drawable* UIMLTable::parseElement(
  737. XML::Element& element, UIMLContainer& generalFactory)
  738. {
  739. ObjTable* t = generalFactory.getFactory().createObjTable(
  740. generalFactory.getFactory().initParam);
  741. updateElement(element, *t, generalFactory);
  742. return t;
  743. }
  744. DLLEXPORT bool Framework::UIMLTable::updateElement(
  745. XML::Element& element, Drawable& z, UIMLContainer& generalFactory)
  746. {
  747. ObjTable* t = dynamic_cast<ObjTable*>(&z);
  748. if (!t) return false;
  749. int index = 0;
  750. int linePos = 0;
  751. int numCols = 0;
  752. Text currentId = element.getAttributeValue("id");
  753. for (auto i = element.getChilds(); i; i++)
  754. {
  755. Text id;
  756. if (i->hasAttribute("id"))
  757. id = i->getAttributeValue("id");
  758. else
  759. {
  760. id = currentId + "_tr_" + index++;
  761. i->setAttribute("id", id);
  762. }
  763. if (i->getName().isEqual("tr"))
  764. {
  765. if (t->getRowNumber(id) == -1) t->addRow(id);
  766. t->setRowPosition(id, linePos);
  767. int c = 1;
  768. for (auto j = i->getChilds(); j; j++)
  769. {
  770. if (t->getColumnCount() < c) t->addColumn(Text(c - 1));
  771. if (numCols < c) numCols = c;
  772. Drawable* z = t->zDrawable(Text(c - 1), id);
  773. if (!z
  774. || !generalFactory.updateElement(
  775. element, *z, generalFactory))
  776. {
  777. z = generalFactory.parseElement(*j.val(), generalFactory);
  778. if (z)
  779. {
  780. if (z->getWidth() > t->getColumnWidth(Text(c - 1)))
  781. t->setColumnWidth(Text(c - 1), z->getWidth());
  782. if (z->getHeight() > t->getRowHeight(Text(id)))
  783. t->setRowHeight(Text(id), z->getHeight());
  784. t->setDrawableZ(Text(c - 1), id, z);
  785. }
  786. }
  787. c++;
  788. }
  789. }
  790. linePos++;
  791. }
  792. for (int i = 0; i < t->getRowCount(); i++)
  793. { // remove all lines that are not in the xml
  794. if (!element.selectChildsByName("tr")
  795. .whereAttributeEquals("id", *t->zRowName(i))
  796. .exists())
  797. {
  798. t->removeRow(i);
  799. i--;
  800. }
  801. }
  802. for (int i = numCols; i < t->getColumnCount(); i++)
  803. { // remove all columns that are not in the xml
  804. t->removeColumn(i);
  805. i--;
  806. }
  807. if (!element.hasAttribute("style"))
  808. {
  809. ObjTable* tmp = generalFactory.getFactory().createObjTable(
  810. generalFactory.getFactory().initParam);
  811. t->setStyle(tmp->getStyles());
  812. tmp->release();
  813. }
  814. return true;
  815. }
  816. void UIMLTable::layout(XML::Element& element,
  817. Drawable& z,
  818. int pWidth,
  819. int pHeight,
  820. UIMLContainer& generalLayouter)
  821. {
  822. if (element.hasAttribute("scroll"))
  823. {
  824. z.setStyle(ObjTable::Style::HScroll,
  825. element.getAttributeValue("scroll").isEqual("horizontal"));
  826. z.setStyle(ObjTable::Style::VScroll,
  827. element.getAttributeValue("scroll").isEqual("vertical"));
  828. z.setStyle(ObjTable::Style::scroll,
  829. element.getAttributeValue("scroll").isEqual("both"));
  830. }
  831. UIMLElement::layout(element, z, pWidth, pHeight, generalLayouter);
  832. ObjTable* objT = (ObjTable*)&z;
  833. if (objT->getRowCount() > 0)
  834. {
  835. if (element.hasAttribute("line-height"))
  836. {
  837. int height = (int)element.getAttributeValue("line-height");
  838. for (int i = 0; i < objT->getRowCount(); i++)
  839. objT->setRowHeight(i, height);
  840. }
  841. for (int i = 0; i < objT->getColumnCount(); i++)
  842. {
  843. if (objT->zDrawable(i, 0))
  844. objT->setColumnWidth(i, objT->zDrawable(i, 0)->getWidth());
  845. }
  846. }
  847. }
  848. XML::Editor Framework::UIMLTable::getChildren(XML::Element& element)
  849. {
  850. return element.selectChildren().selectChildren();
  851. }
  852. UIMLFrame::UIMLFrame()
  853. : UIMLElement()
  854. {}
  855. bool UIMLFrame::isApplicableFor(XML::Element& element)
  856. {
  857. return element.getName().isEqual("frame");
  858. }
  859. Drawable* UIMLFrame::parseElement(
  860. XML::Element& element, UIMLContainer& generalFactory)
  861. {
  862. Window* f = generalFactory.getFactory().createWindow(
  863. generalFactory.getFactory().initParam);
  864. updateElement(element, *f, generalFactory);
  865. return f;
  866. }
  867. bool Framework::UIMLFrame::updateElement(
  868. XML::Element& element, Drawable& z, UIMLContainer& generalFactory)
  869. {
  870. Window* f = dynamic_cast<Window*>(&z);
  871. if (!f) return false;
  872. for (auto member = f->getMembers().begin(); member;)
  873. { // remove all members that are not in the xml
  874. Framework::Text id = generalFactory.getDrawableId(*member.val());
  875. if (id.getLength() == 0)
  876. {
  877. member.remove();
  878. f->setRender();
  879. }
  880. else
  881. {
  882. member++;
  883. }
  884. }
  885. int index = 0;
  886. for (auto i = element.getChilds(); i; i++)
  887. {
  888. Text id = i->getAttributeValue("id");
  889. Drawable* z = generalFactory.zDrawableById(id);
  890. if (!id.getLength() || !z || f->getMembers().indexOf(z) < 0
  891. || !generalFactory.updateElement(*i.val(), *z, generalFactory))
  892. {
  893. if (f->getMembers().indexOf(z) >= 0)
  894. {
  895. f->removeMember(z);
  896. }
  897. if (z) generalFactory.removeDrawable(*z);
  898. z = generalFactory.parseElement(*i.val(), generalFactory);
  899. if (z) f->addMember(z);
  900. }
  901. if (z) f->setMemberIndex(z, index++);
  902. }
  903. if (!element.hasAttribute("style"))
  904. {
  905. Window* tmp = generalFactory.getFactory().createWindow(
  906. generalFactory.getFactory().initParam);
  907. f->setStyle(tmp->getStyles());
  908. tmp->release();
  909. }
  910. return true;
  911. }
  912. void UIMLFrame::layout(XML::Element& element,
  913. Drawable& z,
  914. int pWidth,
  915. int pHeight,
  916. UIMLContainer& generalLayouter)
  917. {
  918. Window* f = dynamic_cast<Window*>(&z);
  919. if (element.hasAttribute("title"))
  920. f->setTitel(element.getAttributeValue("title"));
  921. if (element.hasAttribute("title-height"))
  922. {
  923. f->zTTextField()->setSize(f->zTTextField()->getWidth(),
  924. (int)element.getAttributeValue("title-height"));
  925. }
  926. if (element.hasAttribute("title-font-size"))
  927. {
  928. f->zTTextField()->setFontSize(
  929. (unsigned char)(int)element.getAttributeValue("title-font-size"));
  930. }
  931. if (element.hasAttribute("title-text-color"))
  932. {
  933. f->zTTextField()->setFontColor(
  934. (int)element.getAttributeValue("title-text-color"));
  935. }
  936. if (element.hasAttribute("width"))
  937. {
  938. Text w = element.getAttributeValue("width");
  939. if (w.isEqual("auto"))
  940. {
  941. z.setWidth(f->getNeededChildWidth());
  942. }
  943. }
  944. if (element.hasAttribute("height"))
  945. {
  946. Text h = element.getAttributeValue("height");
  947. if (h.isEqual("auto"))
  948. {
  949. z.setHeight(f->getNeededChildHeight());
  950. }
  951. }
  952. if (element.hasAttribute("display"))
  953. {
  954. UIMLElement::layout(element,
  955. z,
  956. pWidth,
  957. pHeight,
  958. generalLayouter); // calculate all sizes
  959. if (element.getAttributeValue("display").isEqual("column"))
  960. {
  961. int gap = calculateSize(element.getAttributeValue("gap"), pHeight);
  962. int y = 0;
  963. for (Drawable* z : f->getMembers())
  964. {
  965. Text id = generalLayouter.getDrawableId(*z);
  966. auto child = element.selectChildsByAttribute("id", id);
  967. if (child.exists())
  968. {
  969. if (!child.whereAttributeExists("align-left").exists()
  970. && !child.whereAttributeExists("align-right").exists()
  971. && !child.whereAttributeExists("align-top").exists()
  972. && !child.whereAttributeExists("align-bottom").exists())
  973. {
  974. z->setY(y);
  975. y += z->getHeight() + gap;
  976. }
  977. }
  978. }
  979. }
  980. else if (element.getAttributeValue("display").isEqual("row"))
  981. {
  982. int gap = calculateSize(element.getAttributeValue("gap"), pWidth);
  983. int x = 0;
  984. for (Drawable* z : f->getMembers())
  985. {
  986. Text id = generalLayouter.getDrawableId(*z);
  987. auto child = element.selectChildsByAttribute("id", id);
  988. if (child.exists())
  989. {
  990. if (!child.whereAttributeExists("align-left").exists()
  991. && !child.whereAttributeExists("align-right").exists()
  992. && !child.whereAttributeExists("align-top").exists()
  993. && !child.whereAttributeExists("align-bottom").exists())
  994. {
  995. z->setX(x);
  996. x += z->getWidth() + gap;
  997. }
  998. }
  999. }
  1000. }
  1001. }
  1002. UIMLElement::layout(element,
  1003. z,
  1004. pWidth,
  1005. pHeight,
  1006. generalLayouter); // calculate all remaining positions
  1007. if (element.getAttributeValue("vScroll").isEqual("auto"))
  1008. {
  1009. f->setStyle(Window::Style::VScroll,
  1010. f->getNeededChildHeight() > f->getInnerHeight());
  1011. f->setVSBScroll(10);
  1012. f->updateVScroll();
  1013. }
  1014. if (element.getAttributeValue("hScroll").isEqual("auto"))
  1015. {
  1016. f->setStyle(Window::Style::HScroll,
  1017. f->getNeededChildWidth() > f->getInnerWidth());
  1018. f->setHSBScroll(10);
  1019. f->updateHScroll();
  1020. }
  1021. }
  1022. // Creates a UIML View
  1023. UIMLView::UIMLView()
  1024. : DrawableBackground()
  1025. {
  1026. style = Style::MEIgnoreInside | Style::MEIgnoreParentInside
  1027. | Style::MEIgnoreVisible | Style::MEIgnoreProcessed;
  1028. members = new RCTrie<Drawable>();
  1029. dom = 0;
  1030. nextId = 0;
  1031. memset((void*)&init, 0, sizeof(UIInit));
  1032. addKnownElement(new UIMLTextField());
  1033. addKnownElement(new UIMLButton());
  1034. addKnownElement(new UIMLCheck());
  1035. addKnownElement(new UIMLText());
  1036. addKnownElement(new UIMLTextArea());
  1037. addKnownElement(new UIMLTable());
  1038. addKnownElement(new UIMLFrame());
  1039. }
  1040. // Creates a UIML View from a UIML text
  1041. // uiml: An xml element according to the KSG UIML standard
  1042. UIMLView::UIMLView(XML::Element* uiml, UIInit& init)
  1043. : UIMLView()
  1044. {
  1045. this->init = init;
  1046. setUIML(uiml);
  1047. }
  1048. // Creates a UIML View from a UIML text
  1049. // uiml: An xml text according to the KSG UIML standard
  1050. UIMLView::UIMLView(Text uiml, UIInit& init)
  1051. : UIMLView()
  1052. {
  1053. this->init = init;
  1054. setUIML(uiml);
  1055. }
  1056. UIMLView::~UIMLView()
  1057. {
  1058. if (dom) dom->release();
  1059. members->release();
  1060. }
  1061. // Processes a mouse event. Called automatically by the framework.
  1062. // me: The event
  1063. void UIMLView::doMouseEvent(MouseEvent& me, bool userRet)
  1064. {
  1065. if (dom)
  1066. {
  1067. bool processed = me.processed;
  1068. me.processed |= hasStyleNot(Style::Visible);
  1069. bool insideParent = me.insideParent;
  1070. if (!hasStyle(Style::Visible) || !me.insideParent || me.processed
  1071. || me.mx < 0 || me.my < 0 || me.mx >= gr.x || me.my >= gr.y
  1072. || !userRet)
  1073. me.insideParent = 0;
  1074. int rbr = 0;
  1075. if (hasStyle(Style::Border) && border) rbr = border->getRWidth();
  1076. me.mx -= rbr;
  1077. me.my -= rbr;
  1078. if (hasStyle(Style::VScroll) && vertikalScrollBar)
  1079. me.my += vertikalScrollBar->getScroll();
  1080. if (hasStyle(Style::HScroll) && horizontalScrollBar)
  1081. me.mx += horizontalScrollBar->getScroll();
  1082. if (dom)
  1083. {
  1084. for (auto i = dom->getChilds(); i; i++)
  1085. { // TODO render elements backwards
  1086. Drawable* z = members->z(i->getAttributeValue("id"),
  1087. i->getAttributeValue("id").getLength());
  1088. if (z) z->doPublicMouseEvent(me);
  1089. }
  1090. }
  1091. me.mx += rbr;
  1092. me.my += rbr;
  1093. if (hasStyle(Style::VScroll) && vertikalScrollBar)
  1094. me.my -= vertikalScrollBar->getScroll();
  1095. if (hasStyle(Style::HScroll) && horizontalScrollBar)
  1096. me.mx -= horizontalScrollBar->getScroll();
  1097. if (!hasStyle(Style::Visible) || !me.insideParent || me.processed
  1098. || me.mx < 0 || me.my < 0 || me.mx >= gr.x || me.my >= gr.y
  1099. || !userRet)
  1100. me.insideParent = insideParent;
  1101. else
  1102. me.processed = 1;
  1103. if (hasStyleNot(Style::Visible)) me.processed = processed;
  1104. }
  1105. }
  1106. void Framework::UIMLView::setOnMemberMouseEvent(
  1107. std::function<bool(XML::Element& element, Drawable& member, MouseEvent me)>
  1108. onEventAction)
  1109. {
  1110. onMemberMouseEvent = onEventAction;
  1111. }
  1112. void Framework::UIMLView::setOnMemberKeyboardEvent(std::function<bool(
  1113. XML::Element& element, Drawable& member, KeyboardEvent te)>
  1114. onEventAction)
  1115. {
  1116. onMemberKeyboardEvent = onEventAction;
  1117. }
  1118. //! removes all known elements that can be used in UIML
  1119. void UIMLView::removeAllKnownElements()
  1120. {
  1121. knownElements.clear();
  1122. }
  1123. //! adds a new known element that can then be used in UIML.
  1124. void UIMLView::addKnownElement(UIMLElement* element)
  1125. {
  1126. knownElements.add(element);
  1127. }
  1128. //! checks whether an xml element is a known UIML element;
  1129. bool UIMLView::isKnownElement(XML::Element* zElement)
  1130. {
  1131. for (UIMLElement* element : knownElements)
  1132. {
  1133. if (element->isApplicableFor(*zElement)) return 1;
  1134. }
  1135. return 0;
  1136. }
  1137. // sets the content of the view
  1138. // uiml: An xml element according to the KSG UIML standard
  1139. void UIMLView::setUIML(XML::Element* uiml)
  1140. {
  1141. if (dom)
  1142. { // update dom and members
  1143. auto newChilds = uiml->selectChildren().selectAllElements();
  1144. // remove old members
  1145. for (XML::Element* i :
  1146. dom->selectChildren().selectAllElements().whereAttributeExists(
  1147. "id"))
  1148. {
  1149. Framework::Text id = i->getAttributeValue("id");
  1150. if (!newChilds.whereAttributeEquals("id", id).exists())
  1151. {
  1152. Drawable* z = members->z(id, id.getLength());
  1153. if (z) removeDrawable(*z);
  1154. }
  1155. }
  1156. dom = uiml;
  1157. update();
  1158. }
  1159. else
  1160. { // initialize dom and members
  1161. dom = uiml;
  1162. for (auto i = dom->getChilds(); i; i++)
  1163. {
  1164. Drawable* z = parseElement(*i.val(), *this);
  1165. if (z) z->release();
  1166. }
  1167. }
  1168. }
  1169. // sets the content of the view
  1170. // uiml: An xml text according to the KSG UIML standard
  1171. void UIMLView::setUIML(Text uiml)
  1172. {
  1173. setUIML(new XML::Element(uiml));
  1174. }
  1175. // Returns a drawing that has a specific id in UIML
  1176. // id: the id of the drawing
  1177. Drawable* UIMLView::zDrawableById(const char* id)
  1178. {
  1179. return members->z(id, textLength(id));
  1180. }
  1181. // Returns a drawing that has a specific id in UIML
  1182. // id: the id of the drawing
  1183. Drawable* UIMLView::getDrawableById(const char* id)
  1184. {
  1185. return members->get(id, textLength(id));
  1186. }
  1187. void Framework::UIMLView::update()
  1188. {
  1189. for (auto i = dom->getChilds(); i; i++)
  1190. {
  1191. Text id = i->getAttributeValue("id");
  1192. Drawable* z = zDrawableById(id);
  1193. if (!id.getLength() || !z || !updateElement(*i.val(), *z, *this))
  1194. {
  1195. z = parseElement(*i.val(), *this);
  1196. if (z) z->release();
  1197. }
  1198. }
  1199. }
  1200. // updates size and position of all drawings according to the specifications
  1201. // in UIML
  1202. void UIMLView::layout()
  1203. {
  1204. if (dom)
  1205. {
  1206. for (auto i = dom->getChilds(); i; i++)
  1207. {
  1208. Text id = i->getAttributeValue("id");
  1209. Drawable* z = zDrawableById(id);
  1210. if (z)
  1211. {
  1212. layout(*i.val(),
  1213. *z,
  1214. this->getInnerWidth(),
  1215. this->getInnerHeight(),
  1216. *this);
  1217. }
  1218. }
  1219. }
  1220. }
  1221. // adds an element
  1222. // uiml: An xml text according to the KSG UIML standard representing the
  1223. // new object
  1224. Text UIMLView::addMember(Text uiml)
  1225. {
  1226. XML::Element* e = new XML::Element(uiml);
  1227. Drawable* z = parseElement(*e, *this);
  1228. if (z)
  1229. {
  1230. dom->addChildAtFront(e);
  1231. z->release();
  1232. }
  1233. return e->getAttributeValue("id");
  1234. }
  1235. // adds an element to a parent element (currently only works with
  1236. // frame objects)
  1237. // uiml: An xml text according to the KSG UIML standard representing the
  1238. // new object
  1239. Text UIMLView::addMember(Text uiml, Text parentId)
  1240. {
  1241. XML::Element* e = new XML::Element(uiml);
  1242. XML::Editor ed = dom->selectChildren();
  1243. while (ed.begin())
  1244. {
  1245. XML::Editor ed2 = ed.whereAttributeEquals("id", parentId);
  1246. if (ed2.begin())
  1247. {
  1248. if (ed2.begin()->getName().isEqual("frame"))
  1249. {
  1250. Drawable* z = parseElement(*e, *this);
  1251. if (z)
  1252. {
  1253. dynamic_cast<Window*>(
  1254. members->z(parentId, parentId.getLength()))
  1255. ->addMember(z);
  1256. ed2.begin()->addChild(e);
  1257. }
  1258. return e->getAttributeValue("id");
  1259. }
  1260. }
  1261. ed = ed.selectChildren();
  1262. }
  1263. e->release();
  1264. return "";
  1265. }
  1266. // removes an element
  1267. // id: id of the element
  1268. void UIMLView::removeMember(Text id)
  1269. {
  1270. XML::Editor e = dom->selectChildsByAttribute("id", id);
  1271. e.remove();
  1272. members->remove(id, id.getLength());
  1273. }
  1274. // Processes a keyboard event. Called automatically by the framework
  1275. // te: The event
  1276. void UIMLView::doKeyboardEvent(KeyboardEvent& te)
  1277. {
  1278. bool processed = te.processed;
  1279. DrawableBackground::doKeyboardEvent(te);
  1280. te.processed = processed;
  1281. if (dom)
  1282. {
  1283. for (auto i = dom->getChilds(); i; i++)
  1284. { // TODO render elements backwards
  1285. Drawable* z = members->z(i->getAttributeValue("id"),
  1286. i->getAttributeValue("id").getLength());
  1287. if (z) z->doKeyboardEvent(te);
  1288. }
  1289. }
  1290. }
  1291. // Updates the drawing background
  1292. // tickVal: The elapsed time in seconds since the last call of this
  1293. // function return: 1 if the image needs to be redrawn.
  1294. // 0 otherwise
  1295. bool UIMLView::tick(double tickVal)
  1296. {
  1297. if (dom)
  1298. {
  1299. for (auto i = dom->getChilds(); i; i++)
  1300. { // TODO render elements backwards
  1301. Drawable* z = members->z(i->getAttributeValue("id"),
  1302. i->getAttributeValue("id").getLength());
  1303. if (z) rend |= z->tick(tickVal);
  1304. }
  1305. }
  1306. return DrawableBackground::tick(tickVal);
  1307. }
  1308. // Draws the background of a drawing to rObj
  1309. void UIMLView::render(Image& rObj)
  1310. {
  1311. if (hasStyle(Drawable::Style::Visible))
  1312. {
  1313. DrawableBackground::render(rObj);
  1314. if (dom)
  1315. {
  1316. if (!rObj.setDrawOptions(pos.x + getBorderWidth(),
  1317. pos.y + getBorderWidth(),
  1318. gr.x + getBorderWidth() * 2,
  1319. gr.y + getBorderWidth() * 2))
  1320. return;
  1321. bool vSc = hasStyle(Style::VScroll) && vertikalScrollBar;
  1322. bool hSc = hasStyle(Style::HScroll) && horizontalScrollBar;
  1323. rObj.addScrollOffset(hSc ? horizontalScrollBar->getScroll() : 0,
  1324. vSc ? vertikalScrollBar->getScroll() : 0);
  1325. for (int i = dom->getChildCount() - 1; i >= 0; i--)
  1326. { // TODO render elements backwards
  1327. XML::Element* e = dom->zChild(i);
  1328. Drawable* z = members->z(e->getAttributeValue("id"),
  1329. e->getAttributeValue("id").getLength());
  1330. if (z) z->render(rObj);
  1331. }
  1332. rObj.releaseDrawOptions();
  1333. }
  1334. }
  1335. }
  1336. // Returns the DOM tree without increased reference counter
  1337. // Changes to the DOM tree should be avoided (only changes to
  1338. // attributes of individual elements are allowed)
  1339. XML::Element* UIMLView::zDom() const
  1340. {
  1341. return dom;
  1342. }
  1343. // Returns the DOM tree
  1344. // Changes to the DOM tree should be avoided (only changes to
  1345. // attributes of individual elements are allowed)
  1346. XML::Element* UIMLView::getDom() const
  1347. {
  1348. return dom ? dynamic_cast<XML::Element*>(dom->getThis()) : 0;
  1349. }
  1350. bool UIMLView::isApplicableFor(XML::Element& element)
  1351. {
  1352. for (UIMLElement* e : knownElements)
  1353. {
  1354. if (e->isApplicableFor(element)) return 1;
  1355. }
  1356. return 0;
  1357. }
  1358. Drawable* UIMLView::parseElement(
  1359. XML::Element& element, UIMLContainer& generalFactory)
  1360. {
  1361. Text id;
  1362. if (element.hasAttribute("id"))
  1363. id = element.getAttributeValue("id");
  1364. else
  1365. {
  1366. id = Text("_") += nextId++;
  1367. element.setAttribute("id", id);
  1368. }
  1369. Drawable* z = members->z(id, id.getLength());
  1370. if (!z)
  1371. {
  1372. // precompute attributes
  1373. if (element.hasAttribute("margin"))
  1374. {
  1375. Text m = element.getAttributeValue("margin");
  1376. if (!element.hasAttribute("margin-left"))
  1377. element.setAttribute("margin-left", m);
  1378. if (!element.hasAttribute("margin-top"))
  1379. element.setAttribute("margin-top", m);
  1380. if (!element.hasAttribute("margin-right"))
  1381. element.setAttribute("margin-right", m);
  1382. if (!element.hasAttribute("margin-bottom"))
  1383. element.setAttribute("margin-bottom", m);
  1384. }
  1385. if (element.hasAttribute("class"))
  1386. {
  1387. Text c = element.getAttributeValue("class");
  1388. while (1)
  1389. {
  1390. Text* t;
  1391. if (c.has(","))
  1392. t = c.getTeilText(0, c.positionOf(','));
  1393. else
  1394. t = new Text(c);
  1395. XML::Editor ce
  1396. = dom->selectChildsByName("class").whereAttributeEquals(
  1397. "id", *t);
  1398. for (auto i = ce.begin(); i; i++)
  1399. {
  1400. for (auto j = i->getAttributeNames(),
  1401. k = i->getAttributeValues();
  1402. j && k;
  1403. j++, k++)
  1404. {
  1405. if (!element.hasAttribute(j->getText()))
  1406. element.setAttribute(j->getText(), i->getText());
  1407. }
  1408. }
  1409. t->release();
  1410. if (c.has(","))
  1411. c.remove(0, c.positionOf(',' + 1));
  1412. else
  1413. break;
  1414. }
  1415. }
  1416. if (element.hasAttribute("text-align"))
  1417. {
  1418. if (!element.hasAttribute("text-align-horizontal"))
  1419. element.setAttribute("text-align-horizontal",
  1420. element.getAttributeValue("text-align"));
  1421. if (!element.hasAttribute("text-align-vertical"))
  1422. element.setAttribute("text-align-vertical",
  1423. element.getAttributeValue("text-align"));
  1424. }
  1425. // create objects
  1426. for (UIMLElement* e : knownElements)
  1427. {
  1428. if (e->isApplicableFor(element))
  1429. {
  1430. z = e->parseElement(element, *this);
  1431. break;
  1432. }
  1433. }
  1434. if (z)
  1435. {
  1436. if (hasStyle(Style::GlobalMouseEvent))
  1437. {
  1438. z->addMouseEvent([this, z](void* p, void* o, MouseEvent me) {
  1439. return dom->selectChildren()
  1440. .selectAllElements()
  1441. .whereAttributeEquals("id", getDrawableId(*z))
  1442. .getFirstElement()
  1443. .map<bool>(
  1444. [this, &me, z](RCPointer<XML::Element> element) {
  1445. return onMemberMouseEvent
  1446. ? onMemberMouseEvent(*element, *z, me)
  1447. : 0;
  1448. })
  1449. .orElse(0);
  1450. });
  1451. }
  1452. if (hasStyle(Style::GlobalTastaturEvent))
  1453. {
  1454. z->addKeyboardEvent([this, z](
  1455. void* p, void* o, KeyboardEvent te) {
  1456. return dom->selectChildren()
  1457. .selectAllElements()
  1458. .whereAttributeEquals("id", getDrawableId(*z))
  1459. .getFirstElement()
  1460. .map<bool>([this, &te, z](
  1461. RCPointer<XML::Element> element) {
  1462. return onMemberKeyboardEvent
  1463. ? onMemberKeyboardEvent(*element, *z, te)
  1464. : 0;
  1465. })
  1466. .orElse(0);
  1467. });
  1468. }
  1469. members->set(
  1470. id, id.getLength(), dynamic_cast<Drawable*>(z->getThis()));
  1471. idList.add(new Text(id));
  1472. memberList.add(z);
  1473. }
  1474. }
  1475. else
  1476. z->getThis();
  1477. return z;
  1478. }
  1479. bool Framework::UIMLView::updateElement(
  1480. XML::Element& element, Drawable& z, UIMLContainer& generalFactory)
  1481. {
  1482. bool result = 0;
  1483. for (UIMLElement* e : knownElements)
  1484. {
  1485. if (e->isApplicableFor(element))
  1486. {
  1487. result = e->updateElement(element, z, *this);
  1488. break;
  1489. }
  1490. }
  1491. if (!result)
  1492. {
  1493. for (XML::Element* element :
  1494. element.selectChildren().selectAllElements().whereAttributeExists(
  1495. "id"))
  1496. { // element could not be updated so all children will be removed
  1497. Framework::Text id = element->getAttributeValue("id");
  1498. Drawable* z = zDrawableById(id);
  1499. if (z) removeDrawable(*z);
  1500. }
  1501. removeDrawable(z);
  1502. }
  1503. return result;
  1504. }
  1505. void UIMLView::layout(XML::Element& element,
  1506. Drawable& z,
  1507. int pWidth,
  1508. int pHeight,
  1509. UIMLContainer& generalLayouter)
  1510. {
  1511. for (UIMLElement* e : knownElements)
  1512. {
  1513. if (e->isApplicableFor(element))
  1514. {
  1515. e->layout(element, z, pWidth, pHeight, *this);
  1516. break;
  1517. }
  1518. }
  1519. }
  1520. Text Framework::UIMLView::getDrawableId(Drawable& z)
  1521. {
  1522. int index = memberList.getValueIndex(&z);
  1523. if (index >= 0) return *idList.z(index);
  1524. return "";
  1525. }
  1526. void Framework::UIMLView::removeDrawable(Drawable& z)
  1527. {
  1528. int index = memberList.getValueIndex(&z);
  1529. if (index >= 0)
  1530. {
  1531. Text id = *idList.z(index);
  1532. idList.remove(index);
  1533. memberList.remove(index);
  1534. members->remove(id, id.getLength());
  1535. }
  1536. }
  1537. bool Framework::UIMLView::registerDrawable(const char* id, Drawable* z)
  1538. {
  1539. Drawable* existing = members->z(id, textLength(id));
  1540. if (existing)
  1541. {
  1542. z->release();
  1543. return 0;
  1544. }
  1545. members->set(id, textLength(id), z);
  1546. return 1;
  1547. }
  1548. const UIInit& UIMLView::getFactory()
  1549. {
  1550. return init;
  1551. }
  1552. //! calculates the needed size for all content elements to be visible
  1553. Point UIMLView::calculateContentSize()
  1554. {
  1555. Point maxP(0, 0);
  1556. for (int i = dom->getChildCount() - 1; i >= 0; i--)
  1557. { // TODO render elements backwards
  1558. XML::Element* e = dom->zChild(i);
  1559. Drawable* z = members->z(
  1560. e->getAttributeValue("id"), e->getAttributeValue("id").getLength());
  1561. if (z)
  1562. {
  1563. maxP.x = MAX(maxP.x, z->getPosition().x + z->getWidth());
  1564. maxP.y = MAX(maxP.y, z->getPosition().y + z->getHeight());
  1565. }
  1566. }
  1567. maxP.x += 2 * getBorderWidth();
  1568. maxP.y += 2 * getBorderWidth();
  1569. return maxP;
  1570. }