tb_layout.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605
  1. // ================================================================================
  2. // == This file is a part of Turbo Badger. (C) 2011-2014, Emil Segerås ==
  3. // == See tb_core.h for more information. ==
  4. // ================================================================================
  5. #include "tb_layout.h"
  6. #include "tb_system.h"
  7. #include "tb_skin_util.h"
  8. #include <assert.h>
  9. namespace tb {
  10. // == TBLayout ==========================================================================
  11. TBLayout::TBLayout(AXIS axis)
  12. : m_axis(axis)
  13. , m_spacing(SPACING_FROM_SKIN)
  14. , m_overflow(0)
  15. , m_overflow_scroll(0)
  16. , m_packed_init(0)
  17. {
  18. m_packed.layout_mode_size = LAYOUT_SIZE_GRAVITY;
  19. m_packed.layout_mode_pos = LAYOUT_POSITION_CENTER;
  20. m_packed.layout_mode_overflow = LAYOUT_OVERFLOW_CLIP;
  21. m_packed.layout_mode_dist = LAYOUT_DISTRIBUTION_PREFERRED;
  22. m_packed.layout_mode_dist_pos = LAYOUT_DISTRIBUTION_POSITION_CENTER;
  23. m_packed.paint_overflow_fadeout = 1;
  24. }
  25. void TBLayout::SetAxis(AXIS axis)
  26. {
  27. if (axis == m_axis)
  28. return;
  29. m_axis = axis;
  30. InvalidateLayout(INVALIDATE_LAYOUT_RECURSIVE);
  31. InvalidateSkinStates();
  32. }
  33. void TBLayout::SetSpacing(int spacing)
  34. {
  35. if (spacing == m_spacing)
  36. return;
  37. m_spacing = spacing;
  38. InvalidateLayout(INVALIDATE_LAYOUT_RECURSIVE);
  39. }
  40. void TBLayout::SetOverflowScroll(int overflow_scroll)
  41. {
  42. overflow_scroll = MIN(overflow_scroll, m_overflow);
  43. overflow_scroll = MAX(overflow_scroll, 0);
  44. if (overflow_scroll == m_overflow_scroll)
  45. return;
  46. m_overflow_scroll = overflow_scroll;
  47. Invalidate();
  48. if (m_axis == AXIS_X)
  49. OnScroll(m_overflow_scroll, 0);
  50. else
  51. OnScroll(0, m_overflow_scroll);
  52. }
  53. void TBLayout::SetLayoutSize(LAYOUT_SIZE size)
  54. {
  55. if (size == m_packed.layout_mode_size)
  56. return;
  57. m_packed.layout_mode_size = size;
  58. InvalidateLayout(INVALIDATE_LAYOUT_TARGET_ONLY);
  59. }
  60. void TBLayout::SetLayoutPosition(LAYOUT_POSITION pos)
  61. {
  62. if (pos == m_packed.layout_mode_pos)
  63. return;
  64. m_packed.layout_mode_pos = pos;
  65. InvalidateLayout(INVALIDATE_LAYOUT_TARGET_ONLY);
  66. }
  67. void TBLayout::SetLayoutOverflow(LAYOUT_OVERFLOW overflow)
  68. {
  69. if (overflow == m_packed.layout_mode_overflow)
  70. return;
  71. m_packed.layout_mode_overflow = overflow;
  72. InvalidateLayout(INVALIDATE_LAYOUT_TARGET_ONLY);
  73. }
  74. void TBLayout::SetLayoutDistribution(LAYOUT_DISTRIBUTION distribution)
  75. {
  76. if (distribution == m_packed.layout_mode_dist)
  77. return;
  78. m_packed.layout_mode_dist = distribution;
  79. InvalidateLayout(INVALIDATE_LAYOUT_TARGET_ONLY);
  80. }
  81. void TBLayout::SetLayoutDistributionPosition(LAYOUT_DISTRIBUTION_POSITION distribution_pos)
  82. {
  83. if (distribution_pos == m_packed.layout_mode_dist_pos)
  84. return;
  85. m_packed.layout_mode_dist_pos = distribution_pos;
  86. InvalidateLayout(INVALIDATE_LAYOUT_TARGET_ONLY);
  87. }
  88. void TBLayout::SetLayoutOrder(LAYOUT_ORDER order)
  89. {
  90. bool reversed = (order == LAYOUT_ORDER_TOP_TO_BOTTOM);
  91. if (reversed == m_packed.mode_reverse_order)
  92. return;
  93. m_packed.mode_reverse_order = reversed;
  94. InvalidateLayout(INVALIDATE_LAYOUT_TARGET_ONLY);
  95. }
  96. void TBLayout::InvalidateLayout(INVALIDATE_LAYOUT il)
  97. {
  98. m_packed.layout_is_invalid = 1;
  99. // Continue invalidating parents (depending on il)
  100. TBWidget::InvalidateLayout(il);
  101. }
  102. PreferredSize RotPreferredSize(const PreferredSize &ps, AXIS axis)
  103. {
  104. if (axis == AXIS_X)
  105. return ps;
  106. PreferredSize psr;
  107. psr.max_w = ps.max_h;
  108. psr.max_h = ps.max_w;
  109. psr.min_w = ps.min_h;
  110. psr.min_h = ps.min_w;
  111. psr.pref_w = ps.pref_h;
  112. psr.pref_h = ps.pref_w;
  113. psr.size_dependency =
  114. ((ps.size_dependency & SIZE_DEP_WIDTH_DEPEND_ON_HEIGHT) ?
  115. SIZE_DEP_HEIGHT_DEPEND_ON_WIDTH : SIZE_DEP_NONE) |
  116. ((ps.size_dependency & SIZE_DEP_HEIGHT_DEPEND_ON_WIDTH) ?
  117. SIZE_DEP_WIDTH_DEPEND_ON_HEIGHT : SIZE_DEP_NONE);
  118. return psr;
  119. }
  120. SizeConstraints RotSizeConstraints(const SizeConstraints &sc, AXIS axis)
  121. {
  122. return axis == AXIS_X ? sc : SizeConstraints(sc.available_h, sc.available_w);
  123. }
  124. TBRect RotRect(const TBRect &rect, AXIS axis)
  125. {
  126. if (axis == AXIS_X)
  127. return rect;
  128. return TBRect(rect.y, rect.x, rect.h, rect.w);
  129. }
  130. WIDGET_GRAVITY RotGravity(WIDGET_GRAVITY gravity, AXIS axis)
  131. {
  132. if (axis == AXIS_X)
  133. return gravity;
  134. WIDGET_GRAVITY r = WIDGET_GRAVITY_NONE;
  135. r |= (gravity & WIDGET_GRAVITY_LEFT) ? WIDGET_GRAVITY_TOP : WIDGET_GRAVITY_NONE;
  136. r |= (gravity & WIDGET_GRAVITY_TOP) ? WIDGET_GRAVITY_LEFT : WIDGET_GRAVITY_NONE;
  137. r |= (gravity & WIDGET_GRAVITY_RIGHT) ? WIDGET_GRAVITY_BOTTOM : WIDGET_GRAVITY_NONE;
  138. r |= (gravity & WIDGET_GRAVITY_BOTTOM) ? WIDGET_GRAVITY_RIGHT : WIDGET_GRAVITY_NONE;
  139. return r;
  140. }
  141. bool TBLayout::QualifyForExpansion(WIDGET_GRAVITY gravity) const
  142. {
  143. if (m_packed.layout_mode_dist == LAYOUT_DISTRIBUTION_AVAILABLE)
  144. return true;
  145. if (m_packed.layout_mode_dist == LAYOUT_DISTRIBUTION_GRAVITY &&
  146. ((gravity & WIDGET_GRAVITY_LEFT) && (gravity & WIDGET_GRAVITY_RIGHT)))
  147. return true;
  148. return false;
  149. }
  150. int TBLayout::GetWantedHeight(WIDGET_GRAVITY gravity, const PreferredSize &ps, int available_height) const
  151. {
  152. int height = 0;
  153. switch (m_packed.layout_mode_size)
  154. {
  155. case LAYOUT_SIZE_GRAVITY:
  156. height = ((gravity & WIDGET_GRAVITY_TOP) && (gravity & WIDGET_GRAVITY_BOTTOM)) ?
  157. available_height : MIN(available_height, ps.pref_h);
  158. break;
  159. case LAYOUT_SIZE_PREFERRED:
  160. height = MIN(available_height, ps.pref_h);
  161. break;
  162. case LAYOUT_SIZE_AVAILABLE:
  163. height = MIN(available_height, ps.max_h);
  164. break;
  165. };
  166. height = MIN(height, ps.max_h);
  167. return height;
  168. }
  169. TBWidget *TBLayout::GetNextNonCollapsedWidget(TBWidget *child) const
  170. {
  171. TBWidget *next = GetNextInLayoutOrder(child);
  172. while (next && next->GetVisibility() == WIDGET_VISIBILITY_GONE)
  173. next = GetNextInLayoutOrder(next);
  174. return next;
  175. }
  176. int TBLayout::GetTrailingSpace(TBWidget *child, int spacing) const
  177. {
  178. if (spacing == 0)
  179. return 0;
  180. if (!GetNextNonCollapsedWidget(child))
  181. return 0;
  182. return spacing;
  183. }
  184. int TBLayout::CalculateSpacing()
  185. {
  186. // Get spacing from skin, if not specified
  187. int spacing = m_spacing;
  188. if (spacing == SPACING_FROM_SKIN)
  189. {
  190. if (TBSkinElement *e = GetSkinBgElement())
  191. spacing = e->spacing;
  192. assert(SPACING_FROM_SKIN == SKIN_VALUE_NOT_SPECIFIED);
  193. if (spacing == SPACING_FROM_SKIN /*|| spacing == SKIN_VALUE_NOT_SPECIFIED*/)
  194. spacing = g_tb_skin->GetDefaultSpacing();
  195. }
  196. return spacing;
  197. }
  198. TBWidget *TBLayout::GetFirstInLayoutOrder() const
  199. {
  200. return m_packed.mode_reverse_order ? GetLastChild() : GetFirstChild();
  201. }
  202. TBWidget *TBLayout::GetNextInLayoutOrder(TBWidget *child) const
  203. {
  204. return m_packed.mode_reverse_order ? child->GetPrev() : child->GetNext();
  205. }
  206. void TBLayout::ValidateLayout(const SizeConstraints &constraints, PreferredSize *calculate_ps)
  207. {
  208. // Layout notes:
  209. // -All layout code is written for AXIS_X layout.
  210. // Instead of duplicating the layout code for both AXIS_X and AXIS_Y, we simply
  211. // rotate the in data (rect, gravity, preferred size) and the outdata (rect).
  212. if (!calculate_ps)
  213. {
  214. if (!m_packed.layout_is_invalid)
  215. return;
  216. m_packed.layout_is_invalid = 0;
  217. }
  218. else
  219. {
  220. // Maximum size will grow below depending of the childrens maximum size
  221. calculate_ps->max_w = calculate_ps->max_h = 0;
  222. }
  223. const int spacing = CalculateSpacing();
  224. const TBRect padding_rect = GetPaddingRect();
  225. const TBRect layout_rect = RotRect(padding_rect, m_axis);
  226. const SizeConstraints inner_sc = constraints.ConstrainByPadding(GetRect().w - padding_rect.w,
  227. GetRect().h - padding_rect.h);
  228. // Calculate totals for minimum and preferred width that we need for layout.
  229. int total_preferred_w = 0;
  230. int total_min_pref_diff_w = 0;
  231. int total_max_pref_diff_w = 0;
  232. for (TBWidget *child = GetFirstInLayoutOrder(); child; child = GetNextInLayoutOrder(child))
  233. {
  234. if (child->GetVisibility() == WIDGET_VISIBILITY_GONE)
  235. continue;
  236. const int ending_space = GetTrailingSpace(child, spacing);
  237. const PreferredSize ps = RotPreferredSize(child->GetPreferredSize(inner_sc), m_axis);
  238. const WIDGET_GRAVITY gravity = RotGravity(child->GetGravity(), m_axis);
  239. total_preferred_w += ps.pref_w + ending_space;
  240. total_min_pref_diff_w += ps.pref_w - ps.min_w;
  241. if (QualifyForExpansion(gravity))
  242. {
  243. int capped_max_w = MIN(layout_rect.w, ps.max_w);
  244. total_max_pref_diff_w += capped_max_w - ps.pref_w;
  245. }
  246. if (calculate_ps)
  247. {
  248. calculate_ps->min_h = MAX(calculate_ps->min_h, ps.min_h);
  249. calculate_ps->pref_h = MAX(calculate_ps->pref_h, ps.pref_h);
  250. calculate_ps->min_w += ps.min_w + ending_space;
  251. calculate_ps->pref_w += ps.pref_w + ending_space;
  252. calculate_ps->max_w += ps.max_w + ending_space;
  253. // The widget height depends on layout and widget properties, so get what
  254. // it would actually use if it was given max_h as available height.
  255. // If we just used its max_h, that could increase the whole layout size
  256. // even if the widget wouldn't actually use it.
  257. int height = GetWantedHeight(gravity, ps, ps.max_h);
  258. calculate_ps->max_h = MAX(calculate_ps->max_h, height);
  259. calculate_ps->size_dependency |= ps.size_dependency;
  260. }
  261. }
  262. if (calculate_ps)
  263. {
  264. // We just wanted to calculate preferred size, so return without layouting.
  265. *calculate_ps = RotPreferredSize(*calculate_ps, m_axis);
  266. return;
  267. }
  268. TB_IF_DEBUG_SETTING(LAYOUT_PS_DEBUGGING, last_layout_time = TBSystem::GetTimeMS());
  269. // Pre Layout step (calculate distribution position)
  270. int missing_space = MAX(total_preferred_w - layout_rect.w, 0);
  271. int extra_space = MAX(layout_rect.w - total_preferred_w, 0);
  272. int offset = layout_rect.x;
  273. if (extra_space && m_packed.layout_mode_dist_pos != LAYOUT_DISTRIBUTION_POSITION_LEFT_TOP)
  274. {
  275. // To calculate the offset we need to predict the used space. We can do that by checking
  276. // the distribution mode and total_max_pref_diff_w. That's how much the widgets could possible
  277. // expand in the layout below.
  278. int used_space = total_preferred_w;
  279. if (m_packed.layout_mode_dist != LAYOUT_DISTRIBUTION_PREFERRED)
  280. used_space += MIN(extra_space, total_max_pref_diff_w);
  281. if (m_packed.layout_mode_dist_pos == LAYOUT_DISTRIBUTION_POSITION_CENTER)
  282. offset += (layout_rect.w - used_space) / 2;
  283. else // LAYOUT_DISTRIBUTION_POSITION_RIGHT_BOTTOM
  284. offset += layout_rect.w - used_space;
  285. }
  286. // Layout
  287. int used_space = 0;
  288. for (TBWidget *child = GetFirstInLayoutOrder(); child; child = GetNextInLayoutOrder(child))
  289. {
  290. if (child->GetVisibility() == WIDGET_VISIBILITY_GONE)
  291. continue;
  292. const int ending_space = GetTrailingSpace(child, spacing);
  293. const PreferredSize ps = RotPreferredSize(child->GetPreferredSize(inner_sc), m_axis);
  294. const WIDGET_GRAVITY gravity = RotGravity(child->GetGravity(), m_axis);
  295. // Calculate width. May shrink if space is missing, or grow if we have extra space.
  296. int width = ps.pref_w;
  297. if (missing_space && total_min_pref_diff_w)
  298. {
  299. int diff_w = ps.pref_w - ps.min_w;
  300. float factor = (float)diff_w / (float)total_min_pref_diff_w;
  301. int removed = (int)(missing_space * factor);
  302. removed = MIN(removed, diff_w);
  303. width -= removed;
  304. total_min_pref_diff_w -= diff_w;
  305. missing_space -= removed;
  306. }
  307. else if (extra_space && total_max_pref_diff_w && QualifyForExpansion(gravity))
  308. {
  309. int capped_max_w = MIN(layout_rect.w, ps.max_w);
  310. int diff_w = capped_max_w - ps.pref_w;
  311. float factor = (float)diff_w / (float)total_max_pref_diff_w;
  312. int added = (int)(extra_space * factor);
  313. added = MIN(added, diff_w);
  314. width += added;
  315. total_max_pref_diff_w -= capped_max_w - ps.pref_w;
  316. extra_space -= added;
  317. }
  318. // Calculate height
  319. int available_height = layout_rect.h;
  320. int height = GetWantedHeight(gravity, ps, available_height);
  321. // Calculate position
  322. int pos = layout_rect.y;
  323. switch (m_packed.layout_mode_pos)
  324. {
  325. case LAYOUT_POSITION_CENTER:
  326. pos += (available_height - height) / 2;
  327. break;
  328. case LAYOUT_POSITION_RIGHT_BOTTOM:
  329. pos += available_height - height;
  330. break;
  331. case LAYOUT_POSITION_GRAVITY:
  332. if ((gravity & WIDGET_GRAVITY_TOP) && (gravity & WIDGET_GRAVITY_BOTTOM))
  333. pos += (available_height - height) / 2;
  334. else if (gravity & WIDGET_GRAVITY_BOTTOM)
  335. pos += available_height - height;
  336. break;
  337. default: // LAYOUT_POSITION_LEFT_TOP
  338. break;
  339. };
  340. // Done! Set rect and increase used space
  341. TBRect rect(used_space + offset, pos, width, height);
  342. used_space += width + ending_space;
  343. child->SetRect(RotRect(rect, m_axis));
  344. }
  345. // Update overflow and overflow scroll
  346. m_overflow = MAX(0, used_space - layout_rect.w);
  347. SetOverflowScroll(m_overflow_scroll);
  348. }
  349. PreferredSize TBLayout::OnCalculatePreferredContentSize(const SizeConstraints &constraints)
  350. {
  351. // Do a layout pass (without layouting) to check childrens preferences.
  352. PreferredSize ps;
  353. ValidateLayout(constraints, &ps);
  354. return ps;
  355. }
  356. bool TBLayout::OnEvent(const TBWidgetEvent &ev)
  357. {
  358. if (ev.type == EVENT_TYPE_WHEEL && ev.modifierkeys == TB_MODIFIER_NONE)
  359. {
  360. int old_scroll = GetOverflowScroll();
  361. SetOverflowScroll(m_overflow_scroll + ev.delta_y * TBSystem::GetPixelsPerLine());
  362. return m_overflow_scroll != old_scroll;
  363. }
  364. return false;
  365. }
  366. void TBLayout::OnPaintChildren(const PaintProps &paint_props)
  367. {
  368. TBRect padding_rect = GetPaddingRect();
  369. if (padding_rect.IsEmpty())
  370. return;
  371. // If we overflow the layout, apply clipping when painting children
  372. TBRect old_clip_rect;
  373. if (m_overflow)
  374. {
  375. // We only want clipping in one axis (the overflowing one) so we
  376. // don't damage any expanded skins on the other axis. Add some fluff.
  377. TBRect clip_rect = padding_rect;
  378. const int fluff = 100;
  379. if (m_axis == AXIS_X)
  380. clip_rect = clip_rect.Expand(m_overflow_scroll == 0 ? fluff : 0, fluff,
  381. m_overflow_scroll == m_overflow ? fluff : 0, fluff);
  382. else
  383. clip_rect = clip_rect.Expand(fluff, m_overflow_scroll == 0 ? fluff : 0,
  384. fluff, m_overflow_scroll == m_overflow ? fluff : 0);
  385. old_clip_rect = g_renderer->SetClipRect(clip_rect, true);
  386. TB_IF_DEBUG_SETTING(LAYOUT_CLIPPING, g_renderer->DrawRect(clip_rect, TBColor(255, 0, 0, 200)));
  387. }
  388. // Paint children
  389. TBWidget::OnPaintChildren(paint_props);
  390. // Paint fadeout image over the overflowed edges
  391. // to the indicate to used that it's overflowed.
  392. if (m_overflow && m_packed.paint_overflow_fadeout)
  393. {
  394. TBID skin_x, skin_y;
  395. if (m_axis == AXIS_X)
  396. skin_x = TBIDC("TBLayout.fadeout_x");
  397. else
  398. skin_y = TBIDC("TBLayout.fadeout_y");
  399. DrawEdgeFadeout(padding_rect, skin_x, skin_y,
  400. m_overflow_scroll,
  401. m_overflow_scroll,
  402. m_overflow - m_overflow_scroll,
  403. m_overflow - m_overflow_scroll);
  404. }
  405. // Restore clipping
  406. if (m_overflow)
  407. g_renderer->SetClipRect(old_clip_rect, false);
  408. }
  409. void TBLayout::OnProcess()
  410. {
  411. SizeConstraints sc(GetRect().w, GetRect().h);
  412. ValidateLayout(sc);
  413. }
  414. void TBLayout::OnResized(int old_w, int old_h)
  415. {
  416. InvalidateLayout(INVALIDATE_LAYOUT_TARGET_ONLY);
  417. SizeConstraints sc(GetRect().w, GetRect().h);
  418. ValidateLayout(sc);
  419. // ATOMIC BEGIN So pure UIWidgets can handle resize
  420. if (GetDelegate()) { GetDelegate()->OnResized(old_w, old_h); }
  421. // ATOMIC END
  422. }
  423. void TBLayout::OnInflateChild(TBWidget *child)
  424. {
  425. // Do nothing since we're going to layout the child soon.
  426. }
  427. void TBLayout::GetChildTranslation(int &x, int &y) const
  428. {
  429. if (m_axis == AXIS_X)
  430. {
  431. x = -m_overflow_scroll;
  432. y = 0;
  433. }
  434. else
  435. {
  436. x = 0;
  437. y = -m_overflow_scroll;
  438. }
  439. }
  440. void TBLayout::ScrollTo(int x, int y)
  441. {
  442. SetOverflowScroll(m_axis == AXIS_X ? x : y);
  443. }
  444. TBWidget::ScrollInfo TBLayout::GetScrollInfo()
  445. {
  446. ScrollInfo info;
  447. if (m_axis == AXIS_X)
  448. {
  449. info.max_x = m_overflow;
  450. info.x = m_overflow_scroll;
  451. }
  452. else
  453. {
  454. info.max_y = m_overflow;
  455. info.y = m_overflow_scroll;
  456. }
  457. return info;
  458. }
  459. // ATOMIC BEGIN
  460. // defines for character positions
  461. #define LCFG_AXIS 0
  462. #define LCFG_SZ 1
  463. #define LCFG_POS 2
  464. #define LCFG_DST 3
  465. #define LCFG_DSPOS 4
  466. /// A different way of setting up a layout, using a series of characters to program the main 5 layout fields
  467. /// character [0] = 'X' or 'Y' for UI_AXIS = X(D), Y
  468. /// character [1] = 'A'|'G'|'P' for UI_LAYOUT_SIZE = Available, Gravity(D), Perferred
  469. /// character [2] = 'C'|'G'|'L'|'R' for UI_LAYOUT_POSITION = Center(D), Gravity, LeftTop, RightBottom
  470. /// character [3] = 'A'|'G'|'P' for UI_LAYOUT_DISTRIBUTION = Available, Gravity, Perferred(D)
  471. /// character [4] = 'C'|'L'|'R' for UI_LAYOUT_DISTRIBUTION_POSITION, Center(D), LeftTop, RightBottom
  472. /// A '-' character in any field will not program that entry.
  473. /// Any character used that is not an allowed characters or a '-' will result in the default setting to be used.
  474. /// Any text in the string above character 5 is ignored.
  475. /// If the input string is less than 5 characters it will not program any of the fields.
  476. void TBLayout::SetLayoutConfig ( const char *settings )
  477. {
  478. if ( settings && strlen(settings) >= 4 )
  479. {
  480. switch ( settings[LCFG_AXIS] ) // AXIS
  481. {
  482. case 'X': SetAxis(AXIS_X); break;
  483. case 'Y': SetAxis(AXIS_Y); break;
  484. default: if ( settings[LCFG_AXIS] != '-')
  485. SetAxis(AXIS_X);
  486. break;
  487. }
  488. switch ( settings[LCFG_SZ] ) // SIZE
  489. {
  490. case 'A' : SetLayoutSize(LAYOUT_SIZE_AVAILABLE); break;
  491. case 'G' : SetLayoutSize(LAYOUT_SIZE_GRAVITY); break;
  492. case 'P' : SetLayoutSize(LAYOUT_SIZE_PREFERRED); break;
  493. default: if (settings[LCFG_SZ] != '-')
  494. SetLayoutSize(LAYOUT_SIZE_GRAVITY);
  495. break;
  496. }
  497. switch ( settings[LCFG_POS] ) // POSITION
  498. {
  499. case 'C' : SetLayoutPosition(LAYOUT_POSITION_CENTER); break;
  500. case 'G' : SetLayoutPosition(LAYOUT_POSITION_GRAVITY); break;
  501. case 'L' : SetLayoutPosition(LAYOUT_POSITION_LEFT_TOP); break;
  502. case 'R' : SetLayoutPosition(LAYOUT_POSITION_RIGHT_BOTTOM); break;
  503. default: if (settings[LCFG_POS] != '-' )
  504. SetLayoutPosition(LAYOUT_POSITION_CENTER);
  505. break;
  506. }
  507. switch ( settings[LCFG_DST] ) // DISTRIBUTION
  508. {
  509. case 'A' : SetLayoutDistribution(LAYOUT_DISTRIBUTION_AVAILABLE); break;
  510. case 'G' : SetLayoutDistribution(LAYOUT_DISTRIBUTION_GRAVITY); break;
  511. case 'P' : SetLayoutDistribution(LAYOUT_DISTRIBUTION_PREFERRED); break;
  512. default: if (settings[LCFG_DST] != '-')
  513. SetLayoutDistribution(LAYOUT_DISTRIBUTION_PREFERRED );
  514. break;
  515. }
  516. switch ( settings[LCFG_DSPOS] ) // DISTRIBUTION_POSITION
  517. {
  518. case 'C' : SetLayoutDistributionPosition(LAYOUT_DISTRIBUTION_POSITION_CENTER); break;
  519. case 'L' : SetLayoutDistributionPosition(LAYOUT_DISTRIBUTION_POSITION_LEFT_TOP); break;
  520. case 'R' : SetLayoutDistributionPosition(LAYOUT_DISTRIBUTION_POSITION_RIGHT_BOTTOM); break;
  521. default: if (settings[LCFG_DSPOS] != '-' )
  522. SetLayoutDistributionPosition(LAYOUT_DISTRIBUTION_POSITION_CENTER);
  523. break;
  524. }
  525. }
  526. }
  527. // ATOMIC END
  528. }; // namespace tb