infobar.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Name: src/gtk/infobar.cpp
  3. // Purpose: wxInfoBar implementation for GTK
  4. // Author: Vadim Zeitlin
  5. // Created: 2009-09-27
  6. // Copyright: (c) 2009 Vadim Zeitlin <vadim@wxwidgets.org>
  7. // Licence: wxWindows licence
  8. ///////////////////////////////////////////////////////////////////////////////
  9. // ============================================================================
  10. // declarations
  11. // ============================================================================
  12. // ----------------------------------------------------------------------------
  13. // headers
  14. // ----------------------------------------------------------------------------
  15. // for compilers that support precompilation, includes "wx.h".
  16. #include "wx/wxprec.h"
  17. #ifdef __BORLANDC__
  18. #pragma hdrstop
  19. #endif
  20. #include "wx/infobar.h"
  21. #if wxUSE_INFOBAR && defined(wxHAS_NATIVE_INFOBAR)
  22. #ifndef WX_PRECOMP
  23. #endif // WX_PRECOMP
  24. #include "wx/vector.h"
  25. #include "wx/stockitem.h"
  26. #include "wx/gtk/private.h"
  27. #include "wx/gtk/private/messagetype.h"
  28. // ----------------------------------------------------------------------------
  29. // local classes
  30. // ----------------------------------------------------------------------------
  31. class wxInfoBarGTKImpl
  32. {
  33. public:
  34. wxInfoBarGTKImpl()
  35. {
  36. m_label = NULL;
  37. m_close = NULL;
  38. }
  39. // label for the text shown in the bar
  40. GtkWidget *m_label;
  41. // the default close button, NULL if not needed (m_buttons is not empty) or
  42. // not created yet
  43. GtkWidget *m_close;
  44. // information about the buttons added using AddButton()
  45. struct Button
  46. {
  47. Button(GtkWidget *button_, int id_)
  48. : button(button_),
  49. id(id_)
  50. {
  51. }
  52. GtkWidget *button;
  53. int id;
  54. };
  55. typedef wxVector<Button> Buttons;
  56. Buttons m_buttons;
  57. };
  58. // ----------------------------------------------------------------------------
  59. // local functions
  60. // ----------------------------------------------------------------------------
  61. namespace
  62. {
  63. inline bool UseNative()
  64. {
  65. #ifdef __WXGTK3__
  66. return true;
  67. #else
  68. // native GtkInfoBar widget is only available in GTK+ 2.18 and later
  69. return gtk_check_version(2, 18, 0) == 0;
  70. #endif
  71. }
  72. } // anonymous namespace
  73. extern "C"
  74. {
  75. static void wxgtk_infobar_response(GtkInfoBar * WXUNUSED(infobar),
  76. gint btnid,
  77. wxInfoBar *win)
  78. {
  79. win->GTKResponse(btnid);
  80. }
  81. static void wxgtk_infobar_close(GtkInfoBar * WXUNUSED(infobar),
  82. wxInfoBar *win)
  83. {
  84. win->GTKResponse(wxID_CANCEL);
  85. }
  86. } // extern "C" section with GTK+ callbacks
  87. // ============================================================================
  88. // wxInfoBar implementation
  89. // ============================================================================
  90. bool wxInfoBar::Create(wxWindow *parent, wxWindowID winid)
  91. {
  92. if ( !UseNative() )
  93. return wxInfoBarGeneric::Create(parent, winid);
  94. m_impl = new wxInfoBarGTKImpl;
  95. // this control is created initially hidden
  96. Hide();
  97. if ( !CreateBase(parent, winid) )
  98. return false;
  99. // create the info bar widget itself
  100. m_widget = gtk_info_bar_new();
  101. wxCHECK_MSG( m_widget, false, "failed to create GtkInfoBar" );
  102. g_object_ref(m_widget);
  103. // also create a label which will be used to show our message
  104. m_impl->m_label = gtk_label_new("");
  105. gtk_widget_show(m_impl->m_label);
  106. GtkWidget * const
  107. contentArea = gtk_info_bar_get_content_area(GTK_INFO_BAR(m_widget));
  108. wxCHECK_MSG( contentArea, false, "failed to get GtkInfoBar content area" );
  109. gtk_container_add(GTK_CONTAINER(contentArea), m_impl->m_label);
  110. // finish creation and connect to all the signals we're interested in
  111. m_parent->DoAddChild(this);
  112. PostCreation(wxDefaultSize);
  113. GTKConnectWidget("response", G_CALLBACK(wxgtk_infobar_response));
  114. GTKConnectWidget("close", G_CALLBACK(wxgtk_infobar_close));
  115. return true;
  116. }
  117. wxInfoBar::~wxInfoBar()
  118. {
  119. delete m_impl;
  120. }
  121. void wxInfoBar::ShowMessage(const wxString& msg, int flags)
  122. {
  123. if ( !UseNative() )
  124. {
  125. wxInfoBarGeneric::ShowMessage(msg, flags);
  126. return;
  127. }
  128. // if we don't have any buttons, create a standard close one to give the
  129. // user at least some way to close the bar
  130. if ( m_impl->m_buttons.empty() && !m_impl->m_close )
  131. {
  132. m_impl->m_close = GTKAddButton(wxID_CLOSE);
  133. }
  134. GtkMessageType type;
  135. if ( wxGTKImpl::ConvertMessageTypeFromWX(flags, &type) )
  136. gtk_info_bar_set_message_type(GTK_INFO_BAR(m_widget), type);
  137. gtk_label_set_text(GTK_LABEL(m_impl->m_label), wxGTK_CONV(msg));
  138. if ( !IsShown() )
  139. Show();
  140. UpdateParent();
  141. }
  142. void wxInfoBar::Dismiss()
  143. {
  144. if ( !UseNative() )
  145. {
  146. wxInfoBarGeneric::Dismiss();
  147. return;
  148. }
  149. Hide();
  150. UpdateParent();
  151. }
  152. void wxInfoBar::GTKResponse(int btnid)
  153. {
  154. wxCommandEvent event(wxEVT_BUTTON, btnid);
  155. event.SetEventObject(this);
  156. if ( !HandleWindowEvent(event) )
  157. Dismiss();
  158. }
  159. GtkWidget *wxInfoBar::GTKAddButton(wxWindowID btnid, const wxString& label)
  160. {
  161. // as GTK+ lays out the buttons vertically, adding another button changes
  162. // our best size (at least in vertical direction)
  163. InvalidateBestSize();
  164. GtkWidget *button = gtk_info_bar_add_button
  165. (
  166. GTK_INFO_BAR(m_widget),
  167. (label.empty()
  168. ? GTKConvertMnemonics(wxGetStockGtkID(btnid))
  169. : label).utf8_str(),
  170. btnid
  171. );
  172. wxASSERT_MSG( button, "unexpectedly failed to add button to info bar" );
  173. return button;
  174. }
  175. void wxInfoBar::AddButton(wxWindowID btnid, const wxString& label)
  176. {
  177. if ( !UseNative() )
  178. {
  179. wxInfoBarGeneric::AddButton(btnid, label);
  180. return;
  181. }
  182. // if we had created the default close button before, remove it now that we
  183. // have some user-defined button
  184. if ( m_impl->m_close )
  185. {
  186. gtk_widget_destroy(m_impl->m_close);
  187. m_impl->m_close = NULL;
  188. }
  189. GtkWidget * const button = GTKAddButton(btnid, label);
  190. if ( button )
  191. m_impl->m_buttons.push_back(wxInfoBarGTKImpl::Button(button, btnid));
  192. }
  193. void wxInfoBar::RemoveButton(wxWindowID btnid)
  194. {
  195. if ( !UseNative() )
  196. {
  197. wxInfoBarGeneric::RemoveButton(btnid);
  198. return;
  199. }
  200. // as in the generic version, look for the button starting from the end
  201. wxInfoBarGTKImpl::Buttons& buttons = m_impl->m_buttons;
  202. for ( wxInfoBarGTKImpl::Buttons::reverse_iterator i = buttons.rbegin();
  203. i != buttons.rend();
  204. ++i )
  205. {
  206. if (i->id == btnid)
  207. {
  208. gtk_widget_destroy(i->button);
  209. buttons.erase(i.base());
  210. // see comment in GTKAddButton()
  211. InvalidateBestSize();
  212. return;
  213. }
  214. }
  215. wxFAIL_MSG( wxString::Format("button with id %d not found", btnid) );
  216. }
  217. void wxInfoBar::DoApplyWidgetStyle(GtkRcStyle *style)
  218. {
  219. wxInfoBarGeneric::DoApplyWidgetStyle(style);
  220. if ( UseNative() )
  221. GTKApplyStyle(m_impl->m_label, style);
  222. }
  223. #endif // wxUSE_INFOBAR