1 /* DialValue.cpp
2  * Copyright (C) 2018, 2019  Sven Jähnichen
3  *
4  * This program 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  * This program 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 this program.  If not, see <https://www.gnu.org/licenses/>.
16  */
17 
18 #include "DialValue.hpp"
19 #include "../BUtilities/to_string.hpp"
20 #include "../BUtilities/stof.hpp"
21 
22 namespace BWidgets
23 {
24 
DialValue()25 DialValue::DialValue () :
26 	DialValue
27 	(
28 		0.0, 0.0, BWIDGETS_DEFAULT_DIALVALUE_WIDTH, BWIDGETS_DEFAULT_DIALVALUE_HEIGHT,
29 		"dialvalue",
30 		BWIDGETS_DEFAULT_VALUE, BWIDGETS_DEFAULT_RANGE_MIN, BWIDGETS_DEFAULT_RANGE_MAX, BWIDGETS_DEFAULT_RANGE_STEP,
31 		BWIDGETS_DEFAULT_VALUE_FORMAT
32 	) {}
33 
DialValue(const double x,const double y,const double width,const double height,const std::string & name,const double value,const double min,const double max,const double step,const std::string & valueFormat)34 DialValue::DialValue (const double x, const double y, const double width, const double height, const std::string& name,
35 		const double value, const double min, const double max, const double step,
36 		const std::string& valueFormat) :
37 	Dial (x, y, width, height, name, value, min, max, step),
38 	valueDisplay(0, 0.75 * height, width, 0.25 * height, name),
39 	valFormat (valueFormat)
40 {
41 	valueDisplay.setText (BUtilities::to_string (value, valueFormat));
42 	valueDisplay.setScrollable (false);
43 	valueDisplay.setEditable (true);
44 	valueDisplay.setCallbackFunction(BEvents::EventType::POINTER_DRAG_EVENT, displayDraggedCallback);
45 	valueDisplay.setCallbackFunction(BEvents::EventType::MESSAGE_EVENT, displayMessageCallback);
46 	add (valueDisplay);
47 }
48 
DialValue(const DialValue & that)49 DialValue::DialValue (const DialValue& that) :
50 		Dial (that), valueDisplay (that.valueDisplay), valFormat (that.valFormat)
51 {
52 	add (valueDisplay);
53 }
54 
~DialValue()55 DialValue::~DialValue () {}
56 
operator =(const DialValue & that)57 DialValue& DialValue::operator= (const DialValue& that)
58 {
59 	release (&valueDisplay);
60 	valFormat = that.valFormat;
61 	Dial::operator= (that);
62 	valueDisplay = that.valueDisplay;
63 	add (valueDisplay);
64 
65 	return *this;
66 }
67 
clone() const68 Widget* DialValue::clone () const {return new DialValue (*this);}
69 
setValue(const double val)70 void DialValue::setValue (const double val)
71 {
72 	Dial::setValue (val);
73 	valueDisplay.setText(BUtilities::to_string (value, valFormat));
74 }
75 
setValueFormat(const std::string & valueFormat)76 void DialValue::setValueFormat (const std::string& valueFormat)
77 {
78 	valFormat = valueFormat;
79 	update ();
80 }
81 
getValueFormat() const82 std::string DialValue::getValueFormat () const {return valFormat;}
83 
getDisplayLabel()84 Label* DialValue::getDisplayLabel () {return &valueDisplay;}
85 
update()86 void DialValue::update ()
87 {
88 	Dial::update();
89 
90 	// Update display
91 	valueDisplay.moveTo (dialCenter.x - dialRadius, dialCenter.y + 0.7 * dialRadius);
92 	valueDisplay.setWidth (2 * dialRadius);
93 	valueDisplay.setHeight (0.5 * dialRadius);
94 	if (valueDisplay.getFont ()->getFontSize () != 0.4 * dialRadius)
95 	{
96 		valueDisplay.getFont ()->setFontSize (0.4 * dialRadius);
97 		valueDisplay.update ();
98 	}
99 	valueDisplay.setText (BUtilities::to_string (value, valFormat));
100 
101 }
102 
applyTheme(BStyles::Theme & theme)103 void DialValue::applyTheme (BStyles::Theme& theme) {applyTheme (theme, name_);}
applyTheme(BStyles::Theme & theme,const std::string & name)104 void DialValue::applyTheme (BStyles::Theme& theme, const std::string& name)
105 {
106 	Dial::applyTheme (theme, name);
107 	valueDisplay.applyTheme (theme, name);
108 	update ();
109 }
110 
updateCoords()111 void DialValue::updateCoords ()
112 {
113 	double w = getEffectiveWidth ();
114 	double h = getEffectiveHeight ();
115 	dialRadius = (w < h / 1.2 ? w / 2 : h / 2.4);
116 	dialCenter.x = getWidth () / 2;
117 	dialCenter.y = getHeight () / 2 - 0.2 * dialRadius;
118 }
119 
displayDraggedCallback(BEvents::Event * event)120 void DialValue::displayDraggedCallback (BEvents::Event* event)
121 {
122 	if (event && event->getWidget())
123 	{
124 		BWidgets::Label* l = (BWidgets::Label*)event->getWidget();
125 		DialValue* d = (DialValue*)l->getParent();
126 		if (d && (!l->getEditMode())) d->DialValue::onPointerDragged ((BEvents::PointerEvent*)event);
127 	}
128 }
129 
displayMessageCallback(BEvents::Event * event)130 void DialValue::displayMessageCallback (BEvents::Event* event)
131 {
132 	if (event && event->getWidget())
133 	{
134 		BWidgets::Label* l = (BWidgets::Label*)event->getWidget();
135 		DialValue* d = (DialValue*)l->getParent();
136 		if (d)
137 		{
138 			double val;
139 			try {val = BUtilities::stof (l->getText());}
140 			catch (std::invalid_argument &ia)
141 			{
142 				fprintf (stderr, "%s\n", ia.what());
143 				d->update();
144 				return;
145 			}
146 
147 			d->setValue (val);
148 			d->update();
149 		}
150 	}
151 }
152 
153 }
154