Spinning Topp Logo BlackTopp Studios
inc
button.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 _uibutton_cpp
41 #define _uibutton_cpp
42 
43 #include "UI/uimanager.h"
44 #include "UI/button.h"
45 #include "UI/screen.h"
46 
47 namespace Mezzanine
48 {
49  namespace UI
50  {
51  const String Button::TypeName = "Button";
52 
53  const String Button::EventActivated = "Activated";
54  const String Button::EventStandby = "Standby";
55  const String Button::EventDeactivated = "Deactivated";
56 
57  ///////////////////////////////////////////////////////////////////////////////
58  // Button Methods
59 
61  Widget(Parent),
62  Activation(AS_Deactivated),
63  LockoutTime(0),
64  MouseActivated(false)
65  { }
66 
67  Button::Button(const String& RendName, Screen* Parent) :
68  Widget(RendName,Parent),
69  Activation(AS_Deactivated),
70  LockoutTime(0),
71  MouseActivated(false)
72  { this->ConstructButton(); }
73 
74  Button::Button(const String& RendName, const UnifiedRect& RendRect, Screen* Parent) :
75  Widget(RendName,RendRect,Parent),
76  Activation(AS_Deactivated),
77  LockoutTime(0),
78  MouseActivated(false)
79  { this->ConstructButton(); }
80 
81  Button::Button(const XML::Node& XMLNode, Screen* Parent) :
82  Widget(Parent),
83  Activation(AS_Deactivated),
84  LockoutTime(0),
85  MouseActivated(false)
86  { this->ProtoDeSerialize(XMLNode); }
87 
89  { }
90 
92  {
93  // Check to see if this is an activation code
94  if( Code.IsDeviceButton() && this->ActivationCodes.count( Input::MetaCodeKey(Code) ) ) {
95  // Are we changing our activation state from a mouse code?
96  if( Code.IsMouseButton() ) {
97  if( this->IsHovered() && Input::BUTTON_PRESSING == Code.GetMetaValue() ) {
98  Boole Result = this->Activate();
99  if(Result)
100  this->MouseActivated = true;
101  return true;
102  }else if( Input::BUTTON_LIFTING == Code.GetMetaValue() ) {
103  this->Deactivate();
104  this->MouseActivated = false;
105  return true;
106  }
107  }else{
108  if( Input::BUTTON_PRESSING == Code.GetMetaValue() ) {
109  this->Activate();
110  return true;
111  }else if( Input::BUTTON_LIFTING == Code.GetMetaValue() ) {
112  this->Deactivate();
113  return true;
114  }
115  }
116  }
117  return false;
118  }
119 
121  {
123  // Add our button events
124  this->AddEvent(Button::EventActivated);
125  this->AddEvent(Button::EventStandby);
126  this->AddEvent(Button::EventDeactivated);
127  // Handle auto activation registration
128  UIManager* Manager = this->ParentScreen->GetManager();
129  if( Manager->ButtonAutoRegisterEnabled() ) {
130  const UIManager::InputContainer& Codes = Manager->GetAutoRegisteredCodes();
131  for( Whole X = 0 ; X < Codes.size() ; X++ )
132  this->BindActivationKeyOrButton(Codes.at(X));
133  }
134  }
135 
137  {
138  return (Input::KEY_FIRST < Code && Input::KEY_LAST > Code) ||
139  (Input::MOUSEBUTTON_FIRST <= Code && Input::MOUSEBUTTON_LAST >= Code) ||
140  (Input::CONTROLLERBUTTON_FIRST <= Code && Input::CONTROLLERBUTTON_LAST >= Code);
141  }
142 
144  {
145  if( this->Activation == AS_Activated )
146  return false;
147  if( this->LockoutTime != 0 && !( this->LockoutTimer.IsStopped() ) )
148  return false;
149 
150  this->Activation = AS_Activated;
151  this->_OnActivate();
152  return true;
153  }
154 
156  {
157  if( this->Activation == AS_Deactivated )
158  return false;
159  if( this->LockoutTime != 0 ) {
160  this->LockoutTimer.Reset(this->LockoutTime * 1000);
161  this->LockoutTimer.Start();
162  }
163 
164  this->Activation = AS_Deactivated;
165  this->_OnDeactivate();
166  return true;
167  }
168 
170  {
171  if(this->Activation == AS_Activation_Standby)
172  return false;
173 
175  this->_OnStandby();
176  return true;
177  }
178 
179  ///////////////////////////////////////////////////////////////////////////////
180  // Utility Methods
181 
182  void Button::SetLockoutTime(const UInt32& Milliseconds)
183  { this->LockoutTime = Milliseconds; }
184 
186  { return this->LockoutTimer; }
187 
189  { return ( this->Activation == AS_Activated ); }
190 
192  { return ( this->Activation == AS_Activation_Standby ); }
193 
195  { return ( this->Activation == AS_Deactivated ); }
196 
198  { return Button::TypeName; }
199 
200  ///////////////////////////////////////////////////////////////////////////////
201  // Binding Methods
202 
204  {
205  if( this->VertifyActivationCode( Code.GetCode() ) ) {
206  this->ActivationCodes.insert(Input::MetaCodeKey(Code));
207  }else{
208  MEZZ_EXCEPTION(ExceptionBase::PARAMETERS_EXCEPTION,"Attempting to bind an unsupported InputCode to a button.");
209  }
210  }
211 
213  {
214  this->ActivationCodes.erase(Input::MetaCodeKey(Code));
215  }
216 
218  {
219  for( ActivationCodeIterator ActIt = this->ActivationCodes.begin() ; ActIt != this->ActivationCodes.end() ; )
220  {
221  if( (*ActIt).GetKeyData().IsKeyboardButton() ) {
222  this->ActivationCodes.erase(ActIt++);
223  }else{
224  ++ActIt;
225  }
226  }
227  }
228 
230  {
231  for( ActivationCodeIterator ActIt = this->ActivationCodes.begin() ; ActIt != this->ActivationCodes.end() ; )
232  {
233  if( (*ActIt).GetKeyData().IsMouseButton() ) {
234  this->ActivationCodes.erase(ActIt++);
235  }else{
236  ++ActIt;
237  }
238  }
239  }
240 
242  {
243  for( ActivationCodeIterator ActIt = this->ActivationCodes.begin() ; ActIt != this->ActivationCodes.end() ; )
244  {
245  if( (*ActIt).GetKeyData().IsControllerButton() ) {
246  this->ActivationCodes.erase(ActIt++);
247  }else{
248  ++ActIt;
249  }
250  }
251  }
252 
254  {
255  this->ActivationCodes.clear();
256  }
257 
258  ///////////////////////////////////////////////////////////////////////////////
259  // Fetch Methods
260 
262  {
263  return this->ActivationCodes;
264  }
265 
266  ///////////////////////////////////////////////////////////////////////////////
267  // Serialization
268 
270  {
271  this->Widget::ProtoSerializeProperties(SelfRoot);
272 
273  XML::Node PropertiesNode = SelfRoot.AppendChild( Button::GetSerializableName() + "Properties" );
274 
275  if( PropertiesNode.AppendAttribute("Version").SetValue("1") )
276  {
277  // Only if we have a valid timer
278  if( this->LockoutTime != 0 ) {
279  if( PropertiesNode.AppendAttribute("LockoutTime").SetValue( this->LockoutTime ) == false ) {
280  SerializeError("Create XML Attribute Values",Button::GetSerializableName() + "Properties",true);
281  }
282  }
283 
284  XML::Node CodesNode = PropertiesNode.AppendChild( "ActivationCodes" );
285  for( ActivationCodeIterator CodeIt = this->ActivationCodes.begin() ; CodeIt != this->ActivationCodes.end() ; ++CodeIt )
286  {
287  (*CodeIt).GetKeyData().ProtoSerialize(CodesNode);
288  }
289 
290  return;
291  }else{
292  SerializeError("Create XML Attribute Values",Button::GetSerializableName() + "Properties",true);
293  }
294  }
295 
297  {
298  this->Widget::ProtoDeSerializeProperties(SelfRoot);
299 
300  XML::Attribute CurrAttrib;
301  XML::Node PropertiesNode = SelfRoot.GetChild( Button::GetSerializableName() + "Properties" );
302 
303  if( !PropertiesNode.Empty() ) {
304  if(PropertiesNode.GetAttribute("Version").AsInt() == 1) {
305  CurrAttrib = PropertiesNode.GetAttribute("LockoutTime");
306  if( !CurrAttrib.Empty() )
307  this->SetLockoutTime( CurrAttrib.AsUint() );
308 
309  XML::Node CodesNode = PropertiesNode.GetChild( "ActivationCodes" );
310  if( !CodesNode.Empty() ) {
311  for( XML::NodeIterator CodeNodeIt = CodesNode.begin() ; CodeNodeIt != CodesNode.end() ; ++CodeNodeIt )
312  {
313  Input::MetaCode ActivationCode;
314  ActivationCode.ProtoDeSerialize( (*CodeNodeIt) );
315  this->BindActivationKeyOrButton(ActivationCode);
316  }
317  }
318  }else{
319  MEZZ_EXCEPTION(ExceptionBase::INVALID_VERSION_EXCEPTION,"Incompatible XML Version for " + (Button::GetSerializableName() + "Properties") + ": Not Version 1.");
320  }
321  }else{
322  MEZZ_EXCEPTION(ExceptionBase::II_IDENTITY_NOT_FOUND_EXCEPTION,Button::GetSerializableName() + "Properties" + " was not found in the provided XML node, which was expected.");
323  }
324  }
325 
327  {
328  return Button::TypeName;
329  }
330 
331  ///////////////////////////////////////////////////////////////////////////////
332  // Internal Event Methods
333 
335  {
337 
338  if( this->MouseActivated && this->Activation == AS_Activation_Standby ) {
339  this->Activate();
340  }
341  }
342 
344  {
346 
347  if( this->MouseActivated && this->Activation == AS_Activated ) {
348  this->Standby();
349  }
350  }
351 
353  {
354  EventArgumentsPtr Args( new WidgetEventArguments(Button::EventActivated,this->Name) );
355  this->FireEvent(Args);
356  }
357 
359  {
360  EventArgumentsPtr Args( new WidgetEventArguments(Button::EventStandby,this->Name) );
361  this->FireEvent(Args);
362  }
363 
365  {
366  EventArgumentsPtr Args( new WidgetEventArguments(Button::EventDeactivated,this->Name) );
367  this->FireEvent(Args);
368  }
369 
370  ///////////////////////////////////////////////////////////////////////////////
371  // ButtonFactory Methods
372 
374  { return Button::TypeName; }
375 
376  Button* ButtonFactory::CreateButton(const String& RendName, Screen* Parent)
377  { return new Button(RendName,Parent); }
378 
379  Button* ButtonFactory::CreateButton(const String& RendName, const UnifiedRect& RendRect, Screen* Parent)
380  { return new Button(RendName,RendRect,Parent); }
381 
383  { return new Button(XMLNode,Parent); }
384 
386  { return new Button(Parent); }
387 
388  Widget* ButtonFactory::CreateWidget(const String& RendName, const NameValuePairMap& Params, Screen* Parent)
389  { return this->CreateButton(RendName,Parent); }
390 
391  Widget* ButtonFactory::CreateWidget(const String& RendName, const UnifiedRect& RendRect, const NameValuePairMap& Params, Screen* Parent)
392  { return this->CreateButton(RendName,RendRect,Parent); }
393 
395  { return this->CreateButton(XMLNode,Parent); }
396 
398  { delete static_cast<Button*>( ToBeDestroyed ); }
399  }//UI
400 }//Mezzanine
401 
402 #endif
std::set< Input::MetaCodeKey > ActivationCodeContainer
Basic container type for Activation Code storage by this class.
Definition: button.h:70
InputCode
The InputCode enum defines all the posible types of inputs.
virtual void UnbindAllActivationKeysAndButtons()
Clears all keyboard and mouse input codes from the list of activators.
Definition: button.cpp:253
Attribute AppendAttribute(const Char8 *Name)
Creates an Attribute and puts it at the end of this Nodes attributes.
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: button.cpp:296
A light-weight handle for manipulating attributes in DOM tree.
Definition: attribute.h:74
virtual void _OnDeactivate()
Self logic to be executed when this button is deactivated.
Definition: button.cpp:364
bool Boole
Generally acts a single bit, true or false.
Definition: datatypes.h:173
static const String EventActivated
Event name for when this activatable widget is activated.
Definition: button.h:93
static const String EventDeactivated
Event name for when this activatable widget is deactivated.
Definition: button.h:97
const InputContainer & GetAutoRegisteredCodes() const
Gets the list of codes that will be auto-registered with each UI button.
Definition: uimanager.cpp:468
void ProtoDeSerialize(const XML::Node &OneNode)
Take the data stored in an XML and overwrite this instance of this object with it.
Definition: metacode.cpp:431
virtual void UnbindAllControllerActivationButtons()
Clears all controller input codes from the set of activation codes.
Definition: button.cpp:241
Whole LockoutTime
The amount of time to lock the activation of a button after it has already been activated.
Definition: button.h:110
Boole ButtonAutoRegisterEnabled() const
Gets whether or not the ButtonAutoRegister feature is enabled.
Definition: uimanager.cpp:441
Boole IsStopped()
Gets whether or not this Timer is currently running.
Definition: timer.cpp:139
static String GetSerializableName()
Get the name of the the XML tag the Renderable class will leave behind as its instances are serialize...
Definition: button.cpp:326
virtual void _OnStandby()
Self logic to be executed when this button is put into standby.
Definition: button.cpp:358
Thrown when the requested identity could not be found.
Definition: exception.h:94
virtual void UnbindActivationKeyOrButton(const Input::MetaCode &Code)
Removes a previously registered activation code.
Definition: button.cpp:212
#define MEZZ_EXCEPTION(num, desc)
An easy way to throw exceptions with rich information.
Definition: exception.h:3048
A simple reference counting pointer.
Definition: countedptr.h:70
A key class for MetaCodes to be used in associative containers.
Definition: metacodekey.h:56
virtual void ProtoSerializeProperties(XML::Node &SelfRoot) const
Convert the properties of this class to an XML::Node ready for serialization.
Definition: widget.cpp:278
Thrown when a version is accessed/parsed/required and it cannot work correctly or is missing...
Definition: exception.h:112
virtual String GetWidgetTypeName() const
Gets the name of the Widget that is created by this factory.
Definition: button.cpp:373
Boole MouseActivated
Stores whether or not the current activation of this button was triggered by a mouse.
Definition: button.h:113
virtual Boole Standby()
Attempts to put this button into standby.
Definition: button.cpp:169
virtual Boole IsHovered() const
Gets the result of the last mouse hover check.
Definition: widget.cpp:159
virtual UIManager * GetManager() const
Gets the UIManager this screen belongs to.
Definition: screen.cpp:401
virtual Boole HandleInputImpl(const Input::MetaCode &Code)
Consumes input for this widget's use.
Definition: button.cpp:91
std::vector< Input::MetaCode > InputContainer
Basic container type for Input::MetaCode storage by this class.
Definition: uimanager.h:134
bool Empty() const
Is this storing anything at all?
virtual Boole Activate()
Attempts to activate this button.
Definition: button.cpp:143
virtual void BindActivationKeyOrButton(const Input::MetaCode &Code)
Registers a keyboard key or mouse button that can activate this button.
Definition: button.cpp:203
Timer LockoutTimer
The timer that will be used when a button is locked from activating a second time within a certain pe...
Definition: button.h:107
Int32 GetMetaValue() const
This Returns the MetaValue.
Definition: metacode.cpp:250
virtual const String & GetTypeName() const
Gets the type of widget this is.
Definition: button.cpp:197
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
This button has been activated via an input device.
Definition: button.h:86
Child node iterator (a bidirectional iterator over a collection of Node)
Definition: nodeiterator.h:77
ActivationState Activation
Stores the current state of this button's activation. See Button::ActivationState enum for more detai...
Definition: button.h:104
A light-weight handle for manipulating nodes in DOM tree.
Definition: node.h:89
iterator begin() const
Get a Child node iterator that references the first child Node.
unsigned int AsUint(unsigned int def=0) const
Attempts to convert the value of the attribute to an unsigned int and returns the results...
int AsInt(int def=0) const
Attempts to convert the value of the attribute to an int and returns the results. ...
uint32_t UInt32
An 32-bit unsigned integer.
Definition: datatypes.h:126
static const String EventStandby
Event name for when this activatable widget is put into standby.
Definition: button.h:95
iterator end() const
Get a Child node iterator that references one past the last child Node.
ActivationCodeContainer ActivationCodes
A container of codes that stores the inputs that will trigger this button to be activated.
Definition: button.h:101
bool Empty() const
Is this storing anything at all?
This is the base class for all widgets.
Definition: widget.h:126
static const String TypeName
String containing the type name for this class: "Button".
Definition: button.h:91
const ActivationCodeContainer & GetActivationCodes() const
Gets a set with all the activation codes used to activate this button.
Definition: button.cpp:261
void Start()
Activates the Timer.
Definition: timer.cpp:113
virtual ~Button()
Standard destructor.
Definition: button.cpp:88
virtual Widget * CreateWidget(Screen *Parent)
Creates a Widget of the type represented by this factory.
Definition: button.cpp:385
virtual void _OnActivate()
Self logic to be executed when this button is activated.
Definition: button.cpp:352
Event * AddEvent(const String &EventName)
Creates a new event this Publisher can fire.
virtual void ConstructButton()
Contains all the common necessary startup initializations for this class.
Definition: button.cpp:120
void SetCountMode(const Mezzanine::CountMode Mode)
Sets the mode the timer should use to increment time.
Definition: timer.cpp:101
const Timer & GetLockoutTimer() const
Gets this activatables lockout timer.
Definition: button.cpp:185
This button was activated, but an event occured that made it suspend it's activation.
Definition: button.h:87
Button(Screen *Parent)
Blank constructor.
Definition: button.cpp:60
String Name
The unique name of this Renderable.
Definition: renderable.h:81
void FireEvent(EventArgumentsPtr Args)
Fires an event.
virtual Button * CreateButton(const String &RendName, Screen *Parent)
Creates a new Button.
Definition: button.cpp:376
void Reset(const Whole StartTime=0)
Sets the current time to an initial value and stops the Timer if it is running.
Definition: timer.cpp:127
Input::InputCode GetCode() const
This Returns the Inputcode.
Definition: metacode.cpp:244
Boole IsActivated() const
Gets whether or not this button is currently activated.
Definition: button.cpp:188
virtual void _OnMouseEnter()
Self logic to be executed when the mouse cursor enters the bounds of this widget. ...
Definition: widget.cpp:441
Thrown when parameters are checked at runtime and found invalid.
Definition: exception.h:108
This Determines the kind of user input.
Definition: metacode.h:93
The timer counts down, meaning the Timer current time is showing remaining time.
Definition: timer.h:61
virtual void UnbindAllMouseActivationButtons()
Clears all mouse input codes from the set of activation codes.
Definition: button.cpp:229
This class is responsible for any and all user interactions with the User interface/HUD.
Definition: uimanager.h:114
A basic timer class to assist in timed operations.
Definition: timer.h:67
The bulk of the engine components go in this namspace.
Definition: actor.cpp:56
virtual void _OnMouseExit()
Self logic to be executed when the mouse cursor leaves the bounds of thiw widget. ...
Definition: button.cpp:343
unsigned long Whole
Whole is an unsigned integer, it will be at least 32bits in size.
Definition: datatypes.h:151
ActivationCodeContainer::iterator ActivationCodeIterator
Iterator type for Activation Codes stored by this class.
Definition: button.h:72
Boole IsDeviceButton() const
Does this MetaCode Represent a state of any button on an input device.
Definition: metacode.cpp:331
virtual void _OnMouseEnter()
Self logic to be executed when the mouse cursor enters the bounds of this widget. ...
Definition: button.cpp:334
This class is a helper class, specifically for use as a button.
Definition: button.h:66
virtual void ProtoDeSerialize(const XML::Node &SelfRoot)
Take the data stored in an XML Node and overwrite this object with it.
virtual void DestroyWidget(Widget *ToBeDestroyed)
Destroys a Widget created by this factory.
Definition: button.cpp:397
virtual Boole VertifyActivationCode(const Input::InputCode Code)
Verifies the provided to code is valid for this button.
Definition: button.cpp:136
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: widget.cpp:337
void SetLockoutTime(const UInt32 &Milliseconds)
Sets a timer preventing multiple activations for a period of time.
Definition: button.cpp:182
void SerializeError(const String &FailedTo, const String &ClassName, Boole SOrD)
Simply does some string concatenation, then throws an Exception.
virtual void _OnMouseExit()
Self logic to be executed when the mouse cursor leaves the bounds of thiw widget. ...
Definition: widget.cpp:452
Node AppendChild(NodeType Type=NodeElement)
Creates a Node and makes it a child of this one.
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
Boole IsOnStandby() const
Gets whether or not this button is currently on standby.
Definition: button.cpp:191
std::string String
A datatype used to a series of characters.
Definition: datatypes.h:159
virtual void UnbindAllKeyboardActivationKeys()
Clears all keyboard input codes from the set of activation codes.
Definition: button.cpp:217
The normal default state.
Definition: button.h:85
Attribute GetAttribute(const Char8 *Name) const
Attempt to get an Attribute on this Node with a given name.
Boole IsMouseButton() const
Does this MetaCode Represent a state of a Mouse button.
Definition: metacode.cpp:325
virtual Boole Deactivate()
Attempts to deactivate this button.
Definition: button.cpp:155
Boole IsDeactivated() const
Gets whether or not this button is currently deactivated.
Definition: button.cpp:194
Node GetChild(const Char8 *Name) const
Attempt to get a child Node with a given name.
Screen * ParentScreen
A pointer to the Screen that created this Renderable.
Definition: renderable.h:72
virtual void ProtoSerializeProperties(XML::Node &SelfRoot) const
Convert the properties of this class to an XML::Node ready for serialization.
Definition: button.cpp:269
This is the base class for widget specific event arguments.
Definition: widget.h:60