]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/tglbtn.cpp
Fix crash in wxDC::GetMultiLineTextExtent() after last commit.
[wxWidgets.git] / src / gtk / tglbtn.cpp
CommitLineData
1db8dc4a 1/////////////////////////////////////////////////////////////////////////////
f1e01716 2// Name: src/gtk/tglbtn.cpp
1db8dc4a
VZ
3// Purpose: Definition of the wxToggleButton class, which implements a
4// toggle button under wxGTK.
5// Author: John Norris, minor changes by Axel Schlueter
6// Modified by:
7// Created: 08.02.01
8// RCS-ID: $Id$
9// Copyright: (c) 2000 Johnny C. Norris II
526954c5 10// Licence: wxWindows licence
1db8dc4a
VZ
11/////////////////////////////////////////////////////////////////////////////
12
14f355c2
VS
13// For compilers that support precompilation, includes "wx.h".
14#include "wx/wxprec.h"
15
f1e01716
WS
16#if wxUSE_TOGGLEBTN
17
1db8dc4a
VZ
18#include "wx/tglbtn.h"
19
f1e01716
WS
20#ifndef WX_PRECOMP
21 #include "wx/button.h"
22#endif
1db8dc4a 23
9dc44eff 24#include <gtk/gtk.h>
9e691f46 25#include "wx/gtk/private.h"
1db8dc4a 26
1db8dc4a 27extern bool g_blockEventsOnDrag;
1db8dc4a 28
865bb325 29extern "C" {
9864c56d 30static void gtk_togglebutton_clicked_callback(GtkWidget *WXUNUSED(widget), wxToggleButton *cb)
1db8dc4a 31{
8ab75332 32 if (g_blockEventsOnDrag)
91af0895
WS
33 return;
34
91af0895
WS
35 // Generate a wx event.
36 wxCommandEvent event(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, cb->GetId());
37 event.SetInt(cb->GetValue());
38 event.SetEventObject(cb);
937013e0 39 cb->HandleWindowEvent(event);
1db8dc4a 40}
865bb325 41}
1db8dc4a 42
9b11752c 43wxDEFINE_EVENT( wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEvent );
1db8dc4a 44
4f856067 45// ------------------------------------------------------------------------
10ff9c61 46// wxBitmapToggleButton
4f856067
RR
47// ------------------------------------------------------------------------
48
b4354db1 49IMPLEMENT_DYNAMIC_CLASS(wxBitmapToggleButton, wxToggleButton)
4f856067 50
10ff9c61 51bool wxBitmapToggleButton::Create(wxWindow *parent, wxWindowID id,
b4354db1 52 const wxBitmap &bitmap, const wxPoint &pos,
4f856067
RR
53 const wxSize &size, long style,
54 const wxValidator& validator,
55 const wxString &name)
56{
b4354db1
VZ
57 if ( !wxToggleButton::Create(parent, id, wxEmptyString, pos, size, style | wxBU_NOTEXT | wxBU_EXACTFIT,
58 validator, name) )
91af0895 59 return false;
4f856067 60
b4354db1 61 if ( bitmap.IsOk() )
4f856067 62 {
b4354db1 63 SetBitmapLabel(bitmap);
4f856067 64
b4354db1
VZ
65 // we need to adjust the size after setting the bitmap as it may be too
66 // big for the default button size
67 SetInitialSize(size);
ad60f9e7
JS
68 }
69
91af0895 70 return true;
4f856067
RR
71}
72
9d522606 73
4f856067
RR
74// ------------------------------------------------------------------------
75// wxToggleButton
76// ------------------------------------------------------------------------
77
78IMPLEMENT_DYNAMIC_CLASS(wxToggleButton, wxControl)
79
1db8dc4a
VZ
80bool wxToggleButton::Create(wxWindow *parent, wxWindowID id,
81 const wxString &label, const wxPoint &pos,
82 const wxSize &size, long style,
83 const wxValidator& validator,
84 const wxString &name)
85{
91af0895 86 if (!PreCreation(parent, pos, size) ||
e338053c
PC
87 !CreateBase(parent, id, pos, size, style, validator, name ))
88 {
91af0895
WS
89 wxFAIL_MSG(wxT("wxToggleButton creation failed"));
90 return false;
91 }
1db8dc4a 92
b4354db1
VZ
93 // create either a standard toggle button with text label (which may still contain
94 // an image under GTK+ 2.6+) or a bitmap-only toggle button if we don't have any
95 // label
96 const bool
97 useLabel = !(style & wxBU_NOTEXT) && !label.empty();
98 if ( useLabel )
99 {
100 m_widget = gtk_toggle_button_new_with_mnemonic("");
101 }
102 else // no label, suppose we will have a bitmap
103 {
104 m_widget = gtk_toggle_button_new();
105
106 GtkWidget *image = gtk_image_new();
107 gtk_widget_show(image);
108 gtk_container_add(GTK_CONTAINER(m_widget), image);
109 }
110
9ff9d30c 111 g_object_ref(m_widget);
ecf3b4a5 112
b4354db1
VZ
113 if ( useLabel )
114 SetLabel(label);
1db8dc4a 115
9fa72bd2
MR
116 g_signal_connect (m_widget, "clicked",
117 G_CALLBACK (gtk_togglebutton_clicked_callback),
118 this);
1db8dc4a 119
91af0895 120 m_parent->DoAddChild(this);
1db8dc4a 121
91af0895
WS
122 PostCreation(size);
123
124 return true;
1db8dc4a
VZ
125}
126
c71ab7c1
RR
127void wxToggleButton::GTKDisableEvents()
128{
129 g_signal_handlers_block_by_func(m_widget,
130 (gpointer) gtk_togglebutton_clicked_callback, this);
131}
132
133void wxToggleButton::GTKEnableEvents()
134{
135 g_signal_handlers_unblock_by_func(m_widget,
136 (gpointer) gtk_togglebutton_clicked_callback, this);
137}
138
1db8dc4a
VZ
139// void SetValue(bool state)
140// Set the value of the toggle button.
141void wxToggleButton::SetValue(bool state)
142{
91af0895 143 wxCHECK_RET(m_widget != NULL, wxT("invalid toggle button"));
1db8dc4a 144
91af0895
WS
145 if (state == GetValue())
146 return;
1db8dc4a 147
5e53c1c2 148 GTKDisableEvents();
1db8dc4a 149
91af0895 150 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(m_widget), state);
1db8dc4a 151
5e53c1c2 152 GTKEnableEvents();
1db8dc4a
VZ
153}
154
155// bool GetValue() const
156// Get the value of the toggle button.
157bool wxToggleButton::GetValue() const
158{
91af0895 159 wxCHECK_MSG(m_widget != NULL, false, wxT("invalid toggle button"));
1db8dc4a 160
385e8575 161 return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(m_widget)) != 0;
1db8dc4a
VZ
162}
163
1db8dc4a
VZ
164void wxToggleButton::SetLabel(const wxString& label)
165{
8ab696e0 166 wxCHECK_RET(m_widget != NULL, wxT("invalid toggle button"));
1db8dc4a 167
b4354db1 168 wxAnyButton::SetLabel(label);
1db8dc4a 169
b29bd6b4
VZ
170 if ( HasFlag(wxBU_NOTEXT) )
171 {
172 // Don't try to update the label for a button not showing it, this is
173 // unnecessary and can also actually replace the image we show with the
174 // label entirely breaking the button code, see #13693.
175 return;
176 }
177
ecf3b4a5
RR
178 const wxString labelGTK = GTKConvertMnemonics(label);
179
180 gtk_button_set_label(GTK_BUTTON(m_widget), wxGTK_CONV(labelGTK));
181
496e7ec6 182 GTKApplyWidgetStyle( false );
1db8dc4a
VZ
183}
184
b4354db1
VZ
185#if wxUSE_MARKUP
186bool wxToggleButton::DoSetLabelMarkup(const wxString& markup)
1db8dc4a 187{
b4354db1
VZ
188 wxCHECK_MSG( m_widget != NULL, false, "invalid toggle button" );
189
190 const wxString stripped = RemoveMarkup(markup);
191 if ( stripped.empty() && !markup.empty() )
91af0895 192 return false;
1db8dc4a 193
b4354db1
VZ
194 wxControl::SetLabel(stripped);
195
b29bd6b4
VZ
196 if ( !HasFlag(wxBU_NOTEXT) )
197 {
198 GtkLabel * const label = GTKGetLabel();
199 wxCHECK_MSG( label, false, "no label in this toggle button?" );
1db8dc4a 200
b29bd6b4
VZ
201 GTKSetLabelWithMarkupForLabel(label, markup);
202 }
ad60f9e7 203
91af0895 204 return true;
1db8dc4a 205}
b4354db1 206#endif // wxUSE_MARKUP
1db8dc4a 207
b4354db1 208GtkLabel *wxToggleButton::GTKGetLabel() const
1db8dc4a 209{
b4354db1
VZ
210 GtkWidget* child = gtk_bin_get_child(GTK_BIN(m_widget));
211 return GTK_LABEL(child);
1db8dc4a
VZ
212}
213
b4354db1 214void wxToggleButton::DoApplyWidgetStyle(GtkRcStyle *style)
1db8dc4a 215{
9dc44eff
PC
216 GTKApplyStyle(m_widget, style);
217 GTKApplyStyle(gtk_bin_get_child(GTK_BIN(m_widget)), style);
1db8dc4a
VZ
218}
219
1db8dc4a
VZ
220// Get the "best" size for this control.
221wxSize wxToggleButton::DoGetBestSize() const
222{
b4354db1 223 wxSize ret(wxAnyButton::DoGetBestSize());
91af0895 224
8ab696e0
RR
225 if (!HasFlag(wxBU_EXACTFIT))
226 {
227 if (ret.x < 80) ret.x = 80;
228 }
91af0895 229
9f884528
RD
230 CacheBestSize(ret);
231 return ret;
1db8dc4a
VZ
232}
233
9d522606
RD
234// static
235wxVisualAttributes
236wxToggleButton::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant))
237{
238 return GetDefaultAttributesFromGTKWidget(gtk_toggle_button_new);
239}
240
1db8dc4a 241#endif // wxUSE_TOGGLEBTN