1 /*
2  * Copyright (C) 2002 - David W. Durham
3  *
4  * This file is part of ReZound, an audio editing application.
5  *
6  * ReZound is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published
8  * by the Free Software Foundation; either version 2 of the License,
9  * or (at your option) any later version.
10  *
11  * ReZound is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * 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, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
19  */
20 
21 #include "FXTextParamValue.h"
22 
23 #include <stdlib.h>
24 #include <math.h> // for log10
25 
26 #include <istring>
27 
28 #include <CNestedDataFile/CNestedDataFile.h>
29 
30 #include "utils.h"
31 
32 /*
33 	- This is the text entry widget used over and over by ReZound on action dialogs
34 	- Its purpose is to select a constant value for a parameter to an action
35 */
36 
37 FXDEFMAP(FXTextParamValue) FXTextParamValueMap[]=
38 {
39 	//Message_Type				ID					Message_Handler
40 
41 	FXMAPFUNC(SEL_COMMAND,			FXTextParamValue::ID_VALUE_SPINNER,	FXTextParamValue::onValueSpinnerChange),
42 	FXMAPFUNC(SEL_COMMAND,			FXTextParamValue::ID_VALUE_TEXTBOX,	FXTextParamValue::onValueTextBoxChange),
43 };
44 
FXIMPLEMENT(FXTextParamValue,FXHorizontalFrame,FXTextParamValueMap,ARRAYNUMBER (FXTextParamValueMap))45 FXIMPLEMENT(FXTextParamValue,FXHorizontalFrame,FXTextParamValueMap,ARRAYNUMBER(FXTextParamValueMap))
46 
47 FXTextParamValue::FXTextParamValue(FXComposite *p,int opts,const char *_name,const double _initialValue,const double _minValue,const double _maxValue) :
48 	FXHorizontalFrame(p,opts|FRAME_RAISED | LAYOUT_FILL_X|LAYOUT_CENTER_Y,0,0,0,0, 2,2,4,4, 0,0),
49 
50 	name(_name),
51 
52 	isNumeric(true),
53 
54 	initialValue(istring(_initialValue)),
55 	minValue(_minValue),
56 	maxValue(_maxValue),
57 
58 	panel(new FXHorizontalFrame(this,FRAME_NONE|LAYOUT_FILL_Y|LAYOUT_CENTER_X,0,0,0,0, 0,0,0,0, 0,0)),
59 		titleLabel(new FXLabel(panel,gettext(_name),NULL,LABEL_NORMAL|LAYOUT_CENTER_Y)),
60 		valueTextBox(new FXTextField(panel,8,this,ID_VALUE_TEXTBOX, TEXTFIELD_NORMAL | LAYOUT_CENTER_Y)),
61 		valueSpinner(new FXSpinner(panel,0,this,ID_VALUE_SPINNER, SPIN_NORMAL|SPIN_NOTEXT | LAYOUT_FILL_Y, 0,0,0,0, 0,0,0,0)),
62 		unitsLabel(new FXLabel(panel,"",NULL,LABEL_NORMAL|LAYOUT_CENTER_Y)),
63 
64 	textFont(getApp()->getNormalFont())
65 {
66 	valueTextBox->setNumColumns((FXint)(log10(maxValue)+1));
67 
68 	// create a smaller font to use
69         FXFontDesc d;
70         textFont->getFontDesc(d);
71         d.size-=10;
72         textFont=new FXFont(getApp(),d);
73 
74 	valueSpinner->setRange(-10,10);
75 	setValue(_initialValue);
76 
77 	//setFontOfAllChildren(this,textFont);
78 }
79 
FXTextParamValue(FXComposite * p,int opts,const char * _name,const string _initialValue)80 FXTextParamValue::FXTextParamValue(FXComposite *p,int opts,const char *_name,const string _initialValue) :
81 	FXHorizontalFrame(p,opts|FRAME_RAISED | LAYOUT_FILL_X|LAYOUT_CENTER_Y,0,0,0,0, 2,2,4,4, 0,0),
82 
83 	name(_name),
84 
85 	isNumeric(false),
86 
87 	initialValue(_initialValue),
88 
89 	titleLabel(new FXLabel(this,gettext(_name),NULL,LABEL_NORMAL|LAYOUT_CENTER_Y)),
90 	valueTextBox(new FXTextField(this,8,this,ID_VALUE_TEXTBOX, TEXTFIELD_NORMAL | LAYOUT_CENTER_Y|LAYOUT_FILL_X)),
91 	valueSpinner(NULL),
92 	unitsLabel(NULL),
93 
94 	textFont(getApp()->getNormalFont())
95 {
96 	// create a smaller font to use
97         FXFontDesc d;
98         textFont->getFontDesc(d);
99         d.size-=10;
100         textFont=new FXFont(getApp(),d);
101 
102 	//setFontOfAllChildren(this,textFont);
103 	setText(_initialValue);
104 }
105 
~FXTextParamValue()106 FXTextParamValue::~FXTextParamValue()
107 {
108 	delete textFont;
109 }
110 
setUnits(const FXString units,const FXString tipText)111 void FXTextParamValue::setUnits(const FXString units,const FXString tipText)
112 {
113 	if(isNumeric)
114 	{
115 		unitsLabel->setText(units);
116 		unitsLabel->setTipText(tipText);
117 	}
118 }
119 
onValueSpinnerChange(FXObject * sender,FXSelector sel,void * ptr)120 long FXTextParamValue::onValueSpinnerChange(FXObject *sender,FXSelector sel,void *ptr)
121 {
122 	double v=atof(valueTextBox->getText().text());
123 	v+=valueSpinner->getValue();
124 	valueSpinner->setValue(0);
125 	valueTextBox->setText(istring(v).c_str());
126 
127 	validateRange();
128 
129 	changed();
130 	return 1;
131 }
132 
onValueTextBoxChange(FXObject * sender,FXSelector sel,void * ptr)133 long FXTextParamValue::onValueTextBoxChange(FXObject *sender,FXSelector sel,void *ptr)
134 {
135 	// just verity that a value character was typed???
136 
137 	validateRange();
138 	changed();
139 	return 1;
140 }
141 
getValue()142 const double FXTextParamValue::getValue()
143 {
144 	validateRange();
145 	return atof(valueTextBox->getText().text());
146 }
147 
setValue(const double value)148 void FXTextParamValue::setValue(const double value)
149 {
150 	valueTextBox->setText(istring(value).c_str());
151 	validateRange();
152 	changed();
153 }
154 
getText()155 const string FXTextParamValue::getText()
156 {
157 	validateRange();
158 	return valueTextBox->getText().text();
159 }
160 
setText(const string value)161 void FXTextParamValue::setText(const string value)
162 {
163 	validateRange();
164 	valueTextBox->setText(value.c_str());
165 	changed();
166 }
167 
setRange(const double _minValue,const double _maxValue)168 void FXTextParamValue::setRange(const double _minValue,const double _maxValue)
169 {
170 	minValue=_minValue;
171 	maxValue=_maxValue;
172 	valueTextBox->setNumColumns((FXint)(log10(maxValue)+1));
173 	validateRange();
174 	changed();
175 }
176 
validateRange()177 void FXTextParamValue::validateRange()
178 {
179 	if(!isNumeric)
180 		return;
181 
182 	double v=atof(valueTextBox->getText().text());
183 
184 	if(v<minValue)
185 		v=minValue;
186 	else if(v>maxValue)
187 		v=maxValue;
188 
189 	valueTextBox->setText(istring(v).c_str());
190 }
191 
getName() const192 const string FXTextParamValue::getName() const
193 {
194 	return name;
195 }
196 
setTipText(const FXString & text)197 void FXTextParamValue::setTipText(const FXString &text)
198 {
199 	titleLabel->setTipText(text);
200 	valueTextBox->setTipText(text);
201 	if(isNumeric)
202 		valueSpinner->setTipText(text);
203 }
204 
getTipText() const205 FXString FXTextParamValue::getTipText() const
206 {
207 	return titleLabel->getTipText();
208 }
209 
readFromFile(const string & prefix,CNestedDataFile * f)210 void FXTextParamValue::readFromFile(const string &prefix,CNestedDataFile *f)
211 {
212 	const string key=prefix DOT getName() DOT "value";
213 	if(f->keyExists(key))
214 	{
215 		if(isNumeric)
216 			setValue(f->getValue<double>(key));
217 		else
218 			setText(f->getValue<string>(key));
219 	}
220 	else
221 	{
222 		if(isNumeric)
223 			setValue(atof(initialValue.c_str())); // ??? not i18n safe (i.e. if the locale was ru and the initial value was "1.234")
224 		else
225 			setText(initialValue);
226 	}
227 	changed();
228 }
229 
writeToFile(const string & prefix,CNestedDataFile * f)230 void FXTextParamValue::writeToFile(const string &prefix,CNestedDataFile *f)
231 {
232 	const string key=prefix DOT getName();
233 	if(isNumeric)
234 		f->setValue<double>(key DOT "value",getValue());
235 	else
236 		f->setValue<string>(key DOT "value",getText());
237 }
238 
changed()239 void FXTextParamValue::changed()
240 {
241 	if(target)
242 		target->handle(this,FXSEL(SEL_COMMAND,getSelector()),NULL);
243 }
244 
245