The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

764 lines
26KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-7 by Raw Material Software ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the
  7. GNU General Public License, as published by the Free Software Foundation;
  8. either version 2 of the License, or (at your option) any later version.
  9. JUCE is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with JUCE; if not, visit www.gnu.org/licenses or write to the
  15. Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  16. Boston, MA 02111-1307 USA
  17. ------------------------------------------------------------------------------
  18. If you'd like to release a closed-source product which uses JUCE, commercial
  19. licenses are also available: visit www.rawmaterialsoftware.com/juce for
  20. more information.
  21. ==============================================================================
  22. */
  23. #include "../jucer_Headers.h"
  24. #include "../model/jucer_JucerDocument.h"
  25. //==============================================================================
  26. const String replaceCEscapeChars (const String& s)
  27. {
  28. const int len = s.length();
  29. String r;
  30. r.preallocateStorage (len + 2);
  31. bool lastWasHexEscapeCode = false;
  32. for (int i = 0; i < len; ++i)
  33. {
  34. const tchar c = s[i];
  35. switch (c)
  36. {
  37. case '\t':
  38. r << T("\\t");
  39. lastWasHexEscapeCode = false;
  40. break;
  41. case '\r':
  42. r << T("\\r");
  43. lastWasHexEscapeCode = false;
  44. break;
  45. case '\n':
  46. r << T("\\n");
  47. lastWasHexEscapeCode = false;
  48. break;
  49. case '\\':
  50. r << T("\\\\");
  51. lastWasHexEscapeCode = false;
  52. break;
  53. case '\'':
  54. r << T("\\\'");
  55. lastWasHexEscapeCode = false;
  56. break;
  57. case '\"':
  58. r << T("\\\"");
  59. lastWasHexEscapeCode = false;
  60. break;
  61. default:
  62. if (c < 128 &&
  63. ! (lastWasHexEscapeCode
  64. && String (T("0123456789abcdefABCDEF")).containsChar (c))) // (have to avoid following a hex escape sequence with a valid hex digit)
  65. {
  66. r << c;
  67. lastWasHexEscapeCode = false;
  68. }
  69. else
  70. {
  71. lastWasHexEscapeCode = true;
  72. r << T("\\x") << String::toHexString ((int) c);
  73. }
  74. break;
  75. }
  76. }
  77. return r;
  78. }
  79. const String quotedString (const String& s)
  80. {
  81. if (s.isEmpty())
  82. return T("String::empty");
  83. const int embeddedIndex = s.indexOfIgnoreCase (T("%%"));
  84. if (embeddedIndex >= 0)
  85. {
  86. String s1 (s.substring (0, embeddedIndex));
  87. String s2 (s.substring (embeddedIndex + 2));
  88. String code;
  89. const int closeIndex = s2.indexOf (T("%%"));
  90. if (closeIndex > 0)
  91. {
  92. code = s2.substring (0, closeIndex).trim();
  93. s2 = s2.substring (closeIndex + 2);
  94. }
  95. if (code.isNotEmpty())
  96. {
  97. String result;
  98. if (s1.isNotEmpty())
  99. result << quotedString (s1) << T(" + ");
  100. result << code;
  101. if (s2.isNotEmpty())
  102. result << T(" + ") << quotedString (s2);
  103. return result;
  104. }
  105. }
  106. return T("T(\"") + replaceCEscapeChars (s) + T("\")");
  107. }
  108. const String replaceStringTranslations (String s, JucerDocument* document)
  109. {
  110. s = s.replace (T("%%getName()%%"), document->getComponentName());
  111. s = s.replace (T("%%getButtonText()%%"), document->getComponentName());
  112. return s;
  113. }
  114. const String castToFloat (const String& expression)
  115. {
  116. if (expression.containsOnly (T("0123456789.f")))
  117. {
  118. String s (expression.getFloatValue());
  119. if (s.containsChar (T('.')))
  120. return s + T("f");
  121. return s + T(".0f");
  122. }
  123. return T("(float) (") + expression + T(")");
  124. }
  125. const String indentCode (const String& code, const int numSpaces)
  126. {
  127. if (numSpaces == 0)
  128. return code;
  129. const String space (String::repeatedString (T(" "), numSpaces));
  130. StringArray lines;
  131. lines.addLines (code);
  132. for (int i = 1; i < lines.size(); ++i)
  133. {
  134. String s (lines[i].trimEnd());
  135. if (s.isNotEmpty())
  136. s = space + s;
  137. lines.set (i, s);
  138. }
  139. return lines.joinIntoString (T("\n"));
  140. }
  141. //==============================================================================
  142. const String makeValidCppIdentifier (String s,
  143. const bool capitalise,
  144. const bool removeColons,
  145. const bool allowTemplates)
  146. {
  147. if (removeColons)
  148. s = s.replaceCharacters (T(".,;:/@"), T("______"));
  149. else
  150. s = s.replaceCharacters (T(".,;/@"), T("_____"));
  151. int i;
  152. for (i = s.length(); --i > 0;)
  153. if (CharacterFunctions::isLetter (s[i])
  154. && CharacterFunctions::isLetter (s[i - 1])
  155. && CharacterFunctions::isUpperCase (s[i])
  156. && ! CharacterFunctions::isUpperCase (s[i - 1]))
  157. s = s.substring (0, i) + T(" ") + s.substring (i);
  158. String allowedChars (T("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_ 0123456789"));
  159. if (allowTemplates)
  160. allowedChars += T("<>");
  161. if (! removeColons)
  162. allowedChars += T(":");
  163. StringArray words;
  164. words.addTokens (s.retainCharacters (allowedChars), false);
  165. words.trim();
  166. String n (words[0]);
  167. if (capitalise)
  168. n = n.toLowerCase();
  169. for (i = 1; i < words.size(); ++i)
  170. {
  171. if (capitalise && words[i].length() > 1)
  172. n << words[i].substring (0, 1).toUpperCase()
  173. << words[i].substring (1).toLowerCase();
  174. else
  175. n << words[i];
  176. }
  177. // make sure it's not a reserved c++ keyword..
  178. static const tchar* const reservedWords[] =
  179. {
  180. T("auto"), T("const"), T("double"), T("float"), T("int"), T("short"), T("struct"),
  181. T("return"), T("static"), T("union"), T("while"), T("asm"), T("dynamic_cast"),
  182. T("unsigned"), T("break"), T("continue"), T("else"), T("for"), T("long"), T("signed"),
  183. T("switch"), T("void"), T("case"), T("default"), T("enum"), T("goto"), T("register"),
  184. T("sizeof"), T("typedef"), T("volatile"), T("char"), T("do"), T("extern"), T("if"),
  185. T("namespace"), T("reinterpret_cast"), T("try"), T("bool"), T("explicit"), T("new"),
  186. T("static_cast"), T("typeid"), T("catch"), T("false"), T("operator"), T("template"),
  187. T("typename"), T("class"), T("friend"), T("private"), T("this"), T("using"), T("const_cast"),
  188. T("inline"), T("public"), T("throw"), T("virtual"), T("delete"), T("mutable"), T("protected"),
  189. T("true"), T("wchar_t"), T("and"), T("bitand"), T("compl"), T("not_eq"), T("or_eq"),
  190. T("xor_eq"), T("and_eq"), T("bitor"), T("not"), T("or"), T("xor"), T("cin"), T("endl"),
  191. T("INT_MIN"), T("iomanip"), T("main"), T("npos"), T("std"), T("cout"), T("include"),
  192. T("INT_MAX"), T("iostream"), T("MAX_RAND"), T("NULL"), T("string")
  193. };
  194. for (i = 0; i < numElementsInArray (reservedWords); ++i)
  195. if (n == reservedWords[i])
  196. n << '_';
  197. return n;
  198. }
  199. //==============================================================================
  200. int indexOfLineStartingWith (const StringArray& lines, const String& text, int startIndex)
  201. {
  202. startIndex = jmax (0, startIndex);
  203. while (startIndex < lines.size())
  204. {
  205. if (lines[startIndex].trimStart().startsWithIgnoreCase (text))
  206. return startIndex;
  207. ++startIndex;
  208. }
  209. return -1;
  210. }
  211. //==============================================================================
  212. const String valueToFloat (const double v)
  213. {
  214. String s ((double) (float) v, 4);
  215. if (s.containsChar (T('.')))
  216. s << 'f';
  217. else
  218. s << ".0f";
  219. return s;
  220. }
  221. const String boolToString (const bool b)
  222. {
  223. return b ? T("true") : T("false");
  224. }
  225. //==============================================================================
  226. const String colourToHex (const Colour& col)
  227. {
  228. return String::toHexString ((int) col.getARGB());
  229. }
  230. //==============================================================================
  231. const String colourToCode (const Colour& col)
  232. {
  233. #define COL(col) Colours::col,
  234. const Colour colours[] =
  235. {
  236. #include "jucer_Colours.h"
  237. Colours::transparentBlack
  238. };
  239. #undef COL
  240. #define COL(col) #col,
  241. static const char* colourNames[] =
  242. {
  243. #include "jucer_Colours.h"
  244. 0
  245. };
  246. #undef COL
  247. for (int i = 0; i < numElementsInArray (colourNames) - 1; ++i)
  248. if (col == colours[i])
  249. return T("Colours::") + String (colourNames[i]);
  250. return T("Colour (0x") + colourToHex (col) + T(')');
  251. }
  252. void setColourXml (XmlElement& xml, const tchar* const attName, const Colour& colour)
  253. {
  254. xml.setAttribute (attName, colourToHex (colour));
  255. }
  256. const Colour getColourXml (const XmlElement& xml, const tchar* const attName, const Colour& defaultColour)
  257. {
  258. return Colour (xml.getStringAttribute (attName, colourToHex (defaultColour)).getHexValue32());
  259. }
  260. //==============================================================================
  261. const String positionToString (const RelativePositionedRectangle& pos)
  262. {
  263. StringArray toks;
  264. toks.addTokens (pos.rect.toString(), false);
  265. return toks[0] + T(" ") + toks[1];
  266. }
  267. void positionToXY (const RelativePositionedRectangle& position,
  268. double& x, double& y,
  269. const Rectangle& parentArea,
  270. const ComponentLayout* layout)
  271. {
  272. double w, h;
  273. position.getRectangleDouble (x, y, w, h, parentArea, layout);
  274. }
  275. void positionToCode (const RelativePositionedRectangle& position,
  276. const ComponentLayout* layout,
  277. String& x, String& y, String& w, String& h)
  278. {
  279. // these are the code sections for the positions of the relative comps
  280. String xrx, xry, xrw, xrh;
  281. Component* const relCompX = layout != 0 ? layout->findComponentWithId (position.relativeToX) : 0;
  282. if (relCompX != 0)
  283. positionToCode (ComponentTypeHandler::getComponentPosition (relCompX), layout, xrx, xry, xrw, xrh);
  284. String yrx, yry, yrw, yrh;
  285. Component* const relCompY = layout != 0 ? layout->findComponentWithId (position.relativeToY) : 0;
  286. if (relCompY != 0)
  287. positionToCode (ComponentTypeHandler::getComponentPosition (relCompY), layout, yrx, yry, yrw, yrh);
  288. String wrx, wry, wrw, wrh;
  289. Component* const relCompW = (layout != 0 && position.rect.getWidthMode() != PositionedRectangle::absoluteSize)
  290. ? layout->findComponentWithId (position.relativeToW) : 0;
  291. if (relCompW != 0)
  292. positionToCode (ComponentTypeHandler::getComponentPosition (relCompW), layout, wrx, wry, wrw, wrh);
  293. String hrx, hry, hrw, hrh;
  294. Component* const relCompH = (layout != 0 && position.rect.getHeightMode() != PositionedRectangle::absoluteSize)
  295. ? layout->findComponentWithId (position.relativeToH) : 0;
  296. if (relCompH != 0)
  297. positionToCode (ComponentTypeHandler::getComponentPosition (relCompH), layout, hrx, hry, hrw, hrh);
  298. // width
  299. if (position.rect.getWidthMode() == PositionedRectangle::proportionalSize)
  300. {
  301. if (wrw.isNotEmpty())
  302. w << "roundFloatToInt ((" << wrw << ") * " << valueToFloat (position.rect.getWidth()) << ")";
  303. else
  304. w << "proportionOfWidth (" << valueToFloat (position.rect.getWidth()) << ")";
  305. }
  306. else if (position.rect.getWidthMode() == PositionedRectangle::parentSizeMinusAbsolute)
  307. {
  308. if (wrw.isNotEmpty())
  309. w << "(" << wrw << ") - " << roundDoubleToInt (position.rect.getWidth());
  310. else
  311. w << "getWidth() - " << roundDoubleToInt (position.rect.getWidth());
  312. }
  313. else
  314. {
  315. if (wrw.isNotEmpty())
  316. w << "(" << wrw << ") + ";
  317. w << roundDoubleToInt (position.rect.getWidth());
  318. }
  319. // height
  320. if (position.rect.getHeightMode() == PositionedRectangle::proportionalSize)
  321. {
  322. if (hrh.isNotEmpty())
  323. h << "roundFloatToInt ((" << hrh << ") * " << valueToFloat (position.rect.getHeight()) << ")";
  324. else
  325. h << "proportionOfHeight (" << valueToFloat (position.rect.getHeight()) << ")";
  326. }
  327. else if (position.rect.getHeightMode() == PositionedRectangle::parentSizeMinusAbsolute)
  328. {
  329. if (hrh.isNotEmpty())
  330. h << "(" << hrh << ") - " << roundDoubleToInt (position.rect.getHeight());
  331. else
  332. h << "getHeight() - " << roundDoubleToInt (position.rect.getHeight());
  333. }
  334. else
  335. {
  336. if (hrh.isNotEmpty())
  337. h << "(" << hrh << ") + ";
  338. h << roundDoubleToInt (position.rect.getHeight());
  339. }
  340. // x-pos
  341. if (position.rect.getPositionModeX() == PositionedRectangle::proportionOfParentSize)
  342. {
  343. if (xrx.isNotEmpty() && xrw.isNotEmpty())
  344. x << "(" << xrx << ") + roundFloatToInt ((" << xrw << ") * " << valueToFloat (position.rect.getX()) << ")";
  345. else
  346. x << "proportionOfWidth (" << valueToFloat (position.rect.getX()) << ")";
  347. }
  348. else if (position.rect.getPositionModeX() == PositionedRectangle::absoluteFromParentTopLeft)
  349. {
  350. if (xrx.isNotEmpty())
  351. x << "(" << xrx << ") + ";
  352. x << roundDoubleToInt (position.rect.getX());
  353. }
  354. else if (position.rect.getPositionModeX() == PositionedRectangle::absoluteFromParentBottomRight)
  355. {
  356. if (xrx.isNotEmpty())
  357. x << "(" << xrx << ") + (" << xrw << ")";
  358. else
  359. x << "getWidth()";
  360. const int d = roundDoubleToInt (position.rect.getX());
  361. if (d != 0)
  362. x << " - " << d;
  363. }
  364. else if (position.rect.getPositionModeX() == PositionedRectangle::absoluteFromParentCentre)
  365. {
  366. if (xrx.isNotEmpty())
  367. x << "(" << xrx << ") + (" << xrw << ") / 2";
  368. else
  369. x << "(getWidth() / 2)";
  370. const int d = roundDoubleToInt (position.rect.getX());
  371. if (d != 0)
  372. x << " + " << d;
  373. }
  374. if (w != T("0"))
  375. {
  376. if (position.rect.getAnchorPointX() == PositionedRectangle::anchorAtRightOrBottom)
  377. x << " - " << w;
  378. else if (position.rect.getAnchorPointX() == PositionedRectangle::anchorAtCentre)
  379. x << " - ((" << w << ") / 2)";
  380. }
  381. // y-pos
  382. if (position.rect.getPositionModeY() == PositionedRectangle::proportionOfParentSize)
  383. {
  384. if (yry.isNotEmpty() && yrh.isNotEmpty())
  385. y << "(" << yry << ") + roundFloatToInt ((" << yrh << ") * " << valueToFloat (position.rect.getY()) << ")";
  386. else
  387. y << "proportionOfHeight (" << valueToFloat (position.rect.getY()) << ")";
  388. }
  389. else if (position.rect.getPositionModeY() == PositionedRectangle::absoluteFromParentTopLeft)
  390. {
  391. if (yry.isNotEmpty())
  392. y << "(" << yry << ") + ";
  393. y << roundDoubleToInt (position.rect.getY());
  394. }
  395. else if (position.rect.getPositionModeY() == PositionedRectangle::absoluteFromParentBottomRight)
  396. {
  397. if (yry.isNotEmpty())
  398. y << "(" << yry << ") + (" << yrh << ")";
  399. else
  400. y << "getHeight()";
  401. const int d = roundDoubleToInt (position.rect.getY());
  402. if (d != 0)
  403. y << " - " << d;
  404. }
  405. else if (position.rect.getPositionModeY() == PositionedRectangle::absoluteFromParentCentre)
  406. {
  407. if (yry.isNotEmpty())
  408. y << "(" << yry << ") + (" << yrh << ") / 2";
  409. else
  410. y << "(getHeight() / 2)";
  411. const int d = roundDoubleToInt (position.rect.getY());
  412. if (d != 0)
  413. y << " + " << d;
  414. }
  415. if (h != T("0"))
  416. {
  417. if (position.rect.getAnchorPointY() == PositionedRectangle::anchorAtRightOrBottom)
  418. y << " - " << h;
  419. else if (position.rect.getAnchorPointY() == PositionedRectangle::anchorAtCentre)
  420. y << " - ((" << h << ") / 2)";
  421. }
  422. }
  423. const String justificationToCode (const Justification& justification)
  424. {
  425. switch (justification.getFlags())
  426. {
  427. case Justification::centred:
  428. return "Justification::centred";
  429. case Justification::centredLeft:
  430. return "Justification::centredLeft";
  431. case Justification::centredRight:
  432. return "Justification::centredRight";
  433. case Justification::centredTop:
  434. return "Justification::centredTop";
  435. case Justification::centredBottom:
  436. return "Justification::centredBottom";
  437. case Justification::topLeft:
  438. return "Justification::topLeft";
  439. case Justification::topRight:
  440. return "Justification::topRight";
  441. case Justification::bottomLeft:
  442. return "Justification::bottomLeft";
  443. case Justification::bottomRight:
  444. return "Justification::bottomRight";
  445. case Justification::left:
  446. return "Justification::left";
  447. case Justification::right:
  448. return "Justification::right";
  449. case Justification::horizontallyCentred:
  450. return "Justification::horizontallyCentred";
  451. case Justification::top:
  452. return "Justification::top";
  453. case Justification::bottom:
  454. return "Justification::bottom";
  455. case Justification::verticallyCentred:
  456. return "Justification::verticallyCentred";
  457. case Justification::horizontallyJustified:
  458. return "Justification::horizontallyJustified";
  459. default:
  460. jassertfalse
  461. break;
  462. }
  463. return T("Justification (") + String (justification.getFlags()) + T(")");
  464. }
  465. //==============================================================================
  466. void drawResizableBorder (Graphics& g,
  467. int w, int h,
  468. const BorderSize borderSize,
  469. const bool isMouseOver)
  470. {
  471. g.setColour (Colours::orange.withAlpha (isMouseOver ? 0.4f : 0.3f));
  472. g.fillRect (0, 0, w, borderSize.getTop());
  473. g.fillRect (0, 0, borderSize.getLeft(), h);
  474. g.fillRect (0, h - borderSize.getBottom(), w, borderSize.getBottom());
  475. g.fillRect (w - borderSize.getRight(), 0, borderSize.getRight(), h);
  476. g.drawRect (borderSize.getLeft() - 1, borderSize.getTop() - 1,
  477. w - borderSize.getRight() - borderSize.getLeft() + 2,
  478. h - borderSize.getTop() - borderSize.getBottom() + 2);
  479. }
  480. void drawMouseOverCorners (Graphics& g, int w, int h)
  481. {
  482. RectangleList r (Rectangle (0, 0, w, h));
  483. r.subtract (Rectangle (1, 1, w - 2, h - 2));
  484. const int size = jmin (w / 3, h / 3, 12);
  485. r.subtract (Rectangle (size, 0, w - size - size, h));
  486. r.subtract (Rectangle (0, size, w, h - size - size));
  487. g.setColour (Colours::darkgrey);
  488. for (int i = r.getNumRectangles(); --i >= 0;)
  489. g.fillRect (r.getRectangle (i));
  490. }
  491. //==============================================================================
  492. RelativePositionedRectangle::RelativePositionedRectangle()
  493. : relativeToX (0),
  494. relativeToY (0),
  495. relativeToW (0),
  496. relativeToH (0)
  497. {
  498. }
  499. RelativePositionedRectangle::RelativePositionedRectangle (const RelativePositionedRectangle& other)
  500. : rect (other.rect),
  501. relativeToX (other.relativeToX),
  502. relativeToY (other.relativeToY),
  503. relativeToW (other.relativeToW),
  504. relativeToH (other.relativeToH)
  505. {
  506. }
  507. const RelativePositionedRectangle& RelativePositionedRectangle::operator= (const RelativePositionedRectangle& other)
  508. {
  509. rect = other.rect;
  510. relativeToX = other.relativeToX;
  511. relativeToY = other.relativeToY;
  512. relativeToW = other.relativeToW;
  513. relativeToH = other.relativeToH;
  514. return *this;
  515. }
  516. RelativePositionedRectangle::~RelativePositionedRectangle()
  517. {
  518. }
  519. //==============================================================================
  520. bool RelativePositionedRectangle::operator== (const RelativePositionedRectangle& other) const throw()
  521. {
  522. return rect == other.rect
  523. && relativeToX == other.relativeToX
  524. && relativeToY == other.relativeToY
  525. && relativeToW == other.relativeToW
  526. && relativeToH == other.relativeToH;
  527. }
  528. bool RelativePositionedRectangle::operator!= (const RelativePositionedRectangle& other) const throw()
  529. {
  530. return ! operator== (other);
  531. }
  532. void RelativePositionedRectangle::getRelativeTargetBounds (const Rectangle& parentArea,
  533. const ComponentLayout* layout,
  534. int& x, int& xw, int& y, int& yh,
  535. int& w, int& h) const
  536. {
  537. Component* rx = 0;
  538. Component* ry = 0;
  539. Component* rw = 0;
  540. Component* rh = 0;
  541. if (layout != 0)
  542. {
  543. rx = layout->findComponentWithId (relativeToX);
  544. ry = layout->findComponentWithId (relativeToY);
  545. rw = layout->findComponentWithId (relativeToW);
  546. rh = layout->findComponentWithId (relativeToH);
  547. }
  548. x = parentArea.getX() + (rx != 0 ? rx->getX() : 0);
  549. y = parentArea.getY() + (ry != 0 ? ry->getY() : 0);
  550. w = rw != 0 ? rw->getWidth() : parentArea.getWidth();
  551. h = rh != 0 ? rh->getHeight() : parentArea.getHeight();
  552. xw = rx != 0 ? rx->getWidth() : parentArea.getWidth();
  553. yh = ry != 0 ? ry->getHeight() : parentArea.getHeight();
  554. }
  555. const Rectangle RelativePositionedRectangle::getRectangle (const Rectangle& parentArea,
  556. const ComponentLayout* layout) const
  557. {
  558. int x, xw, y, yh, w, h;
  559. getRelativeTargetBounds (parentArea, layout, x, xw, y, yh, w, h);
  560. const Rectangle xyRect ((xw <= 0 || yh <= 0) ? Rectangle()
  561. : rect.getRectangle (Rectangle (x, y, xw, yh)));
  562. const Rectangle whRect ((w <= 0 || h <= 0) ? Rectangle()
  563. : rect.getRectangle (Rectangle (x, y, w, h)));
  564. return Rectangle (xyRect.getX(), xyRect.getY(),
  565. whRect.getWidth(), whRect.getHeight());
  566. }
  567. void RelativePositionedRectangle::getRectangleDouble (double& x, double& y, double& w, double& h,
  568. const Rectangle& parentArea,
  569. const ComponentLayout* layout) const
  570. {
  571. int rx, rxw, ry, ryh, rw, rh;
  572. getRelativeTargetBounds (parentArea, layout, rx, rxw, ry, ryh, rw, rh);
  573. double dummy1, dummy2;
  574. rect.getRectangleDouble (Rectangle (rx, ry, rxw, ryh), x, y, dummy1, dummy2);
  575. rect.getRectangleDouble (Rectangle (rx, ry, rw, rh), dummy1, dummy2, w, h);
  576. }
  577. void RelativePositionedRectangle::updateFromComponent (const Component& comp,
  578. const ComponentLayout* layout)
  579. {
  580. int x, xw, y, yh, w, h;
  581. getRelativeTargetBounds (Rectangle (0, 0, comp.getParentWidth(), comp.getParentHeight()),
  582. layout, x, xw, y, yh, w, h);
  583. PositionedRectangle xyRect (rect), whRect (rect);
  584. xyRect.updateFrom (comp.getBounds(), Rectangle (x, y, xw, yh));
  585. whRect.updateFrom (comp.getBounds(), Rectangle (x, y, w, h));
  586. rect.setX (xyRect.getX());
  587. rect.setY (xyRect.getY());
  588. rect.setWidth (whRect.getWidth());
  589. rect.setHeight (whRect.getHeight());
  590. }
  591. void RelativePositionedRectangle::updateFrom (double newX, double newY, double newW, double newH,
  592. const Rectangle& parentArea, const ComponentLayout* layout)
  593. {
  594. int x, xw, y, yh, w, h;
  595. getRelativeTargetBounds (parentArea, layout, x, xw, y, yh, w, h);
  596. PositionedRectangle xyRect (rect), whRect (rect);
  597. xyRect.updateFromDouble (newX, newY, newW, newH, Rectangle (x, y, xw, yh));
  598. whRect.updateFromDouble (newX, newY, newW, newH, Rectangle (x, y, w, h));
  599. rect.setX (xyRect.getX());
  600. rect.setY (xyRect.getY());
  601. rect.setWidth (whRect.getWidth());
  602. rect.setHeight (whRect.getHeight());
  603. }
  604. void RelativePositionedRectangle::applyToXml (XmlElement& e) const
  605. {
  606. e.setAttribute (T("pos"), rect.toString());
  607. if (relativeToX != 0)
  608. e.setAttribute (T("posRelativeX"), String::toHexString (relativeToX));
  609. if (relativeToY != 0)
  610. e.setAttribute (T("posRelativeY"), String::toHexString (relativeToY));
  611. if (relativeToW != 0)
  612. e.setAttribute (T("posRelativeW"), String::toHexString (relativeToW));
  613. if (relativeToH != 0)
  614. e.setAttribute (T("posRelativeH"), String::toHexString (relativeToH));
  615. }
  616. void RelativePositionedRectangle::restoreFromXml (const XmlElement& e,
  617. const RelativePositionedRectangle& defaultPos)
  618. {
  619. rect = PositionedRectangle (e.getStringAttribute (T("pos"), defaultPos.rect.toString()));
  620. relativeToX = e.getStringAttribute (T("posRelativeX"), String::toHexString (defaultPos.relativeToX)).getHexValue64();
  621. relativeToY = e.getStringAttribute (T("posRelativeY"), String::toHexString (defaultPos.relativeToY)).getHexValue64();
  622. relativeToW = e.getStringAttribute (T("posRelativeW"), String::toHexString (defaultPos.relativeToW)).getHexValue64();
  623. relativeToH = e.getStringAttribute (T("posRelativeH"), String::toHexString (defaultPos.relativeToH)).getHexValue64();
  624. }