1 /*
2 * This file is part of the Colobot: Gold Edition source code
3 * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam
4 * http://epsitec.ch; http://colobot.info; http://github.com/colobot
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 * See the GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see http://gnu.org/licenses
18 */
19
20
21 #include "ui/controls/editvalue.h"
22
23 #include "common/event.h"
24 #include "common/make_unique.h"
25
26 #include "level/robotmain.h"
27
28 #include "ui/controls/button.h"
29 #include "ui/controls/edit.h"
30 #include "ui/controls/interface.h"
31
32 #include <cstdio>
33
34
35
36 namespace Ui
37 {
38 // Object's constructor.
39
CEditValue()40 CEditValue::CEditValue() : CControl ()
41 {
42 m_type = EVT_100; // %
43 m_stepValue = 0.1f; // 10%
44 m_minValue = 0.0f; // 0%
45 m_maxValue = 1.0f; // 100%
46
47 m_interface = CRobotMain::GetInstancePointer()->GetInterface();
48 }
49
50 // Object's destructor.
51
~CEditValue()52 CEditValue::~CEditValue()
53 {
54 }
55
56
57 // Creates a new button.
58
Create(Math::Point pos,Math::Point dim,int icon,EventType eventType)59 bool CEditValue::Create(Math::Point pos, Math::Point dim, int icon, EventType eventType)
60 {
61 if ( eventType == EVENT_NULL ) eventType = GetUniqueEventType();
62 CControl::Create(pos, dim, icon, eventType);
63
64 GlintDelete();
65
66 m_edit = MakeUnique<Ui::CEdit>();
67 m_edit->Create(pos, dim, 0, EVENT_NULL);
68 m_edit->SetMaxChar(4);
69
70 m_buttonUp = MakeUnique<Ui::CButton>();
71 m_buttonUp->Create(pos, dim, 49, EVENT_NULL); // ^
72 m_buttonUp->SetRepeat(true);
73
74 m_buttonDown = MakeUnique<Ui::CButton>();
75 m_buttonDown->Create(pos, dim, 50, EVENT_NULL); // v
76 m_buttonDown->SetRepeat(true);
77
78 MoveAdjust();
79 return true;
80 }
81
82
SetPos(Math::Point pos)83 void CEditValue::SetPos(Math::Point pos)
84 {
85 CControl::SetPos(pos);
86 MoveAdjust();
87 }
88
SetDim(Math::Point dim)89 void CEditValue::SetDim(Math::Point dim)
90 {
91 CControl::SetDim(dim);
92 MoveAdjust();
93 }
94
MoveAdjust()95 void CEditValue::MoveAdjust()
96 {
97 Math::Point pos, dim;
98
99 if (m_edit != nullptr)
100 {
101 pos.x = m_pos.x;
102 pos.y = m_pos.y;
103 dim.x = m_dim.x-m_dim.y*0.6f;
104 dim.y = m_dim.y;
105 m_edit->SetPos(pos);
106 m_edit->SetDim(dim);
107 }
108
109 if (m_buttonUp != nullptr)
110 {
111 pos.x = m_pos.x+m_dim.x-m_dim.y*0.6f;
112 pos.y = m_pos.y+m_dim.y*0.5f;
113 dim.x = m_dim.y*0.6f;
114 dim.y = m_dim.y*0.5f;
115 m_buttonUp->SetPos(pos);
116 m_buttonUp->SetDim(dim);
117 }
118
119 if (m_buttonDown != nullptr)
120 {
121 pos.x = m_pos.x+m_dim.x-m_dim.y*0.6f;
122 pos.y = m_pos.y;
123 dim.x = m_dim.y*0.6f;
124 dim.y = m_dim.y*0.5f;
125 m_buttonDown->SetPos(pos);
126 m_buttonDown->SetDim(dim);
127 }
128 }
129
130
131 // Management of an event.
132
EventProcess(const Event & event)133 bool CEditValue::EventProcess(const Event &event)
134 {
135 CControl::EventProcess(event);
136
137 if ( (m_state & STATE_VISIBLE) == 0 ) return true;
138 if ( (m_state & STATE_ENABLE) == 0 ) return true;
139 if ( m_state & STATE_DEAD ) return true;
140
141 if (m_edit != nullptr)
142 {
143 if ( m_edit->GetFocus() &&
144 event.type == EVENT_KEY_DOWN &&
145 event.GetData<KeyEventData>()->key == KEY(RETURN) )
146 {
147 float value = GetValue();
148 if ( value > m_maxValue ) value = m_maxValue;
149 if ( value < m_minValue ) value = m_minValue;
150 SetValue(value, true);
151 HiliteValue(event);
152 }
153 if ( !m_edit->EventProcess(event) ) return false;
154
155 if ( event.type == m_edit->GetEventType() )
156 {
157 m_event->AddEvent(Event(m_eventType));
158 }
159 }
160
161 if (m_buttonUp != nullptr)
162 {
163 if ( event.type == m_buttonUp->GetEventType() )
164 {
165 float value = GetValue()+m_stepValue;
166 if ( value > m_maxValue ) value = m_maxValue;
167 SetValue(value, true);
168 HiliteValue(event);
169 }
170 if ( !m_buttonUp->EventProcess(event) ) return false;
171 }
172
173 if (m_buttonDown != nullptr)
174 {
175 if ( event.type == m_buttonDown->GetEventType() )
176 {
177 float value = GetValue()-m_stepValue;
178 if ( value < m_minValue ) value = m_minValue;
179 SetValue(value, true);
180 HiliteValue(event);
181 }
182 if ( !m_buttonDown->EventProcess(event) ) return false;
183 }
184
185 if (event.type == EVENT_MOUSE_WHEEL &&
186 Detect(event.mousePos))
187 {
188 float value = GetValue() + (m_stepValue * event.GetData<MouseWheelEventData>()->y);
189 if ( value < m_minValue ) value = m_minValue;
190 if ( value > m_maxValue ) value = m_maxValue;
191 SetValue(value, true);
192 HiliteValue(event);
193 return false;
194 }
195
196 return true;
197 }
198
199
200 // Puts in evidence the edited value.
201
HiliteValue(const Event & event)202 void CEditValue::HiliteValue(const Event &event)
203 {
204 if (m_edit == nullptr) return;
205
206 int pos = m_edit->GetTextLength();
207 if ( m_type == EVT_100 && pos > 0 )
208 {
209 pos --; // not only selects the "%"
210 }
211
212 m_edit->SetCursor(pos, 0);
213 m_interface->SetFocus(m_edit.get());
214
215 Event newEvent = event.Clone();
216 newEvent.type = EVENT_FOCUS;
217 newEvent.customParam = m_edit->GetEventType();
218 m_event->AddEvent(std::move(newEvent)); // defocus the other objects
219 }
220
221
222 // Draw button.
223
Draw()224 void CEditValue::Draw()
225 {
226 if ( (m_state & STATE_VISIBLE) == 0 ) return;
227
228 if ( m_state & STATE_SHADOW )
229 {
230 DrawShadow(m_pos, m_dim);
231 }
232
233 if (m_edit != nullptr)
234 {
235 m_edit->SetState(STATE_ENABLE, TestState(STATE_ENABLE));
236 m_edit->Draw();
237 }
238 if (m_buttonUp != nullptr)
239 {
240 m_buttonUp->SetState(STATE_DEAD, TestState(STATE_DEAD));
241 m_buttonUp->Draw();
242 }
243 if (m_buttonDown != nullptr)
244 {
245 m_buttonDown->SetState(STATE_DEAD, TestState(STATE_DEAD));
246 m_buttonDown->Draw();
247 }
248 }
249
250
251 // Choosing the type of value.
252
SetType(EditValueType type)253 void CEditValue::SetType(EditValueType type)
254 {
255 m_type = type;
256 }
257
GetType()258 EditValueType CEditValue::GetType()
259 {
260 return m_type;
261 }
262
263
264 // Changes the value.
265
SetValue(float value,bool bSendMessage)266 void CEditValue::SetValue(float value, bool bSendMessage)
267 {
268 char text[100];
269
270 if ( m_edit == nullptr ) return;
271
272 text[0] = 0;
273
274 if ( m_type == EVT_INT )
275 {
276 sprintf(text, "%d", static_cast<int>(value));
277 }
278
279 if ( m_type == EVT_FLOAT )
280 {
281 sprintf(text, "%.2f", value);
282 }
283
284 if ( m_type == EVT_100 )
285 {
286 sprintf(text, "%d%%", static_cast<int>(value*100.0f));
287 }
288
289 m_edit->SetText(text);
290
291 if ( bSendMessage )
292 {
293 m_event->AddEvent(Event(m_eventType));
294 }
295 }
296
297 // Return the edited value.
298
GetValue()299 float CEditValue::GetValue()
300 {
301 std::string text;
302 float value = 0.0f;
303
304 if ( m_edit != nullptr )
305 {
306 text = m_edit->GetText(100);
307 sscanf(text.c_str(), "%f", &value);
308
309 if ( m_type == EVT_100 )
310 {
311 value = (value+0.5f)/100.0f;
312 if ( value < 0.01f ) value = 0.0f; // less than 1%?
313 }
314 }
315 return value;
316 }
317
318
319 // Management not for buttons.
320
SetStepValue(float value)321 void CEditValue::SetStepValue(float value)
322 {
323 m_stepValue = value;
324 }
325
GetStepValue()326 float CEditValue::GetStepValue()
327 {
328 return m_stepValue;
329 }
330
331
332 // Management of the minimum value.
333
SetMinValue(float value)334 void CEditValue::SetMinValue(float value)
335 {
336 m_minValue = value;
337 }
338
GetMinValue()339 float CEditValue::GetMinValue()
340 {
341 return m_minValue;
342 }
343
344
345 // Management of the maximum value.
346
SetMaxValue(float value)347 void CEditValue::SetMaxValue(float value)
348 {
349 m_maxValue = value;
350 }
351
GetMaxValue()352 float CEditValue::GetMaxValue()
353 {
354 return m_maxValue;
355 }
356
SetInterface(CInterface * interface)357 void CEditValue::SetInterface(CInterface* interface)
358 {
359 m_interface = interface;
360 }
361
362 }
363