Consolidate cocoa view/control/cell label setting into wxControl::CocoaSetLabelForObject.
[wxWidgets.git] / src / cocoa / radiobut.mm
1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/cocoa/radiobut.mm
3 // Purpose:     wxRadioButton
4 // Author:      David Elliott
5 // Modified by:
6 // Created:     2003/03/16
7 // RCS-ID:      $Id$
8 // Copyright:   (c) 2003 David Elliott
9 // Licence:     wxWidgets licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #include "wx/wxprec.h"
13
14 #if wxUSE_RADIOBTN
15
16 #include "wx/radiobut.h"
17
18 #ifndef WX_PRECOMP
19     #include "wx/log.h"
20     #include "wx/app.h"
21 #endif //WX_PRECOMP
22
23 #import <AppKit/NSButton.h>
24 #include "wx/cocoa/string.h"
25 #include "wx/cocoa/autorelease.h"
26
27 #include "wx/listimpl.cpp"
28
29 WX_DEFINE_LIST(wxRadioButtonList);
30
31 IMPLEMENT_DYNAMIC_CLASS(wxRadioButton, wxControl)
32 // wxRadioButtonBase == wxControl
33 BEGIN_EVENT_TABLE(wxRadioButton, wxControl)
34 END_EVENT_TABLE()
35 WX_IMPLEMENT_COCOA_OWNER(wxRadioButton,NSButton,NSControl,NSView)
36
37 bool wxRadioButton::Create(wxWindow *parent, wxWindowID winid,
38            const wxString& label,
39            const wxPoint& pos,
40            const wxSize& size,
41            long style,
42            const wxValidator& validator,
43            const wxString& name)
44 {
45     wxAutoNSAutoreleasePool pool;
46     m_radioMaster = NULL;
47     if(!CreateControl(parent,winid,pos,size,style,validator,name))
48         return false;
49     if(style&wxRB_GROUP)
50     {
51         m_radioMaster = this;
52         m_radioSlaves.Append(this);
53     }
54     else if(style&wxRB_SINGLE)
55         m_radioMaster = NULL;
56     else
57     {
58         for(wxWindowList::compatibility_iterator siblingNode= GetParent()->GetChildren().GetLast();
59             siblingNode;
60             siblingNode = siblingNode->GetPrevious())
61         {
62             wxRadioButton *radioButton  = wxDynamicCast(siblingNode->GetData(),wxRadioButton);
63             if(radioButton && radioButton!=this)
64             {
65                 m_radioMaster = radioButton->m_radioMaster;
66                 wxASSERT_MSG(m_radioMaster,
67                     wxT("Previous radio button should be part of a group"));
68                 // Don't crash, assume user meant wxRB_SINGLE
69                 if(m_radioMaster)
70                     m_radioMaster->m_radioSlaves.Append(this);
71                 break;
72             }
73         }
74     }
75
76     m_cocoaNSView = NULL;
77     SetNSButton([[NSButton alloc] initWithFrame: MakeDefaultNSRect(size)]);
78     [m_cocoaNSView release];
79     [GetNSButton() setButtonType: NSRadioButton];
80     CocoaSetLabelForObject(label, GetNSButton());
81     // If it's the first in a group, it should be selected
82     if(style&wxRB_GROUP)
83         [GetNSButton() setState: NSOnState];
84     [GetNSControl() sizeToFit];
85
86     if(m_parent)
87         m_parent->CocoaAddChild(this);
88     SetInitialFrameRect(pos,size);
89
90     return true;
91 }
92
93 wxRadioButton::~wxRadioButton()
94 {
95     if(m_radioMaster==this)
96     {
97         // First get rid of ourselves (we should ALWAYS be at the head)
98         wxRadioButtonList::compatibility_iterator slaveNode =
99             m_radioSlaves.GetFirst();
100         wxASSERT(slaveNode);
101         wxASSERT(slaveNode->GetData() == this);
102         m_radioSlaves.Erase(slaveNode);
103
104         // Now find the new master
105         wxRadioButton *newMaster = NULL;
106         slaveNode = m_radioSlaves.GetFirst();
107         if(slaveNode)
108             newMaster = slaveNode->GetData();
109
110         // For each node (including the new master) set the master, remove
111         // it from this list, and add it to the new master's list
112         for(; slaveNode; slaveNode = m_radioSlaves.GetFirst())
113         {
114             wxRadioButton *radioButton = slaveNode->GetData();
115             wxASSERT(radioButton->m_radioMaster == this);
116             radioButton->m_radioMaster = newMaster;
117             newMaster->m_radioSlaves.Append(radioButton);
118             m_radioSlaves.Erase(slaveNode);
119         }
120     }
121     else if(m_radioMaster)
122     {
123         m_radioMaster->m_radioSlaves.DeleteObject(this);
124         m_radioMaster = NULL;
125     }
126     // normal stuff
127     DisassociateNSButton(GetNSButton());
128 }
129
130 void wxRadioButton::SetValue(bool value)
131 {
132     if(value)
133     {
134         [GetNSButton() setState: NSOnState];
135         Cocoa_DeselectOtherButtonsInTheGroup();
136     }
137     else
138         [GetNSButton() setState: NSOffState];
139 }
140
141 bool wxRadioButton::GetValue() const
142 {
143     int state = [GetNSButton() state];
144     wxASSERT(state!=NSMixedState);
145     return state==NSOnState;
146 }
147
148 /**
149  * If this radio button is part of a group, this method turns off every other
150  * button in the group.  If this radio button is not part of a group, this
151  * method does absolutely nothing.
152  */
153 void wxRadioButton::Cocoa_DeselectOtherButtonsInTheGroup(void)
154 {
155     if(m_radioMaster)
156     {
157         for(wxRadioButtonList::compatibility_iterator slaveNode =
158                 m_radioMaster->m_radioSlaves.GetFirst();
159             slaveNode; slaveNode = slaveNode->GetNext())
160         {
161             wxRadioButton *radioButton = slaveNode->GetData();
162             if(radioButton!=this)
163                 radioButton->SetValue(false);
164         }
165     }
166 }
167
168 void wxRadioButton::Cocoa_wxNSButtonAction(void)
169 {
170     wxLogTrace(wxTRACE_COCOA,wxT("wxRadioButton"));
171     if([GetNSButton() state] == NSOnState)
172     {
173         Cocoa_DeselectOtherButtonsInTheGroup();
174     }
175     wxCommandEvent event(wxEVT_COMMAND_RADIOBUTTON_SELECTED, GetId());
176     InitCommandEvent(event); //    event.SetEventObject(this);
177     event.SetInt(GetValue());
178     Command(event);
179 }
180
181 #endif