Spinning Topp Logo BlackTopp Studios
inc
radiobutton.cpp
1 // © Copyright 2010 - 2016 BlackTopp Studios Inc.
2 /* This file is part of The Mezzanine Engine.
3 
4  The Mezzanine Engine is free software: you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation, either version 3 of the License, or
7  (at your option) any later version.
8 
9  The Mezzanine Engine is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with The Mezzanine Engine. If not, see <http://www.gnu.org/licenses/>.
16 */
17 /* The original authors have included a copy of the license specified above in the
18  'Docs' folder. See 'gpl.txt'
19 */
20 /* We welcome the use of the Mezzanine engine to anyone, including companies who wish to
21  Build professional software and charge for their product.
22 
23  However there are some practical restrictions, so if your project involves
24  any of the following you should contact us and we will try to work something
25  out:
26  - DRM or Copy Protection of any kind(except Copyrights)
27  - Software Patents You Do Not Wish to Freely License
28  - Any Kind of Linking to Non-GPL licensed Works
29  - Are Currently In Violation of Another Copyright Holder's GPL License
30  - If You want to change our code and not add a few hundred MB of stuff to
31  your distribution
32 
33  These and other limitations could cause serious legal problems if you ignore
34  them, so it is best to simply contact us or the Free Software Foundation, if
35  you have any questions.
36 
37  Joseph Toppi - toppij@gmail.com
38  John Blackwood - makoenergy02@gmail.com
39 */
40 #ifndef _uiradiobutton_cpp
41 #define _uiradiobutton_cpp
42 
43 #include "UI/radiobutton.h"
44 #include "UI/screen.h"
45 
46 #include "stringtool.h"
47 #include "serialization.h"
48 #include "exception.h"
49 
50 #include <algorithm>
51 
52 namespace Mezzanine
53 {
54  namespace UI
55  {
56  ///////////////////////////////////////////////////////////////////////////////
57  // RadioButtonGroup Static Members
58 
59  const String RadioButtonGroup::EventGroupButtonSelected = "GroupButtonSelected";
60 
61  ///////////////////////////////////////////////////////////////////////////////
62  // RadioButtonGroup Methods
63 
65  CurrentSelection(NULL)
66  { this->AddEvent(RadioButtonGroup::EventGroupButtonSelected); }
67 
69  { }
70 
71  ///////////////////////////////////////////////////////////////////////////////
72  // Utility Methods
73 
75  {
76  RadioButtonIterator RadioIt = std::find(this->GroupButtons.begin(),this->GroupButtons.end(),ToAdd);
77  if( RadioIt == this->GroupButtons.end() ) {
78  this->GroupButtons.push_back( ToAdd );
79  }
80  }
81 
83  {
84  return this->GroupButtons.size();
85  }
86 
88  {
89  RadioButtonIterator RadioIt = std::find(this->GroupButtons.begin(),this->GroupButtons.end(),ToRemove);
90  if( RadioIt != this->GroupButtons.end() ) {
91  this->GroupButtons.erase( RadioIt );
92  }
93  }
94 
96  {
97  this->DeselectOtherButtons(ToSelect);
98  this->CurrentSelection = ToSelect;
99  if( this->CurrentSelection != NULL ) {
100  this->CurrentSelection->ManualSelect(true);
101  }
102  }
103 
105  {
106  for( RadioButtonIterator RadioIt = this->GroupButtons.begin() ; RadioIt != this->GroupButtons.end() ; ++RadioIt )
107  {
108  if( (*RadioIt) != Exclude ) {
109  (*RadioIt)->ManualSelect(false);
110  }
111  }
112  }
113 
115  { return this->CurrentSelection; }
116 
118  { return this->GroupButtons.begin(); }
119 
121  { return this->GroupButtons.end(); }
122 
124  { return this->GroupButtons.begin(); }
125 
127  { return this->GroupButtons.end(); }
128 
129  ///////////////////////////////////////////////////////////////////////////////
130  // Internal Methods
131 
133  {
134  if( this->CurrentSelection != Selected ) {
135  this->CurrentSelection = Selected;
136  this->DeselectOtherButtons(Selected);
137 
138  WidgetEventArgumentsPtr Args( new WidgetEventArguments( RadioButtonGroup::EventGroupButtonSelected,Selected->GetName()) );
139  this->FireEvent(Args);
140  }
141  }
142 
143  ///////////////////////////////////////////////////////////////////////////////
144  // RadioButton Static Members
145 
146  const String RadioButton::TypeName = "RadioButton";
147 
148  ///////////////////////////////////////////////////////////////////////////////
149  // RadioButton Methods
150 
152  CheckBox(Parent)
153  { }
154 
155  RadioButton::RadioButton(const String& RendName, Screen* Parent) :
156  CheckBox(RendName,Parent)
157  { }
158 
159  RadioButton::RadioButton(const String& RendName, const UnifiedRect& RendRect, Screen* Parent) :
160  CheckBox(RendName,RendRect,Parent)
161  { }
162 
163  RadioButton::RadioButton(const XML::Node& XMLNode, Screen* Parent) :
164  CheckBox(Parent)
165  { this->ProtoDeSerialize(XMLNode); }
166 
168  { this->RemoveFromButtonGroup(); }
169 
171  {
172  this->Widget::ProtoSerializeImpl(SelfRoot);
173  this->ProtoSerializeGroupButtons(SelfRoot);
174  }
175 
177  {
178  this->Widget::ProtoDeSerializeImpl(SelfRoot);
179  this->ProtoDeSerializeGroupButtons(SelfRoot);
180  }
181 
182  ///////////////////////////////////////////////////////////////////////////////
183  // Utility Methods
184 
186  { return RadioButton::TypeName; }
187 
188  ///////////////////////////////////////////////////////////////////////////////
189  // RadioButton Properties
190 
191  ///////////////////////////////////////////////////////////////////////////////
192  // RadioButton Configuration
193 
195  {
196  RadioButtonGroup* OtherGroup = ToAdd->_GetButtonGroup();
197  if( this->ButtonGroup != NULL ) {
198  if( OtherGroup == NULL ) {
199  this->ButtonGroup->AddButtonToGroup(ToAdd);
200  }else{
201  MEZZ_EXCEPTION(ExceptionBase::INVALID_STATE_EXCEPTION,"Attempting to add RadioButton to another group when it already has one.");
202  }
203  }else{
204  if( OtherGroup != NULL ) {
205  OtherGroup->AddButtonToGroup(this);
206  }else{
207  OtherGroup = new RadioButtonGroup();
208  OtherGroup->AddButtonToGroup(this);
209  OtherGroup->AddButtonToGroup(ToAdd);
210  }
211  }
212  }
213 
215  {
216  if( this->ButtonGroup != NULL ) {
217  this->ButtonGroup->RemoveButtonFromGroup(this);
218 
219  if( this->ButtonGroup->GetNumButtons() == 0 ) {
220  delete this->ButtonGroup;
221  }
222 
223  this->ButtonGroup = NULL;
224  }
225  }
226 
227  ///////////////////////////////////////////////////////////////////////////////
228  // Serialization
229 
231  {
232  XML::Node ButtonsNode = SelfRoot.AppendChild( "GroupButtons" );
233 
234  if( ButtonsNode.AppendAttribute("Version").SetValue("1") ) {
237  for( RadioButtonGroup::ConstRadioButtonIterator ButIt = ButBeg ; ButIt != ButEnd ; ++ButIt )
238  {
239  XML::Node ButtonNode = ButtonsNode.AppendChild( "GroupButton" );
240 
241  if( ButtonNode.AppendAttribute("Version").SetValue("1") &&
242  ButtonNode.AppendAttribute("GroupButtonName").SetValue( (*ButIt)->GetName() ) )
243  {
244  continue;
245  }else{
246  SerializeError("Create XML Version Attribute","GroupButton",true);
247  }
248  }
249  }else{
250  SerializeError("Create XML Version Attribute","GroupButtons",true);
251  }
252  }
253 
255  {
256  this->CheckBox::ProtoSerializeProperties(SelfRoot);
257  }
258 
260  {
261  this->RemoveFromButtonGroup();
262 
263  XML::Attribute CurrAttrib;
264  XML::Node ButtonsNode = SelfRoot.GetChild( "GroupButtons" );
265 
266  if( !ButtonsNode.Empty() ) {
267  if( ButtonsNode.GetAttribute("Version").AsInt() == 1 ) {
268  for( XML::NodeIterator ButtonNodeIt = ButtonsNode.begin() ; ButtonNodeIt != ButtonsNode.end() ; ++ButtonNodeIt )
269  {
270  if( (*ButtonNodeIt).GetAttribute("Version").AsInt() == 1 ) {
271  String GroupButtonName;
272 
273  CurrAttrib = (*ButtonNodeIt).GetAttribute("GroupButtonName");
274  if( !CurrAttrib.Empty() )
275  GroupButtonName = CurrAttrib.AsString();
276 
277  if( !GroupButtonName.empty() ) {
278  Widget* NamedButton = this->ParentScreen->GetWidget(GroupButtonName);
279  if( NamedButton != NULL && NamedButton->GetTypeName() == RadioButton::TypeName ) {
280  this->AddToButtonGroup( static_cast<RadioButton*>( NamedButton ) );
281  }else{
282  StringStream ExceptionStream;
283  ExceptionStream << "Named Widget \"" << GroupButtonName << "\" not found or not a RadioButton when deserializing Widget named \"" << this->GetName() << "\".";
285  }
286  }
287  }else{
288  MEZZ_EXCEPTION(ExceptionBase::INVALID_VERSION_EXCEPTION,"Incompatible XML Version for " + String("GroupButtons") + ": Not Version 1.");
289  }
290  }
291  }else{
292  MEZZ_EXCEPTION(ExceptionBase::INVALID_VERSION_EXCEPTION,"Incompatible XML Version for " + String("GroupButtons") + ": Not Version 1.");
293  }
294  }
295  }
296 
298  {
299  this->CheckBox::ProtoDeSerializeProperties(SelfRoot);
300 
301  XML::Attribute CurrAttrib;
302  XML::Node PropertiesNode = SelfRoot.GetChild( RadioButton::GetSerializableName() + "Properties" );
303 
304  if( !PropertiesNode.Empty() ) {
305  if(PropertiesNode.GetAttribute("Version").AsInt() == 1) {
306  CurrAttrib = PropertiesNode.GetAttribute("LockoutTime");
307  if( !CurrAttrib.Empty() )
308  this->SelectLock = StringTools::ConvertToBool( CurrAttrib.AsString() );
309  }else{
310  MEZZ_EXCEPTION(ExceptionBase::INVALID_VERSION_EXCEPTION,"Incompatible XML Version for " + (RadioButton::GetSerializableName() + "Properties") + ": Not Version 1.");
311  }
312  }else{
313  MEZZ_EXCEPTION(ExceptionBase::II_IDENTITY_NOT_FOUND_EXCEPTION,RadioButton::GetSerializableName() + "Properties" + " was not found in the provided XML node, which was expected.");
314  }
315  }
316 
318  {
319  return RadioButton::TypeName;
320  }
321 
322  ///////////////////////////////////////////////////////////////////////////////
323  // Internal Event Methods
324 
326  {
327  if( this->ButtonGroup != NULL ) {
328  this->ButtonGroup->_NotifyButtonSelected(this);
329  }
330  this->CheckBox::_OnSelected();
331  }
332 
334  {
335  // The updated selection button is written to the group first, so we should be able to tell if we need to block deselection.
336  // Radio buttons shouldn't deselect themselves. The initial state should be the only time a radio button group should be without a selection.
337  if( this->ButtonGroup ) {
338  if( this->ButtonGroup->GetCurrentSelection() != this ) {
339  this->CheckBox::_OnDeselected();
340  }
341  }else{
342  this->CheckBox::_OnDeselected();
343  }
344  }
345 
346  ///////////////////////////////////////////////////////////////////////////////
347  // Internal Methods
348 
350  {
351  return this->ButtonGroup;
352  }
353 
354  ///////////////////////////////////////////////////////////////////////////////
355  // RadioButtonFactory Methods
356 
358  { return RadioButton::TypeName; }
359 
361  { return new RadioButton(RendName,Parent); }
362 
363  RadioButton* RadioButtonFactory::CreateRadioButton(const String& RendName, const UnifiedRect& RendRect, Screen* Parent)
364  { return new RadioButton(RendName,RendRect,Parent); }
365 
367  { return new RadioButton(XMLNode,Parent); }
368 
370  { return new RadioButton(Parent); }
371 
372  Widget* RadioButtonFactory::CreateWidget(const String& RendName, const NameValuePairMap& Params, Screen* Parent)
373  { return this->CreateRadioButton(RendName,Parent); }
374 
375  Widget* RadioButtonFactory::CreateWidget(const String& RendName, const UnifiedRect& RendRect, const NameValuePairMap& Params, Screen* Parent)
376  { return this->CreateRadioButton(RendName,RendRect,Parent); }
377 
379  { return this->CreateRadioButton(XMLNode,Parent); }
380 
382  { delete static_cast<RadioButton*>( ToBeDestroyed ); }
383  }//UI
384 }//Mezzanine
385 
386 #endif
RadioButtonContainer::iterator RadioButtonIterator
Iterator type for RadioButton instances stored by this class.
Definition: radiobutton.h:60
static const String EventGroupButtonSelected
Event name for when the selection among radio buttons has changed.
Definition: radiobutton.h:65
RadioButtonIterator RadioButtonBegin()
Gets an iterator to the first RadioButton.
Attribute AppendAttribute(const Char8 *Name)
Creates an Attribute and puts it at the end of this Nodes attributes.
virtual void ProtoSerializeGroupButtons(XML::Node &SelfRoot) const
Convert the Group Buttons of this class to an XML::Node ready for serialization.
const String & GetName() const
Gets the name of this renderable.
Definition: renderable.cpp:77
virtual String GetWidgetTypeName() const
Gets the name of the Widget that is created by this factory.
A light-weight handle for manipulating attributes in DOM tree.
Definition: attribute.h:74
virtual void _OnDeselected()
Self logic to be executed when this checkbox is deselected.
Definition: checkbox.cpp:211
virtual RadioButton * CreateRadioButton(const String &RendName, Screen *Parent)
Creates a new RadioButton.
virtual void DestroyWidget(Widget *ToBeDestroyed)
Destroys a Widget created by this factory.
Boole SelectLock
Stores whether or not the current state of this CheckBox is locked.
Definition: checkbox.h:79
~RadioButtonGroup()
Class destructor.
Definition: radiobutton.cpp:68
virtual void RemoveFromButtonGroup()
Removes this RadioButton from the RadioButtonGroup it currently belongs to.
virtual const String & GetTypeName() const
Gets the type of widget this is.
Definition: widget.cpp:156
Thrown when the requested identity could not be found.
Definition: exception.h:94
#define MEZZ_EXCEPTION(num, desc)
An easy way to throw exceptions with rich information.
Definition: exception.h:3048
virtual void ProtoDeSerializeProperties(const XML::Node &SelfRoot)
Take the data stored in an XML Node and overwrite the properties of this object with it...
Definition: checkbox.cpp:157
void RemoveButtonFromGroup(RadioButton *ToRemove)
Removes a RadioButton from this group.
Definition: radiobutton.cpp:87
A simple reference counting pointer.
Definition: countedptr.h:70
Thrown when a version is accessed/parsed/required and it cannot work correctly or is missing...
Definition: exception.h:112
static const String TypeName
String containing the type name for this class: "RadioButton".
Definition: radiobutton.h:134
const Char8 * AsString(const Char8 *def="") const
Attempts to convert the value of the attribute to a String and returns the results.
RadioButtonGroup * ButtonGroup
A pointer to the group this RadioButton belongs to.
Definition: radiobutton.h:138
void DeselectOtherButtons(RadioButton *Exclude)
Deselects all but one (or just all) button(s) in this group.
bool Empty() const
Is this storing anything at all?
This implements the exception hiearchy for Mezzanine.
std::stringstream StringStream
A Datatype used for streaming operations with strings.
Definition: datatypes.h:176
The interface for serialization.
bool SetValue(const Char8 *rhs)
Set the value of this.
This class represents a 2D rect which can express the size and position of a renderable on screen...
Definition: unifieddim.h:661
virtual Widget * CreateWidget(Screen *Parent)
Creates a Widget of the type represented by this factory.
Boole ConvertToBool(const String &ToConvert, const Boole Default)
Converts a string into a Boole.
Definition: stringtool.cpp:379
virtual void ProtoSerializeImpl(XML::Node &SelfRoot) const
Implementation method for serializing additional sets of data.
Child node iterator (a bidirectional iterator over a collection of Node)
Definition: nodeiterator.h:77
A light-weight handle for manipulating nodes in DOM tree.
Definition: node.h:89
void AddButtonToGroup(RadioButton *ToAdd)
Adds a RadioButton to this group.
Definition: radiobutton.cpp:74
iterator begin() const
Get a Child node iterator that references the first child Node.
virtual RadioButtonGroup * _GetButtonGroup() const
Gets the RadioButtonGroup this button belongs to.
int AsInt(int def=0) const
Attempts to convert the value of the attribute to an int and returns the results. ...
RadioButtonGroup()
Class constructor.
Definition: radiobutton.cpp:64
iterator end() const
Get a Child node iterator that references one past the last child Node.
bool Empty() const
Is this storing anything at all?
virtual void ProtoDeSerializeImpl(const XML::Node &SelfRoot)
Implementation method for deseriailizing additional sets of data.
This is the base class for all widgets.
Definition: widget.h:126
RadioButtonContainer GroupButtons
A container storing all the RadioButtons belonging to this group.
Definition: radiobutton.h:69
Event * AddEvent(const String &EventName)
Creates a new event this Publisher can fire.
RadioButton * CurrentSelection
A pointer to the RadioButton that is the current selection, or NULL if none are selected.
Definition: radiobutton.h:72
virtual void ProtoDeSerializeImpl(const XML::Node &SelfRoot)
Implementation method for deseriailizing additional sets of data.
Definition: widget.cpp:105
RadioButtonContainer::const_iterator ConstRadioButtonIterator
Const Iterator type for RadioButton instances stored by this class.
Definition: radiobutton.h:62
void FireEvent(EventArgumentsPtr Args)
Fires an event.
Thrown when the available information should have worked but failed for unknown reasons.
Definition: exception.h:113
virtual void ProtoDeSerializeGroupButtons(const XML::Node &SelfRoot)
Take the data stored in an XML Node and overwrite the Group Buttons of this object with it...
Thrown when parameters are checked at runtime and found invalid.
Definition: exception.h:108
virtual void ProtoSerializeProperties(XML::Node &SelfRoot) const
Convert the properties of this class to an XML::Node ready for serialization.
virtual ~RadioButton()
Class destructor.
virtual void AddToButtonGroup(RadioButton *GroupButton)
Adds this RadioButton to the same RadioButtonGroup as the specified RadioButton.
RadioButton * GetCurrentSelection() const
Gets the button that is currently selected among this group of buttons.
void SelectButton(RadioButton *ToSelect)
Makes a RadioButton in this group the selection, deselecting all other RadioButtons in the group...
Definition: radiobutton.cpp:95
RadioButton(Screen *Parent)
Blank constructor.
virtual void ProtoDeSerializeProperties(const XML::Node &SelfRoot)
Take the data stored in an XML Node and overwrite the properties of this object with it...
virtual Widget * GetWidget(const String &Name)
Gets a widget in this screen by name.
Definition: screen.cpp:573
virtual void ProtoSerializeImpl(XML::Node &SelfRoot) const
Implementation method for serializing additional sets of data.
Definition: widget.cpp:97
static String GetSerializableName()
Get the name of the the XML tag the Renderable class will leave behind as its instances are serialize...
This is a class designed to facilitate operations across an entire group of RadioButtons.
Definition: radiobutton.h:54
The bulk of the engine components go in this namspace.
Definition: actor.cpp:56
unsigned long Whole
Whole is an unsigned integer, it will be at least 32bits in size.
Definition: datatypes.h:151
RadioButtonIterator RadioButtonEnd()
Gets an iterator to one passed the last RadioButton.
virtual void ManualSelect(Boole Select)
Manually select or deselect this checkbox.
Definition: checkbox.cpp:120
virtual const String & GetTypeName() const
Gets the type of widget this is.
virtual void _OnDeselected()
Self logic to be executed when this checkbox is deselected.
virtual void ProtoDeSerialize(const XML::Node &SelfRoot)
Take the data stored in an XML Node and overwrite this object with it.
virtual void _OnSelected()
Self logic to be executed when this checkbox is selected.
Definition: checkbox.cpp:202
This is a simple widget for storing a bool value.
Definition: checkbox.h:55
This is a simple widget where only one of it's selections can be selected at a time.
Definition: radiobutton.h:130
void SerializeError(const String &FailedTo, const String &ClassName, Boole SOrD)
Simply does some string concatenation, then throws an Exception.
void _NotifyButtonSelected(RadioButton *Selected)
Notifies this group a button has been selected.
Node AppendChild(NodeType Type=NodeElement)
Creates a Node and makes it a child of this one.
virtual void ProtoSerializeProperties(XML::Node &SelfRoot) const
Convert the properties of this class to an XML::Node ready for serialization.
Definition: checkbox.cpp:142
std::map< String, String > NameValuePairMap
This is a datatype mostly used for describing settings or parameters that can't be declared in advanc...
Definition: datatypes.h:209
This class is a helper class for creating UI's. It is responsible for storing and keeping track of al...
Definition: screen.h:142
std::string String
A datatype used to a series of characters.
Definition: datatypes.h:159
Attribute GetAttribute(const Char8 *Name) const
Attempt to get an Attribute on this Node with a given name.
virtual void _OnSelected()
Self logic to be executed when this checkbox is selected.
Node GetChild(const Char8 *Name) const
Attempt to get a child Node with a given name.
Whole GetNumButtons() const
Gets the number of buttons in this group.
Definition: radiobutton.cpp:82
Screen * ParentScreen
A pointer to the Screen that created this Renderable.
Definition: renderable.h:72
This is the base class for widget specific event arguments.
Definition: widget.h:60