MezzanineEngine 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
widget.cpp
1 // © Copyright 2010 - 2014 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 _uiwidget_cpp
41 #define _uiwidget_cpp
42 
43 #include "UI/widget.h"
44 #include "UI/button.h"
45 #include "UI/screen.h"
46 
47 #include "UI/uimanager.h"
48 #include "entresol.h"
49 #include "Input/inputmanager.h"
50 #include "Input/mouse.h"
51 
52 namespace Mezzanine
53 {
54  namespace UI
55  {
56  const String Widget::TypeName = "GenericWidget";
57  const String Widget::EventMouseEnter = "MouseEnter";
58  const String Widget::EventMouseExit = "MouseExit";
59  const String Widget::EventMouseDragStart = "MouseDragStart";
60  const String Widget::EventMouseDragging = "MouseDragging";
61  const String Widget::EventMouseDragEnd = "MouseDragEnd";
62  const String Widget::EventFocusGained = "FocusGained";
63  const String Widget::EventFocusLost = "FocusLost";
64  const String Widget::EventFocusLocked = "FocusLocked";
65  const String Widget::EventFocusUnlocked = "FocusUnlocked";
66  const String Widget::EventVisibilityShown = "VisibilityShown";
67  const String Widget::EventVisibilityHidden = "VisibilityHidden";
68 
70  QuadRenderable(Parent),
71  HoveredSubWidget(NULL),
72  State(WS_Untouched)
73  { /* Do nothing to leave it blank */ }
74 
75  Widget::Widget(const String& RendName, Screen* Parent) :
76  QuadRenderable(RendName,Parent),
77  HoveredSubWidget(NULL),
78  State(WS_Untouched)
79  { this->ConstructWidget(); }
80 
81  Widget::Widget(const String& RendName, const UnifiedRect& RendRect, Screen* Parent) :
82  QuadRenderable(RendName,RendRect,Parent),
83  HoveredSubWidget(NULL),
84  State(WS_Untouched)
85  { this->ConstructWidget(); }
86 
87  Widget::Widget(const XML::Node& XMLNode, Screen* Parent) :
88  QuadRenderable(Parent),
89  HoveredSubWidget(NULL),
90  State(WS_Untouched)
91  { this->ProtoDeSerialize(XMLNode); }
92 
94  { }
95 
96  void Widget::ProtoSerializeImpl(XML::Node& SelfRoot) const
97  {
98  this->QuadRenderable::ProtoSerializeImpl(SelfRoot);
99  this->ProtoSerializeStateGroupBindings(SelfRoot);
100  this->ProtoSerializeEvents(SelfRoot);
101  /// @todo Seriailze subscribed events? Scripts at least.
102  }
103 
105  {
106  this->QuadRenderable::ProtoDeSerializeImpl(SelfRoot);
107  this->ProtoDeSerializeStateGroupBindings(SelfRoot);
108  this->ProtoDeSerializeEvents(SelfRoot);
109  }
110 
112  {
113  return false;
114  }
115 
117  {
118  // Create our events.
130 
131  // Create our render groups and bind them
132  RenderLayerGroup* NormalGroup = this->CreateRenderLayerGroup("Normal");
133  RenderLayerGroup* HoveredGroup = this->CreateRenderLayerGroup("Hovered");
134 
135  this->StateGroupBindings[ WS_Untouched ] = NormalGroup;
136  this->StateGroupBindings[ WS_Hovered ] = HoveredGroup;
137  this->StateGroupBindings[ WS_Focused ] = NormalGroup;
138  this->StateGroupBindings[ WS_Dragged ] = NormalGroup;
139  this->StateGroupBindings[ WS_Hovered | WS_Focused ] = HoveredGroup;
140  this->StateGroupBindings[ WS_Hovered | WS_Dragged ] = HoveredGroup;
141  this->StateGroupBindings[ WS_Focused | WS_Dragged ] = NormalGroup;
142  this->StateGroupBindings[ WS_Hovered | WS_Focused | WS_Dragged ] = HoveredGroup;
143  }
144 
145  ///////////////////////////////////////////////////////////////////////////////
146  // Utility Methods
147 
149  { return Renderable::RT_Widget; }
150 
152  { return Widget::TypeName; }
153 
154  Boolean Widget::IsHovered() const
155  { return (this->State & WS_Hovered); }
156 
157  Boolean Widget::HasFocus() const
158  { return (this->State & WS_Focused); }
159 
160  Boolean Widget::IsBeingDragged() const
161  { return (this->State & WS_Dragged); }
162 
163  ///////////////////////////////////////////////////////////////////////////////
164  // State-LayerGroup Binding Methods
165 
166  void Widget::BindGroupToState(const UInt32 BindState, RenderLayerGroup* ToBind)
167  {
168  this->StateGroupBindings[BindState] = ToBind;
169  }
170 
172  {
173  ConstStateLayerGroupIterator It = this->StateGroupBindings.find(BindState);
174  if( It != this->StateGroupBindings.end() ) return (*It).second;
175  else return NULL;
176  }
177 
178  bool Widget::SetGroupFromState(const UInt32 BindState)
179  {
180  StateLayerGroupIterator It = this->StateGroupBindings.find(BindState);
181  if( It != this->StateGroupBindings.end() )
182  {
183  this->SetActiveGroup( (*It).second );
184  return true;
185  }
186  else return false;
187  }
188 
189  ///////////////////////////////////////////////////////////////////////////////
190  // Fetch Methods
191 
193  {
194  return this->HoveredSubWidget;
195  }
196 
198  {
200  else return this;
201  }
202 
203  ///////////////////////////////////////////////////////////////////////////////
204  // Visibility and Priority Methods
205 
206  void Widget::SetVisible(Boolean CanSee)
207  {
208  if( this->Visible == CanSee )
209  return;
210  Visible = CanSee;
211  if(CanSee) this->_OnVisibilityShown();
212  else this->_OnVisibilityHidden();
213  for( ChildIterator It = this->ChildWidgets.begin() ; It != this->ChildWidgets.end() ; ++It )
214  {
215  (*It)->SetVisible(CanSee);
216  }
217  }
218 
219  Boolean Widget::GetVisible() const
220  {
221  return this->Visible;
222  }
223 
224  Boolean Widget::IsVisible() const
225  {
226  if( this->ParentQuad ) {
227  return this->Visible && this->ParentQuad->IsVisible();
228  }else{
229  return this->Visible;
230  }
231  }
232 
234  {
235  if( this->Visible == true )
236  return;
237  this->Visible = true;
238  this->_OnVisibilityShown();
239  for( ChildIterator It = this->ChildWidgets.begin() ; It != this->ChildWidgets.end() ; ++It )
240  {
241  (*It)->Show();
242  }
243  }
244 
246  {
247  if( this->Visible == false )
248  return;
249  this->Visible = false;
250  this->_OnVisibilityHidden();
251  for( ChildIterator It = this->ChildWidgets.begin() ; It != this->ChildWidgets.end() ; ++It )
252  {
253  (*It)->Hide();
254  }
255  }
256 
257  ///////////////////////////////////////////////////////////////////////////////
258  // Serialization
259 
261  {
263  XML::Node PropertiesNode = SelfRoot.AppendChild( Widget::GetSerializableName() + "Properties" );
264 
265  if( PropertiesNode.AppendAttribute("Version").SetValue("1") &&
266  PropertiesNode.AppendAttribute("State").SetValue( this->State ) )
267  {
268  return;
269  }else{
270  SerializeError("Create XML Attribute Values",Widget::GetSerializableName() + "Properties",true);
271  }
272  }
273 
275  {
276  XML::Node BindingsNode = SelfRoot.AppendChild( "StateGroupBindings" );
277 
278  if( BindingsNode.AppendAttribute("Version").SetValue("1") ) {
279  for( ConstStateLayerGroupIterator BindingIt = this->StateGroupBindings.begin() ; BindingIt != this->StateGroupBindings.end() ; ++BindingIt )
280  {
281  XML::Node BindingNode = BindingsNode.AppendChild( "StateGroupBinding" );
282 
283  if( BindingNode.AppendAttribute("Version").SetValue("1") &&
284  BindingNode.AppendAttribute("StateID").SetValue( (*BindingIt).first ) &&
285  BindingNode.AppendAttribute("LayerGroupName").SetValue( (*BindingIt).second->GetName() ) )
286  {
287  continue;
288  }else{
289  SerializeError("Create XML Version Attribute","StateGroupBinding",true);
290  }
291  }
292  }else{
293  SerializeError("Create XML Version Attribute","StateGroupBindings",true);
294  }
295  }
296 
298  {
299  XML::Node EventsNode = SelfRoot.AppendChild( "Events" );
300 
301  if( EventsNode.AppendAttribute("Version").SetValue("1") ) {
302  for( ConstEventIterator EvIt = this->Events.begin() ; EvIt != this->Events.end() ; ++EvIt )
303  {
304  XML::Node BindingNode = EventsNode.AppendChild( "Event" );
305 
306  if( BindingNode.AppendAttribute("Version").SetValue("1") &&
307  BindingNode.AppendAttribute("Name").SetValue( (*EvIt).first ) )
308  {
309  continue;
310  }else{
311  SerializeError("Create XML Version Attribute","Event",true);
312  }
313  }
314  }else{
315  SerializeError("Create XML Version Attribute","Events",true);
316  }
317  }
318 
320  {
322 
323  XML::Attribute CurrAttrib;
324  XML::Node PropertiesNode = SelfRoot.GetChild( Widget::GetSerializableName() + "Properties" );
325 
326  if( !PropertiesNode.Empty() ) {
327  if(PropertiesNode.GetAttribute("Version").AsInt() == 1) {
328  CurrAttrib = PropertiesNode.GetAttribute("State");
329  if( !CurrAttrib.Empty() )
330  this->State = CurrAttrib.AsUint();
331  }else{
332  MEZZ_EXCEPTION(Exception::INVALID_VERSION_EXCEPTION,"Incompatible XML Version for " + (Widget::GetSerializableName() + "Properties") + ": Not Version 1.");
333  }
334  }else{
335  MEZZ_EXCEPTION(Exception::II_IDENTITY_NOT_FOUND_EXCEPTION,Widget::GetSerializableName() + "Properties" + " was not found in the provided XML node, which was expected.");
336  }
337  }
338 
340  {
341  this->StateGroupBindings.clear();
342 
343  XML::Attribute CurrAttrib;
344  XML::Node BindingsNode = SelfRoot.GetChild( "StateGroupBindings" );
345 
346  if( !BindingsNode.Empty() ) {
347  if( BindingsNode.GetAttribute("Version").AsInt() == 1 ) {
348  for( XML::NodeIterator BindingNodeIt = BindingsNode.begin() ; BindingNodeIt != BindingsNode.end() ; ++BindingNodeIt )
349  {
350  if( (*BindingNodeIt).GetAttribute("Version").AsInt() == 1 ) {
351  UInt32 StateID = 0;
352  String LayerGroupName;
353 
354  CurrAttrib = (*BindingNodeIt).GetAttribute("StateID");
355  if( !CurrAttrib.Empty() )
356  StateID = CurrAttrib.AsUint();
357 
358  CurrAttrib = (*BindingNodeIt).GetAttribute("LayerGroupName");
359  if( !CurrAttrib.Empty() )
360  LayerGroupName = CurrAttrib.AsString();
361 
362  if( !LayerGroupName.empty() ) { //Don't check the StateID because 0 is valid >.>
363  RenderLayerGroup* NamedGroup = this->GetRenderLayerGroup(LayerGroupName);
364  if( NamedGroup != NULL ) {
365  this->StateGroupBindings.insert( std::pair<UInt32,RenderLayerGroup*>(StateID,NamedGroup) );
366  }else{
367  StringStream ExceptionStream;
368  ExceptionStream << "Named RenderLayerGroup \"" << LayerGroupName << "\" not found when deserializing Widget named \"" << this->GetName() << "\".";
369  MEZZ_EXCEPTION(Exception::PARAMETERS_EXCEPTION,ExceptionStream.str());
370  }
371  }
372  }else{
373  MEZZ_EXCEPTION(Exception::INVALID_VERSION_EXCEPTION,"Incompatible XML Version for " + String("StateGroupBindings") + ": Not Version 1.");
374  }
375  }
376  }else{
377  MEZZ_EXCEPTION(Exception::INVALID_VERSION_EXCEPTION,"Incompatible XML Version for " + String("StateGroupBindings") + ": Not Version 1.");
378  }
379  }
380  }
381 
383  {
384  this->RemoveAllEvents();
385 
386  XML::Attribute CurrAttrib;
387  XML::Node EventsNode = SelfRoot.GetChild( "Events" );
388 
389  if( !EventsNode.Empty() ) {
390  if( EventsNode.GetAttribute("Version").AsInt() == 1 ) {
391  for( XML::NodeIterator EvNodeIt = EventsNode.begin() ; EvNodeIt != EventsNode.end() ; ++EvNodeIt )
392  {
393  if( (*EvNodeIt).GetAttribute("Version").AsInt() == 1 ) {
394  String EvName;
395 
396  CurrAttrib = (*EvNodeIt).GetAttribute("Name");
397  if( !CurrAttrib.Empty() )
398  EvName = CurrAttrib.AsString();
399 
400  if( !EvName.empty() ) {
401  this->AddEvent(EvName);
402  }
403  }else{
404  MEZZ_EXCEPTION(Exception::INVALID_VERSION_EXCEPTION,"Incompatible XML Version for " + String("Events") + ": Not Version 1.");
405  }
406  }
407  }else{
408  MEZZ_EXCEPTION(Exception::INVALID_VERSION_EXCEPTION,"Incompatible XML Version for " + String("Events") + ": Not Version 1.");
409  }
410  }
411  }
412 
414  {
415  return this->GetTypeName();
416  }
417 
419  {
420  return Widget::TypeName;
421  }
422 
423  ///////////////////////////////////////////////////////////////////////////////
424  // Internal Event Methods
425 
427  {
428  this->State |= WS_Hovered;
429  this->SetGroupFromState(this->State);
430 
432  this->FireEvent(Args);
433  }
434 
436  {
437  if( this->State & WS_Hovered )
438  {
439  this->State &= ~WS_Hovered;
440  this->SetGroupFromState(this->State);
441  }
442 
444  this->FireEvent(Args);
445  }
446 
448  {
449  this->State |= WS_Dragged;
450  this->SetGroupFromState(this->State);
451 
453  this->FireEvent(Args);
454  }
455 
457  {
459  this->FireEvent(Args);
460  }
461 
463  {
464  if( this->State & WS_Dragged )
465  {
466  this->State &= ~WS_Dragged;
467  this->SetGroupFromState(this->State);
468  }
469 
471  this->FireEvent(Args);
472  }
473 
475  {
476  this->State |= WS_Focused;
477  this->SetGroupFromState(this->State);
478 
480  this->FireEvent(Args);
481  }
482 
484  {
485  if( this->State & WS_Focused )
486  {
487  this->State &= ~WS_Focused;
488  this->SetGroupFromState(this->State);
489  }
490 
492  this->FireEvent(Args);
493  }
494 
496  {
498  this->FireEvent(Args);
499  }
500 
502  {
504  this->FireEvent(Args);
505  }
506 
508  {
510  this->FireEvent(Args);
511  }
512 
514  {
516  this->FireEvent(Args);
517  }
518 
519  ///////////////////////////////////////////////////////////////////////////////
520  // Internal Methods
521 
523  {
524  if( this->HandleInputImpl(Code) ) {
525  return true;
526  }else{
527  if( this->ParentQuad && Renderable::RT_Widget == this->ParentQuad->GetRenderableType() )
528  return static_cast<Widget*>(this->ParentQuad)->_HandleInput(Code);
529  else return false;
530  }
531  }
532 
534  {
535  // Default to doing nothing, must be overridden to add logic if a widget needs it
536  }
537 
538  ///////////////////////////////////////////////////////////////////////////////
539  // ButtonFactory Methods
540 
542  { return Widget::TypeName; }
543 
545  { return new Widget(RendName,Parent); }
546 
547  Widget* GenericWidgetFactory::CreateWidget(const String& RendName, const UnifiedRect& RendRect, Screen* Parent)
548  { return new Widget(RendName,RendRect,Parent); }
549 
551  { return new Widget(Parent); }
552 
553  Widget* GenericWidgetFactory::CreateWidget(const String& RendName, const NameValuePairMap& Params, Screen* Parent)
554  { return new Widget(RendName,Parent); }
555 
556  Widget* GenericWidgetFactory::CreateWidget(const String& RendName, const UnifiedRect& RendRect, const NameValuePairMap& Params, Screen* Parent)
557  { return new Widget(RendName,RendRect,Parent); }
558 
560  { return new Widget(XMLNode,Parent); }
561 
563  { delete ToBeDestroyed; }
564  }//UI
565 }//Mezzanine
566 
567 #endif