tb_message_window.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  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_message_window.h"
  6. #include "tb_widgets_reader.h"
  7. #include "tb_editfield.h"
  8. #include "tb_language.h"
  9. #include <assert.h>
  10. namespace tb {
  11. // == TBMessageWindow =======================================================================================
  12. TBMessageWindow::TBMessageWindow(TBWidget *target, TBID id)
  13. : m_target(target)
  14. {
  15. TBWidgetListener::AddGlobalListener(this);
  16. SetID(id);
  17. }
  18. TBMessageWindow::~TBMessageWindow()
  19. {
  20. TBWidgetListener::RemoveGlobalListener(this);
  21. if (TBWidget *dimmer = m_dimmer.Get())
  22. {
  23. dimmer->GetParent()->RemoveChild(dimmer);
  24. delete dimmer;
  25. }
  26. }
  27. bool TBMessageWindow::Show(const char *title, const char *message, TBMessageWindowSettings *settings, int width, int height)
  28. {
  29. TBWidget *target = m_target.Get();
  30. if (!target)
  31. return false;
  32. TBMessageWindowSettings default_settings;
  33. if (!settings)
  34. settings = &default_settings;
  35. TBWidget *root = target->GetParentRoot();
  36. const char *source = "TBLayout: axis: y, distribution: available\n"
  37. " TBLayout: distribution: available, size: available\n"
  38. " TBSkinImage: id: 2\n"
  39. " TBEditField: multiline: 1, readonly: 1, id: 1\n"
  40. " TBLayout: distribution: available\n"
  41. " TBLayout: distribution-position: left top, id: 5\n"
  42. " TBLayout: distribution-position: right bottom, id: 3\n";
  43. if (!g_widgets_reader->LoadData(GetContentRoot(), source))
  44. return false;
  45. SetText(title);
  46. GetWidgetByIDAndType<TBSkinImage>(2)->SetSkinBg(settings->icon_skin);
  47. TBEditField *editfield = GetWidgetByIDAndType<TBEditField>(1);
  48. editfield->SetStyling(settings->styling);
  49. editfield->SetText(message);
  50. editfield->SetSkinBg("");
  51. // Create buttons
  52. if (settings->msg == TB_MSG_OK)
  53. {
  54. AddButton("TBMessageWindow.ok", true);
  55. }
  56. else if (settings->msg == TB_MSG_OK_CANCEL)
  57. {
  58. AddButton("TBMessageWindow.ok", true);
  59. AddButton("TBMessageWindow.cancel", false);
  60. }
  61. else if (settings->msg == TB_MSG_YES_NO)
  62. {
  63. AddButton("TBMessageWindow.yes", true);
  64. AddButton("TBMessageWindow.no", false);
  65. }
  66. TBRect rect;
  67. // Size to fit content. This will use the default size of the textfield.
  68. if (width == 0 || height == 0)
  69. {
  70. ResizeToFitContent();
  71. rect = GetRect();
  72. // Get how much we overflow the textfield has given the current width, and grow our height to show all we can.
  73. // FIX: It would be better to use adapt-to-content on the editfield to achieve the most optimal size.
  74. // At least when we do full blown multi pass size checking.
  75. rect.h += editfield->GetStyleEdit()->GetOverflowY();
  76. }
  77. else
  78. {
  79. SetSize(width, height);
  80. rect = GetRect();
  81. }
  82. // Create background dimmer
  83. if (settings->dimmer)
  84. {
  85. if (TBDimmer *dimmer = new TBDimmer)
  86. {
  87. root->AddChild(dimmer);
  88. m_dimmer.Set(dimmer);
  89. }
  90. }
  91. // Center and size to the new height
  92. TBRect bounds(0, 0, root->GetRect().w, root->GetRect().h);
  93. SetRect(rect.CenterIn(bounds).MoveIn(bounds).Clip(bounds));
  94. root->AddChild(this);
  95. return true;
  96. }
  97. void TBMessageWindow::AddButtonLeft(TBID id, bool focused)
  98. {
  99. AddButton(id, focused, GetWidgetByIDAndType<TBLayout>(5));
  100. }
  101. void TBMessageWindow::AddButton(TBID id, bool focused, TBLayout *layout)
  102. {
  103. if (!layout)
  104. layout = GetWidgetByIDAndType<TBLayout>(3);
  105. if (!layout)
  106. return;
  107. if (TBButton *btn = new TBButton)
  108. {
  109. btn->SetID(id);
  110. btn->SetText(g_tb_lng->GetString(btn->GetID()));
  111. layout->AddChild(btn);
  112. if (focused)
  113. btn->SetFocus(WIDGET_FOCUS_REASON_UNKNOWN);
  114. }
  115. }
  116. bool TBMessageWindow::OnEvent(const TBWidgetEvent &ev)
  117. {
  118. if (ev.type == EVENT_TYPE_CLICK && ev.target->IsOfType<TBButton>())
  119. {
  120. TBWidgetSafePointer this_widget(this);
  121. // Invoke the click on the target
  122. TBWidgetEvent target_ev(EVENT_TYPE_CLICK);
  123. target_ev.ref_id = ev.target->GetID();
  124. InvokeEvent(target_ev);
  125. // If target got deleted, close
  126. if (this_widget.Get())
  127. Close();
  128. return true;
  129. }
  130. else if (ev.type == EVENT_TYPE_KEY_DOWN && ev.special_key == TB_KEY_ESC)
  131. {
  132. TBWidgetEvent click_ev(EVENT_TYPE_CLICK);
  133. m_close_button.InvokeEvent(click_ev);
  134. return true;
  135. }
  136. return TBWindow::OnEvent(ev);
  137. }
  138. void TBMessageWindow::OnDie()
  139. {
  140. if (TBWidget *dimmer = m_dimmer.Get())
  141. dimmer->Die();
  142. }
  143. void TBMessageWindow::OnWidgetDelete(TBWidget *widget)
  144. {
  145. // If the target widget is deleted, close!
  146. if (!m_target.Get())
  147. Close();
  148. }
  149. bool TBMessageWindow::OnWidgetDying(TBWidget *widget)
  150. {
  151. // If the target widget or an ancestor of it is dying, close!
  152. if (widget == m_target.Get() || widget->IsAncestorOf(m_target.Get()))
  153. Close();
  154. return false;
  155. }
  156. }; // namespace tb