tb_inline_select.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  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_inline_select.h"
  6. #include <assert.h>
  7. #include <math.h>
  8. #include <stdlib.h>
  9. namespace tb {
  10. // FIX: axis should affect the buttons arrow skin!
  11. // FIX: unfocus should set the correct text!
  12. // == TBInlineSelect ========================================================================================
  13. TBInlineSelect::TBInlineSelect()
  14. : m_value(0)
  15. , m_min(0)
  16. , m_max(100)
  17. , m_modified(false)
  18. // ATOMIC BEGIN
  19. , m_stepsize(1.0)
  20. // ATOMIC END
  21. {
  22. SetSkinBg(TBIDC("TBInlineSelect"));
  23. AddChild(&m_layout);
  24. m_layout.AddChild(&m_buttons[0]);
  25. m_layout.AddChild(&m_editfield);
  26. m_layout.AddChild(&m_buttons[1]);
  27. m_layout.SetRect(GetPaddingRect());
  28. m_layout.SetGravity(WIDGET_GRAVITY_ALL);
  29. m_layout.SetSpacing(0);
  30. m_buttons[0].SetSkinBg(TBIDC("TBButton.flat"));
  31. m_buttons[1].SetSkinBg(TBIDC("TBButton.flat"));
  32. m_buttons[0].GetContentRoot()->AddChild(new TBSkinImage(TBIDC("arrowdark.left")));
  33. m_buttons[1].GetContentRoot()->AddChild(new TBSkinImage(TBIDC("arrowdark.right")));
  34. m_buttons[0].SetIsFocusable(false);
  35. m_buttons[1].SetIsFocusable(false);
  36. m_buttons[0].SetID(TBIDC("dec"));
  37. m_buttons[1].SetID(TBIDC("inc"));
  38. m_buttons[0].SetAutoRepeat(true);
  39. m_buttons[1].SetAutoRepeat(true);
  40. m_editfield.SetID(TBIDC("edit"));
  41. m_editfield.SetTextAlign(TB_TEXT_ALIGN_CENTER);
  42. m_editfield.SetEditType(EDIT_TYPE_NUMBER);
  43. m_editfield.SetText("0");
  44. m_editfield.AddListener(this);
  45. }
  46. TBInlineSelect::~TBInlineSelect()
  47. {
  48. m_editfield.RemoveListener(this);
  49. m_layout.RemoveChild(&m_buttons[1]);
  50. m_layout.RemoveChild(&m_editfield);
  51. m_layout.RemoveChild(&m_buttons[0]);
  52. RemoveChild(&m_layout);
  53. }
  54. void TBInlineSelect::SetEditFieldLayoutParams(LayoutParams& lp)
  55. {
  56. m_editfield.SetLayoutParams(lp);
  57. }
  58. void TBInlineSelect::SetLimits(double min, double max)
  59. {
  60. assert(min <= max);
  61. m_min = min;
  62. m_max = max;
  63. SetValueDouble(m_value);
  64. }
  65. void TBInlineSelect::SetValueInternal(double value, bool update_text)
  66. {
  67. value = CLAMP(value, m_min, m_max);
  68. if (value == m_value)
  69. return;
  70. m_value = value;
  71. if (update_text)
  72. {
  73. TBStr strval;
  74. double prec = m_value - floor(m_value);
  75. if (prec < .001)
  76. {
  77. strval.SetFormatted("%.0f", m_value);
  78. }
  79. else
  80. strval.SetFormatted("%.2f", m_value);
  81. m_editfield.SetText(strval);
  82. }
  83. TBWidgetEvent ev(EVENT_TYPE_CHANGED);
  84. InvokeEvent(ev);
  85. // Warning: Do nothing here since the event might have deleted us.
  86. // If needed, check if we are alive using a safe pointer first.
  87. }
  88. void TBInlineSelect::OnSkinChanged()
  89. {
  90. m_layout.SetRect(GetPaddingRect());
  91. }
  92. bool TBInlineSelect::OnEvent(const TBWidgetEvent &ev)
  93. {
  94. if (ev.type == EVENT_TYPE_KEY_DOWN)
  95. {
  96. if (ev.special_key == TB_KEY_UP || ev.special_key == TB_KEY_DOWN)
  97. {
  98. // ATOMIC BEGIN
  99. double dv = ev.special_key == TB_KEY_UP ? m_stepsize : -m_stepsize;
  100. // ATOMIC END
  101. SetValueDouble(GetValueDouble() + dv);
  102. return true;
  103. }
  104. }
  105. else if (ev.type == EVENT_TYPE_CLICK && ev.target->GetID() == TBIDC("dec"))
  106. {
  107. // ATOMIC BEGIN
  108. SetValueDouble(GetValueDouble() - m_stepsize);
  109. // ATOMIC END
  110. if (!ev.target->IsCaptured()) {
  111. InvokeModifiedEvent();
  112. }
  113. return true;
  114. }
  115. else if (ev.type == EVENT_TYPE_CLICK && ev.target->GetID() == TBIDC("inc"))
  116. {
  117. // ATOMIC BEGIN
  118. SetValueDouble(GetValueDouble() + m_stepsize);
  119. // ATOMIC END
  120. if (!ev.target->IsCaptured()) {
  121. InvokeModifiedEvent();
  122. }
  123. return true;
  124. }
  125. else if (ev.type == EVENT_TYPE_CHANGED && ev.target == &m_editfield)
  126. {
  127. TBStr text;
  128. m_editfield.GetText(text);
  129. SetValueInternal((double) atof(text), false);
  130. }
  131. else if (ev.type == EVENT_TYPE_CHANGED && ev.target == this)
  132. {
  133. return TBWidget::OnEvent(ev);
  134. }
  135. return false;
  136. }
  137. void TBInlineSelect::InvokeModifiedEvent()
  138. {
  139. TBWidgetEvent ev(EVENT_TYPE_CUSTOM);
  140. // TBIDC does not register the TBID with the UI system, so do it this way
  141. TBID refid("edit_complete");
  142. ev.ref_id = refid;
  143. // forward to delegate
  144. TBWidget::OnEvent(ev);
  145. m_modified = false;
  146. m_editfield.GetText(m_initial_edit_value);
  147. }
  148. bool TBInlineSelect::OnWidgetInvokeEvent(TBWidget *widget, const TBWidgetEvent &ev)
  149. {
  150. return false;
  151. }
  152. void TBInlineSelect::OnWidgetFocusChanged(TBWidget *widget, bool focused)
  153. {
  154. if (widget == &m_editfield)
  155. {
  156. if (focused)
  157. m_editfield.GetText(m_initial_edit_value);
  158. else
  159. {
  160. TBStr editvalue;
  161. m_editfield.GetText(editvalue);
  162. if (m_modified || !editvalue.Equals(m_initial_edit_value.CStr()))
  163. {
  164. InvokeModifiedEvent();
  165. }
  166. }
  167. }
  168. }
  169. }; // namespace tb