1 /*
2  *  tracker/DialogWithValues.cpp
3  *
4  *  Copyright 2009 Peter Barth
5  *
6  *  This file is part of Milkytracker.
7  *
8  *  Milkytracker is free software: you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation, either version 3 of the License, or
11  *  (at your option) any later version.
12  *
13  *  Milkytracker is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with Milkytracker.  If not, see <http://www.gnu.org/licenses/>.
20  *
21  */
22 
23 /*
24  *  DialogWithValues.cpp
25  *  MilkyTracker
26  *
27  *  Created by Peter Barth on 25.10.05.
28  *
29  */
30 
31 #include "DialogWithValues.h"
32 #include "Screen.h"
33 #include "StaticText.h"
34 #include "MessageBoxContainer.h"
35 #include "Font.h"
36 #include "ListBox.h"
37 #include "Seperator.h"
38 
DialogWithValues(PPScreen * screen,DialogResponder * responder,pp_int32 id,const PPString & caption,ValueStyles style)39 DialogWithValues::DialogWithValues(PPScreen* screen,
40 								   DialogResponder* responder,
41 								   pp_int32 id,
42 								   const PPString& caption,
43 								   ValueStyles style) :
44 	PPDialogBase()
45 {
46 	valueOne = 0;
47 	valueTwo = 0;
48 	valueOneRangeStart = (float)-0x7FFFFFFF;
49 	valueOneRangeEnd = (float)0x7FFFFFFE;
50 	valueTwoRangeStart = (float)-0x7FFFFFFF;
51 	valueTwoRangeEnd = (float)0x7FFFFFFE;
52 	valueOneIncreaseStep = 1.0f;
53 	valueTwoIncreaseStep = 1.0f;
54 	numValueOneDecimals = 0;
55 	numValueTwoDecimals = 0;
56 
57 	switch (style)
58 	{
59 		case ValueStyleEnterOneValue:
60 #ifdef __LOWRES__
61 			initDialog(screen, responder, id, caption, 290, 110+15, 26+15, "Ok", "Cancel");
62 #else
63 			initDialog(screen, responder, id, caption, 290, 110, 26, "Ok", "Cancel");
64 #endif
65 			break;
66 
67 		case ValueStyleEnterTwoValues:
68 #ifdef __LOWRES__
69 			initDialog(screen, responder, id, caption, 290, 142+15, 26+15, "Ok", "Cancel");
70 #else
71 			initDialog(screen, responder, id, caption, 290, 142, 26, "Ok", "Cancel");
72 #endif
73 			break;
74 	}
75 
76 	pp_int32 x = getMessageBoxContainer()->getLocation().x;
77 
78 	pp_int32 width = getMessageBoxContainer()->getSize().width;
79 
80 	pp_int32 x2 = x;
81 	pp_int32 y2 = getMessageBoxContainer()->getControlByID(MESSAGEBOX_STATICTEXT_MAIN_CAPTION)->getLocation().y;
82 
83 	PPButton* button;
84 
85 	if (style == ValueStyleEnterOneValue ||
86 		style == ValueStyleEnterTwoValues)
87 	{
88 		//setValueOneCaption("Enter new volume in percent");
89 		y2 +=20+12;
90 
91 		// enter edit field 1
92 		x2 = x + width / 2 - (100+35)/2;
93 
94 		PPListBox* listBox = new PPListBox(MESSAGEBOX_LISTBOX_VALUE_ONE, screen, this, PPPoint(x2, y2), PPSize(100,12), true, true, false);
95 		listBox->showSelection(false);
96 		listBox->setBorderColor(messageBoxContainerGeneric->getColor());
97 		listBox->setMaxEditSize(8);
98 		messageBoxContainerGeneric->addControl(listBox);
99 
100 		button = new PPButton(MESSAGEBOX_BUTTON_INCREASE_VALUEONE, screen, this, PPPoint(x2 + listBox->getSize().width + 2, y2), PPSize(16, 11));
101 		button->setText("+");
102 		messageBoxContainerGeneric->addControl(button);
103 
104 		button = new PPButton(MESSAGEBOX_BUTTON_DECREASE_VALUEONE, screen, this, PPPoint(x2 + listBox->getSize().width + 2 + button->getSize().width + 1, y2), PPSize(16, 11));
105 		button->setText("-");
106 		messageBoxContainerGeneric->addControl(button);
107 
108 #ifdef __LOWRES__
109 		pp_int32 height = getMessageBoxContainer()->getSize().height;
110 		pp_int32 y = getMessageBoxContainer()->getLocation().y;
111 
112 		const char buttonTexts[] = {'1','2','3','4','5','6','7','8','9','0','+','-','.','<','>'};
113 
114 		pp_int32 bWidth = (width - 22*2 - 2*3) / sizeof(buttonTexts);
115 		pp_int32 x2_2 = x+4;
116 
117 		pp_int32 y2_2 = y+height - 4 - 13;
118 
119 		messageBoxContainerGeneric->addControl(new PPSeperator(0, screen, PPPoint(x2_2-1, y2_2-3), width-2*3, messageBoxContainerGeneric->getColor(), true));
120 
121 		pp_uint32 i = 0;
122 		for (i = 0; i < sizeof(buttonTexts); i++)
123 		{
124 			button = new PPButton(MESSAGEBOX_BUTTON_KEYS_BASE+i, screen, this, PPPoint(x2_2, y2_2), PPSize(bWidth+1, 13));
125 			button->setText(buttonTexts[i]);
126 			messageBoxContainerGeneric->addControl(button);
127 			x2_2+=bWidth;
128 		}
129 
130 		bWidth = 22;
131 
132 		button = new PPButton(MESSAGEBOX_BUTTON_KEYS_BASE+i, screen, this, PPPoint(x2_2, y2_2), PPSize(bWidth+1-3, 13));
133 		button->setFont(PPFont::getFont(PPFont::FONT_TINY));
134 		button->setText("Del");
135 		messageBoxContainerGeneric->addControl(button);
136 		x2_2+=bWidth-3;
137 		i++;
138 		button = new PPButton(MESSAGEBOX_BUTTON_KEYS_BASE+i, screen, this, PPPoint(x2_2, y2_2), PPSize(bWidth+1, 13));
139 		button->setFont(PPFont::getFont(PPFont::FONT_TINY));
140 		button->setText("Back");
141 		messageBoxContainerGeneric->addControl(button);
142 #endif
143 	}
144 
145 	if (style == ValueStyleEnterTwoValues)
146 	{
147 		//setValueTwoCaption("Enter new volume in percent");
148 		y2 += 32;
149 
150 		// enter edit field 2
151 		x2 = x + width / 2 - (100+35)/2;
152 
153 		PPListBox* listBox = new PPListBox(MESSAGEBOX_LISTBOX_VALUE_TWO, screen, this, PPPoint(x2, y2), PPSize(100,12), true, true, false);
154 		listBox->showSelection(false);
155 		listBox->setBorderColor(messageBoxContainerGeneric->getColor());
156 		listBox->setMaxEditSize(8);
157 		messageBoxContainerGeneric->addControl(listBox);
158 
159 		button = new PPButton(MESSAGEBOX_BUTTON_INCREASE_VALUETWO, screen, this, PPPoint(x2 + listBox->getSize().width + 2, y2), PPSize(16, 11));
160 		button->setText("+");
161 		messageBoxContainerGeneric->addControl(button);
162 
163 		button = new PPButton(MESSAGEBOX_BUTTON_DECREASE_VALUETWO, screen, this, PPPoint(x2 + listBox->getSize().width + 2 + button->getSize().width + 1, y2), PPSize(16, 11));
164 		button->setText("-");
165 		messageBoxContainerGeneric->addControl(button);
166 	}
167 
168 	fitListBoxes();
169 	updateListBoxes();
170 }
171 
setValueOneCaption(const PPString & caption)172 void DialogWithValues::setValueOneCaption(const PPString& caption)
173 {
174 	PPControl* ctrl = messageBoxContainerGeneric->getControlByID(MESSAGEBOX_STATICTEXT_VALUE_ONE_CAPTION);
175 	if (ctrl)
176 		messageBoxContainerGeneric->removeControl(ctrl);
177 
178 	pp_int32 width = messageBoxContainerGeneric->getSize().width;
179 
180 	pp_int32 x = messageBoxContainerGeneric->getLocation().x;
181 	pp_int32 y = messageBoxContainerGeneric->getControlByID(MESSAGEBOX_STATICTEXT_MAIN_CAPTION)->getLocation().y;
182 
183 	y+=20;
184 
185 	x += width / 2 - (PPFont::getFont(PPFont::FONT_SYSTEM)->getStrWidth(caption) / 2);
186 
187 	messageBoxContainerGeneric->addControl(new PPStaticText(MESSAGEBOX_STATICTEXT_VALUE_ONE_CAPTION, parentScreen, this, PPPoint(x, y), caption, true));
188 }
189 
setValueTwoCaption(const PPString & caption)190 void DialogWithValues::setValueTwoCaption(const PPString& caption)
191 {
192 	PPControl* ctrl = messageBoxContainerGeneric->getControlByID(MESSAGEBOX_STATICTEXT_VALUE_TWO_CAPTION);
193 	if (ctrl)
194 		messageBoxContainerGeneric->removeControl(ctrl);
195 
196 	pp_int32 width = messageBoxContainerGeneric->getSize().width;
197 
198 	pp_int32 x = messageBoxContainerGeneric->getLocation().x;
199 	pp_int32 y = messageBoxContainerGeneric->getControlByID(MESSAGEBOX_STATICTEXT_MAIN_CAPTION)->getLocation().y;
200 
201 	y+=20+32;
202 
203 	x += width / 2 - (PPFont::getFont(PPFont::FONT_SYSTEM)->getStrWidth(caption) / 2);
204 
205 	messageBoxContainerGeneric->addControl(new PPStaticText(MESSAGEBOX_STATICTEXT_VALUE_TWO_CAPTION, parentScreen, this, PPPoint(x, y), caption, true));
206 }
207 
show(bool b)208 void DialogWithValues::show(bool b/* = true*/)
209 {
210 	if (b)
211 		listBoxEnterEditState(MESSAGEBOX_LISTBOX_VALUE_ONE);
212 	PPDialogBase::show(b);
213 }
214 
handleEvent(PPObject * sender,PPEvent * event)215 pp_int32 DialogWithValues::handleEvent(PPObject* sender, PPEvent* event)
216 {
217 	if (event->getID() == eKeyDown)
218 	{
219 		pp_uint16 keyCode = *((pp_uint16*)event->getDataPtr());
220 		if (keyCode == VK_TAB)
221 		{
222 			switchListBox();
223 			event->cancel();
224 		}
225 	}
226 	else if (event->getID() == eCommand || event->getID() == eCommandRepeat)
227 	{
228 		switch (reinterpret_cast<PPControl*>(sender)->getID())
229 		{
230 			case PP_MESSAGEBOX_BUTTON_YES:
231 			{
232 				commitChanges();
233 				break;
234 			}
235 
236 			case MESSAGEBOX_BUTTON_INCREASE_VALUEONE:
237 			{
238 				setValueOne(valueOne+valueOneIncreaseStep);
239 				parentScreen->paintControl(messageBoxContainerGeneric->getControlByID(MESSAGEBOX_LISTBOX_VALUE_ONE));
240 				break;
241 			}
242 
243 			case MESSAGEBOX_BUTTON_DECREASE_VALUEONE:
244 			{
245 				setValueOne(valueOne-valueOneIncreaseStep);
246 				parentScreen->paintControl(messageBoxContainerGeneric->getControlByID(MESSAGEBOX_LISTBOX_VALUE_ONE));
247 				break;
248 			}
249 
250 			case MESSAGEBOX_BUTTON_INCREASE_VALUETWO:
251 			{
252 				setValueTwo(valueTwo+valueOneIncreaseStep);
253 				parentScreen->paintControl(messageBoxContainerGeneric->getControlByID(MESSAGEBOX_LISTBOX_VALUE_TWO));
254 				break;
255 			}
256 
257 			case MESSAGEBOX_BUTTON_DECREASE_VALUETWO:
258 			{
259 				setValueTwo(valueTwo-valueOneIncreaseStep);
260 				parentScreen->paintControl(messageBoxContainerGeneric->getControlByID(MESSAGEBOX_LISTBOX_VALUE_TWO));
261 				break;
262 			}
263 
264 		}
265 	}
266 	else if (event->getID() == eValueChanged)
267 	{
268 		switch (reinterpret_cast<PPControl*>(sender)->getID())
269 		{
270 			// song title
271 			case MESSAGEBOX_LISTBOX_VALUE_ONE:
272 			{
273 				const PPString* str = *(reinterpret_cast<PPString* const*>(event->getDataPtr()));
274 				setValueOne((float)atof(*str));
275 				break;
276 			}
277 
278 			case MESSAGEBOX_LISTBOX_VALUE_TWO:
279 			{
280 				const PPString* str = *(reinterpret_cast<PPString* const*>(event->getDataPtr()));
281 				setValueTwo((float)atof(*str));
282 				break;
283 			}
284 		}
285 	}
286 
287 	return PPDialogBase::handleEvent(sender, event);
288 }
289 
setValueOneRange(float start,float end,pp_int32 numDecimals)290 void DialogWithValues::setValueOneRange(float start, float end, pp_int32 numDecimals)
291 {
292 	valueOneRangeStart = start; valueOneRangeEnd = end;  numValueOneDecimals = numDecimals;
293 	fitListBoxes();
294 	setValueOne(valueOne);
295 }
setValueTwoRange(float start,float end,pp_int32 numDecimals)296 void DialogWithValues::setValueTwoRange(float start, float end, pp_int32 numDecimals)
297 {
298 	valueTwoRangeStart = start; valueTwoRangeEnd = end; numValueTwoDecimals = numDecimals;
299 	fitListBoxes();
300 	setValueTwo(valueTwo);
301 }
302 
fitListBoxes()303 void DialogWithValues::fitListBoxes()
304 {
305 	fitListBox(MESSAGEBOX_LISTBOX_VALUE_ONE, valueOneRangeStart, valueOneRangeEnd, numValueOneDecimals);
306 	fitListBox(MESSAGEBOX_LISTBOX_VALUE_TWO, valueTwoRangeStart, valueTwoRangeEnd, numValueTwoDecimals);
307 }
308 
fitListBox(pp_int32 id,float valueOneRangeStart,float valueOneRangeEnd,pp_int32 numDecimals)309 void DialogWithValues::fitListBox(pp_int32 id, float valueOneRangeStart, float valueOneRangeEnd, pp_int32 numDecimals)
310 {
311 	pp_int32 width = messageBoxContainerGeneric->getSize().width;
312 	pp_int32 x = messageBoxContainerGeneric->getLocation().x;
313 
314 	char buffer1[100];
315 	char buffer2[100];
316 
317 	sprintf(buffer1, "%%.%if", numDecimals);
318 
319 	PPListBox* listBox = static_cast<PPListBox*>(messageBoxContainerGeneric->getControlByID(id));
320 	if (listBox)
321 	{
322 		sprintf(buffer2, buffer1, valueOneRangeStart);
323 		pp_int32 len = (pp_int32)strlen(buffer2);
324 		sprintf(buffer2, buffer1,  valueOneRangeEnd);
325 		if ((pp_int32)strlen(buffer2) > len) len = (pp_int32)strlen(buffer2);
326 
327 		pp_int32 y2 = listBox->getLocation().y;
328 
329 		pp_int32 x2 = x + width / 2 - ((len*8)+10+35)/2;
330 
331 		listBox->setLocation(PPPoint(x2, y2));
332 		listBox->setSize(PPSize(len*8+10, listBox->getSize().height));
333 
334 		x2+=listBox->getSize().width + 2;
335 
336 		PPButton* button = static_cast<PPButton*>(messageBoxContainerGeneric->getControlByID(id+1));
337 		y2 = button->getLocation().y;
338 		button->setLocation(PPPoint(x2, y2));
339 
340 		x2+=button->getSize().width+1;
341 		button = static_cast<PPButton*>(messageBoxContainerGeneric->getControlByID(id+2));
342 		y2 = button->getLocation().y;
343 		button->setLocation(PPPoint(x2, y2));
344 	}
345 }
346 
updateListBoxes()347 void DialogWithValues::updateListBoxes()
348 {
349 	updateListBox(MESSAGEBOX_LISTBOX_VALUE_ONE, valueOne, numValueOneDecimals);
350 	updateListBox(MESSAGEBOX_LISTBOX_VALUE_TWO, valueTwo, numValueTwoDecimals);
351 }
352 
updateListBox(pp_int32 id,float val,pp_int32 numDecimals)353 void DialogWithValues::updateListBox(pp_int32 id, float val, pp_int32 numDecimals)
354 {
355 	char buffer1[100];
356 	char buffer2[100];
357 
358 	sprintf(buffer1, "%%.%if", numDecimals);
359 
360 	PPListBox* listBox = static_cast<PPListBox*>(messageBoxContainerGeneric->getControlByID(id));
361 	if (listBox)
362 	{
363 		sprintf(buffer2, buffer1, val);
364 		listBox->clear();
365 		listBox->addItem(buffer2);
366 	}
367 }
368 
commitChanges()369 void DialogWithValues::commitChanges()
370 {
371 	PPListBox* listBox = static_cast<PPListBox*>(messageBoxContainerGeneric->getControlByID(MESSAGEBOX_LISTBOX_VALUE_ONE));
372 	if (listBox)
373 		listBox->commitChanges();
374 
375 	listBox = static_cast<PPListBox*>(messageBoxContainerGeneric->getControlByID(MESSAGEBOX_LISTBOX_VALUE_TWO));
376 	if (listBox)
377 		listBox->commitChanges();
378 }
379 
listBoxEnterEditState(pp_int32 id)380 void DialogWithValues::listBoxEnterEditState(pp_int32 id)
381 {
382 	PPListBox* listBox = static_cast<PPListBox*>(messageBoxContainerGeneric->getControlByID(id));
383 	if (listBox)
384 		listBox->placeCursorAtEnd();
385 }
386 
switchListBox()387 void DialogWithValues::switchListBox()
388 {
389 	if (messageBoxContainerGeneric->getControlByID(MESSAGEBOX_LISTBOX_VALUE_TWO) == NULL)
390 		return;
391 
392 	PPListBox* listBox = static_cast<PPListBox*>(messageBoxContainerGeneric->getControlByID(MESSAGEBOX_LISTBOX_VALUE_ONE));
393 	if (listBox->isEditing())
394 	{
395 		listBox->commitChanges();
396 		listBoxEnterEditState(MESSAGEBOX_LISTBOX_VALUE_TWO);
397 		messageBoxContainerGeneric->setFocus(messageBoxContainerGeneric->getControlByID(MESSAGEBOX_LISTBOX_VALUE_TWO));
398 		parentScreen->paintControl(messageBoxContainerGeneric);
399 		return;
400 	}
401 
402 	listBox = static_cast<PPListBox*>(messageBoxContainerGeneric->getControlByID(MESSAGEBOX_LISTBOX_VALUE_TWO));
403 	if (listBox->isEditing())
404 	{
405 		listBox->commitChanges();
406 		listBoxEnterEditState(MESSAGEBOX_LISTBOX_VALUE_ONE);
407 		messageBoxContainerGeneric->setFocus(messageBoxContainerGeneric->getControlByID(MESSAGEBOX_LISTBOX_VALUE_ONE));
408 		parentScreen->paintControl(messageBoxContainerGeneric);
409 		return;
410 	}
411 
412 	listBoxEnterEditState(MESSAGEBOX_LISTBOX_VALUE_ONE);
413 	messageBoxContainerGeneric->setFocus(messageBoxContainerGeneric->getControlByID(MESSAGEBOX_LISTBOX_VALUE_ONE));
414 	parentScreen->paintControl(messageBoxContainerGeneric);
415 }
416