1//************************************ bs::framework - Copyright 2018 Marko Pintera **************************************//
2//*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********//
3#include "GUI/BsGUIToggle.h"
4#include "GUI/BsGUIDimensions.h"
5#include "GUI/BsGUIMouseEvent.h"
6#include "GUI/BsGUIToggleGroup.h"
7#include "BsGUICommandEvent.h"
8
9namespace bs
10{
11 const String& GUIToggle::getGUITypeName()
12 {
13 static String name = "Toggle";
14 return name;
15 }
16
17 GUIToggle::GUIToggle(const String& styleName, const GUIContent& content, SPtr<GUIToggleGroup> toggleGroup, const GUIDimensions& dimensions)
18 :GUIButtonBase(styleName, content, dimensions), mToggleGroup(nullptr), mIsToggled(false)
19 {
20 if(toggleGroup != nullptr)
21 toggleGroup->_add(this);
22 }
23
24 GUIToggle::~GUIToggle()
25 {
26 if(mToggleGroup != nullptr)
27 {
28 mToggleGroup->_remove(this);
29 }
30 }
31
32 GUIToggle* GUIToggle::create(const HString& text, const String& styleName)
33 {
34 return create(GUIContent(text), styleName);
35 }
36
37 GUIToggle* GUIToggle::create(const HString& text, const GUIOptions& options, const String& styleName)
38 {
39 return create(GUIContent(text), options, styleName);
40 }
41
42 GUIToggle* GUIToggle::create(const HString& text, SPtr<GUIToggleGroup> toggleGroup, const String& styleName)
43 {
44 return create(GUIContent(text), toggleGroup, styleName);
45 }
46
47 GUIToggle* GUIToggle::create(const HString& text, SPtr<GUIToggleGroup> toggleGroup,
48 const GUIOptions& options, const String& styleName)
49 {
50 return create(GUIContent(text), toggleGroup, options, styleName);
51 }
52
53 GUIToggle* GUIToggle::create(const GUIContent& content, const String& styleName)
54 {
55 return new (bs_alloc<GUIToggle>()) GUIToggle(getStyleName<GUIToggle>(styleName), content, nullptr, GUIDimensions::create());
56 }
57
58 GUIToggle* GUIToggle::create(const GUIContent& content, const GUIOptions& options, const String& styleName)
59 {
60 return new (bs_alloc<GUIToggle>()) GUIToggle(getStyleName<GUIToggle>(styleName), content, nullptr, GUIDimensions::create(options));
61 }
62
63 GUIToggle* GUIToggle::create(const GUIContent& content, SPtr<GUIToggleGroup> toggleGroup, const String& styleName)
64 {
65 return new (bs_alloc<GUIToggle>()) GUIToggle(getStyleName<GUIToggle>(styleName), content, toggleGroup, GUIDimensions::create());
66 }
67
68 GUIToggle* GUIToggle::create(const GUIContent& content, SPtr<GUIToggleGroup> toggleGroup,
69 const GUIOptions& options, const String& styleName)
70 {
71 return new (bs_alloc<GUIToggle>()) GUIToggle(getStyleName<GUIToggle>(styleName), content, toggleGroup, GUIDimensions::create(options));
72 }
73
74 SPtr<GUIToggleGroup> GUIToggle::createToggleGroup(bool allowAllOff)
75 {
76 SPtr<GUIToggleGroup> toggleGroup = bs_shared_ptr<GUIToggleGroup>(new (bs_alloc<GUIToggleGroup>()) GUIToggleGroup(allowAllOff));
77 toggleGroup->initialize(toggleGroup);
78
79 return toggleGroup;
80 }
81
82 void GUIToggle::_setToggleGroup(SPtr<GUIToggleGroup> toggleGroup)
83 {
84 mToggleGroup = toggleGroup;
85
86 bool isToggled = false;
87 if(mToggleGroup != nullptr) // If in group ensure at least one element is toggled on
88 {
89 for(auto& toggleElem : mToggleGroup->mButtons)
90 {
91 if(isToggled)
92 {
93 if(toggleElem->mIsToggled)
94 toggleElem->toggleOff();
95 }
96 else
97 {
98 if(toggleElem->mIsToggled)
99 isToggled = true;
100 }
101
102 }
103
104 if(!isToggled && !toggleGroup->mAllowAllOff)
105 toggleOn();
106 }
107 }
108
109 void GUIToggle::_toggleOn(bool triggerEvent)
110 {
111 if(mIsToggled)
112 return;
113
114 mIsToggled = true;
115
116 if(triggerEvent)
117 {
118 if (!onToggled.empty())
119 onToggled(mIsToggled);
120 }
121
122 if(mToggleGroup != nullptr)
123 {
124 for(auto& toggleElem : mToggleGroup->mButtons)
125 {
126 if(toggleElem != this)
127 toggleElem->_toggleOff(triggerEvent);
128 }
129 }
130
131 _setOn(true);
132 }
133
134 void GUIToggle::_toggleOff(bool triggerEvent)
135 {
136 if(!mIsToggled)
137 return;
138
139 bool canBeToggledOff = false;
140 if(mToggleGroup != nullptr) // If in group ensure at least one element is toggled on
141 {
142 for(auto& toggleElem : mToggleGroup->mButtons)
143 {
144 if(toggleElem != this)
145 {
146 if(toggleElem->mIsToggled)
147 {
148 canBeToggledOff = true;
149 break;
150 }
151 }
152
153 }
154 }
155 else
156 canBeToggledOff = true;
157
158 if (canBeToggledOff || mToggleGroup->mAllowAllOff)
159 {
160 mIsToggled = false;
161
162 if(triggerEvent)
163 {
164 if (!onToggled.empty())
165 onToggled(mIsToggled);
166 }
167
168 _setOn(false);
169 }
170 }
171
172 bool GUIToggle::_mouseEvent(const GUIMouseEvent& ev)
173 {
174 bool processed = GUIButtonBase::_mouseEvent(ev);
175
176 if(ev.getType() == GUIMouseEventType::MouseUp)
177 {
178 if (!_isDisabled())
179 {
180 if (mIsToggled)
181 _toggleOff(true);
182 else
183 _toggleOn(true);
184 }
185
186 processed = true;
187 }
188
189 return processed;
190 }
191
192 bool GUIToggle::_commandEvent(const GUICommandEvent& ev)
193 {
194 const bool processed = GUIButtonBase::_commandEvent(ev);
195
196 if(ev.getType() == GUICommandEventType::Confirm)
197 {
198 if(!_isDisabled())
199 {
200 if(mIsToggled)
201 _toggleOff(true);
202 else
203 _toggleOn(true);
204 }
205
206 return true;
207 }
208
209 return processed;
210 }
211}
212