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