tb_message_window.cpp 4.6 KB

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