1 //------------------------------------------------------------------------------
2 // emRadioButton.cpp
3 //
4 // Copyright (C) 2005-2011,2014-2016 Oliver Hamann.
5 //
6 // Homepage: http://eaglemode.sourceforge.net/
7 //
8 // This program is free software: you can redistribute it and/or modify it under
9 // the terms of the GNU General Public License version 3 as published by the
10 // Free Software Foundation.
11 //
12 // This program is distributed in the hope that it will be useful, but WITHOUT
13 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 // FOR A PARTICULAR PURPOSE. See the GNU General Public License version 3 for
15 // more details.
16 //
17 // You should have received a copy of the GNU General Public License version 3
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
19 //------------------------------------------------------------------------------
20 
21 #include <emCore/emRadioButton.h>
22 
23 
emRadioButton(ParentArg parent,const emString & name,const emString & caption,const emString & description,const emImage & icon)24 emRadioButton::emRadioButton(
25 	ParentArg parent, const emString & name, const emString & caption,
26 	const emString & description, const emImage & icon
27 )
28 	: emCheckButton(parent,name,caption,description,icon)
29 {
30 	Mechanism * mechanism;
31 
32 	SetShownRadioed(true);
33 	Mech=NULL;
34 	MechIndex=-1;
35 	if (GetParent()) {
36 		mechanism=dynamic_cast<emRadioButton::Mechanism*>(GetParent());
37 		if (mechanism) mechanism->Add(this);
38 	}
39 }
40 
41 
~emRadioButton()42 emRadioButton::~emRadioButton()
43 {
44 	if (Mech) Mech->Remove(this);
45 }
46 
47 
Mechanism()48 emRadioButton::Mechanism::Mechanism()
49 {
50 	Array.SetTuningLevel(4);
51 	CheckIndex=-1;
52 }
53 
54 
~Mechanism()55 emRadioButton::Mechanism::~Mechanism()
56 {
57 	RemoveAll();
58 }
59 
60 
Add(emRadioButton * radioButton)61 void emRadioButton::Mechanism::Add(emRadioButton * radioButton)
62 {
63 	if (radioButton->Mech) radioButton->Mech->Remove(radioButton);
64 	radioButton->Mech=this;
65 	radioButton->MechIndex=Array.GetCount();
66 	Array.Add(radioButton);
67 	if (radioButton->IsChecked()) {
68 		if (CheckIndex>=0) {
69 			radioButton->SetChecked(false);
70 		}
71 		else {
72 			CheckIndex=Array.GetCount()-1;
73 			CheckSignal.Signal(radioButton->GetScheduler());
74 			CheckChanged();
75 		}
76 	}
77 }
78 
79 
AddAll(emPanel * parent)80 void emRadioButton::Mechanism::AddAll(emPanel * parent)
81 {
82 	emRadioButton * rb;
83 	emPanel * p;
84 
85 	for (p=parent->GetFirstChild(); p; p=p->GetNext()) {
86 		rb=dynamic_cast<emRadioButton*>(p);
87 		if (rb) Add(rb);
88 	}
89 }
90 
91 
Remove(emRadioButton * radioButton)92 void emRadioButton::Mechanism::Remove(emRadioButton * radioButton)
93 {
94 	RemoveByIndex(GetIndexOf(radioButton));
95 }
96 
97 
RemoveByIndex(int index)98 void emRadioButton::Mechanism::RemoveByIndex(int index)
99 {
100 	emScheduler * scheduler;
101 	emRadioButton * rb;
102 	int i;
103 
104 	if (index>=0 && index<Array.GetCount()) {
105 		rb=Array[index];
106 		rb->Mech=NULL;
107 		rb->MechIndex=-1;
108 		scheduler=&rb->GetScheduler();
109 		Array.Remove(index);
110 		for (i=Array.GetCount()-1; i>=index; i--) Array[i]->MechIndex=i;
111 		if (CheckIndex>=index) {
112 			if (CheckIndex==index) CheckIndex=-1;
113 			else CheckIndex--;
114 			CheckSignal.Signal(*scheduler);
115 			CheckChanged();
116 		}
117 	}
118 }
119 
120 
RemoveAll()121 void emRadioButton::Mechanism::RemoveAll()
122 {
123 	emScheduler * scheduler;
124 	emRadioButton * rb;
125 	int i;
126 
127 	i=Array.GetCount()-1;
128 	if (i>=0) {
129 		scheduler=&Array[0]->GetScheduler();
130 		do {
131 			rb=Array[i];
132 			rb->Mech=NULL;
133 			rb->MechIndex=-1;
134 			i--;
135 		} while (i>=0);
136 		Array.Clear();
137 		if (CheckIndex>=0) {
138 			CheckIndex=-1;
139 			CheckSignal.Signal(*scheduler);
140 			CheckChanged();
141 		}
142 	}
143 }
144 
145 
SetChecked(emRadioButton * radioButton)146 void emRadioButton::Mechanism::SetChecked(emRadioButton * radioButton)
147 {
148 	SetCheckIndex(GetIndexOf(radioButton));
149 }
150 
151 
SetCheckIndex(int index)152 void emRadioButton::Mechanism::SetCheckIndex(int index)
153 {
154 	emScheduler * scheduler;
155 	int old;
156 
157 	if (index<-1 || index>=Array.GetCount()) index=-1;
158 	if (CheckIndex!=index) {
159 		// Remember, this could be called recursively!
160 		scheduler=&Array[0]->GetScheduler();
161 		if (CheckIndex>=0 && Array[CheckIndex]->IsChecked()) {
162 			old=CheckIndex;
163 			CheckIndex=-1;
164 			Array[old]->SetChecked(false);
165 			if (CheckIndex!=-1) return;
166 		}
167 		CheckIndex=index;
168 		if (CheckIndex>=0 && !Array[CheckIndex]->IsChecked()) {
169 			Array[CheckIndex]->SetChecked(true);
170 			if (CheckIndex!=index) return;
171 		}
172 		CheckSignal.Signal(*scheduler);
173 		CheckChanged();
174 	}
175 }
176 
177 
GetButton(int index) const178 emRadioButton * emRadioButton::Mechanism::GetButton(int index) const
179 {
180 	if (index>=0 && index<Array.GetCount()) {
181 		return Array[index];
182 	}
183 	return NULL;
184 }
185 
186 
187 
CheckChanged()188 void emRadioButton::Mechanism::CheckChanged()
189 {
190 }
191 
192 
LinearGroup(ParentArg parent,const emString & name,const emString & caption,const emString & description,const emImage & icon)193 emRadioButton::LinearGroup::LinearGroup(
194 	ParentArg parent, const emString & name, const emString & caption,
195 	const emString & description, const emImage & icon
196 )
197 	: emLinearGroup(parent,name,caption,description,icon)
198 {
199 }
200 
201 
~LinearGroup()202 emRadioButton::LinearGroup::~LinearGroup()
203 {
204 }
205 
206 
RasterGroup(ParentArg parent,const emString & name,const emString & caption,const emString & description,const emImage & icon)207 emRadioButton::RasterGroup::RasterGroup(
208 	ParentArg parent, const emString & name, const emString & caption,
209 	const emString & description, const emImage & icon
210 )
211 	: emRasterGroup(parent,name,caption,description,icon)
212 {
213 }
214 
215 
~RasterGroup()216 emRadioButton::RasterGroup::~RasterGroup()
217 {
218 }
219 
220 
Group(ParentArg parent,const emString & name,const emString & caption,const emString & description,const emImage & icon)221 emRadioButton::Group::Group(
222 	ParentArg parent, const emString & name, const emString & caption,
223 	const emString & description, const emImage & icon
224 )
225 	: emGroup(parent,name,caption,description,icon,0)
226 {
227 }
228 
229 
~Group()230 emRadioButton::Group::~Group()
231 {
232 }
233 
234 
Clicked()235 void emRadioButton::Clicked()
236 {
237 	if (Mech) Mech->SetChecked(this);
238 }
239 
240 
CheckChanged()241 void emRadioButton::CheckChanged()
242 {
243 	if (Mech) {
244 		if (IsChecked()) Mech->SetChecked(this);
245 		else if (Mech->GetChecked()==this) Mech->SetChecked(NULL);
246 	}
247 }
248 
249 
GetHowTo() const250 emString emRadioButton::GetHowTo() const
251 {
252 	emString h;
253 
254 	h=emCheckButton::GetHowTo();
255 	h+=HowToRadioButton;
256 	return h;
257 }
258 
259 
260 const char * emRadioButton::HowToRadioButton=
261 	"\n"
262 	"\n"
263 	"RADIO BUTTON\n"
264 	"\n"
265 	"This is a radio button. It is a check button with changed behavior: In a set of\n"
266 	"radio buttons, only one button can have checked state. When triggering a radio\n"
267 	"button, that button is checked and all the other radio buttons of the set are\n"
268 	"unchecked. There is no way to uncheck a radio button directly.\n"
269 ;
270