1 /* B.Oops
2  * Glitch effect sequencer LV2 plugin
3  *
4  * Copyright (C) 2020 by Sven Jähnichen
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.  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, see <https://www.gnu.org/licenses/>.
18  */
19 
20 #ifndef PADBUTTON_HPP_
21 #define PADBUTTON_HPP_
22 
23 #include "BWidgets/Button.hpp"
24 #include "BWidgets/Focusable.hpp"
25 #include "BWidgets/Label.hpp"
26 #include "drawbutton.hpp"
27 #include "drawSymbol.hpp"
28 
29 class PadButton : public BWidgets::Button, public BWidgets::Focusable
30 {
31 public:
PadButton()32 	PadButton	() : PadButton (0.0, 0.0, BWIDGETS_DEFAULT_BUTTON_WIDTH, BWIDGETS_DEFAULT_BUTTON_HEIGHT, "padbutton", NOSYMBOL, 0.0) {}
PadButton(const double x,const double y,const double width,const double height,const std::string & name,SymbolIndex symbol=NOSYMBOL,double defaultValue=0.0)33 	PadButton	(const double x, const double y, const double width, const double height,
34 			 const std::string& name, SymbolIndex symbol = NOSYMBOL, double defaultValue = 0.0) :
35 		Button (x, y, width, height, name, defaultValue),
36 		Focusable (std::chrono::milliseconds (BWIDGETS_DEFAULT_FOCUS_IN_MS),
37 			   std::chrono::milliseconds (BWIDGETS_DEFAULT_FOCUS_OUT_MS)),
38 		symbol (symbol), fgColors (BWIDGETS_DEFAULT_BGCOLORS), txColors (BWIDGETS_DEFAULT_FGCOLORS),
39      		focusLabel_ (0, 0, 40, 20, name_ + BWIDGETS_DEFAULT_FOCUS_NAME, "")
40 	{
41 		focusLabel_.setStacking (BWidgets::STACKING_OVERSIZE);
42 		focusLabel_.setText (symboltxt[symbol + 1]);
43    		focusLabel_.resize ();
44    		focusLabel_.hide ();
45    		add (focusLabel_);
46 	}
47 
PadButton(const PadButton & that)48 	PadButton (const PadButton& that) :
49 		Button (that), Focusable (that),
50 		symbol (that.symbol), fgColors (that.fgColors), txColors (that.txColors),
51 		focusLabel_ (that.focusLabel_)
52 	{
53 		focusLabel_.hide();
54 		add (focusLabel_);
55 	}
56 
operator =(const PadButton & that)57 	PadButton& operator= (const PadButton& that)
58 	{
59 		release (&focusLabel_);
60 		focusLabel_ = that.focusLabel_;
61 		symbol = that.symbol;
62 		fgColors = that.fgColors;
63 		txColors = that.fgColors;
64 		focusLabel_.hide();
65 
66 		Widget::operator= (that);
67 		Focusable::operator= (that);
68 
69 		add (focusLabel_);
70 
71 		return *this;
72 
73 	}
74 
clone() const75 	virtual Widget* clone () const override {return new PadButton (*this);}
76 
setSymbol(const SymbolIndex sym)77 	virtual void setSymbol (const SymbolIndex sym)
78 	{
79 		symbol = sym;
80 		focusLabel_.setText (symboltxt[symbol + 1]);
81 		focusLabel_.resize();
82 		update();
83 	}
84 
applyTheme(BStyles::Theme & theme)85 	virtual void applyTheme (BStyles::Theme& theme) override {applyTheme (theme, name_);}
86 
applyTheme(BStyles::Theme & theme,const std::string & name)87 	virtual void applyTheme (BStyles::Theme& theme, const std::string& name) override
88 	{
89 		Button::applyTheme (theme, name);
90 		focusLabel_.applyTheme (theme, name + BWIDGETS_DEFAULT_FOCUS_NAME);
91 		focusLabel_.resize();
92 
93 		void* fgPtr = theme.getStyle(name, BWIDGETS_KEYWORD_FGCOLORS);
94 		if (fgPtr)
95 		{
96 			fgColors = *((BColors::ColorSet*) fgPtr);
97 			update ();
98 		}
99 
100 		void* txPtr = theme.getStyle(name, BWIDGETS_KEYWORD_TEXTCOLORS);
101 		if (txPtr)
102 		{
103 			txColors = *((BColors::ColorSet*) txPtr);
104 			update ();
105 		}
106 	}
107 
onFocusIn(BEvents::FocusEvent * event)108 	virtual void onFocusIn (BEvents::FocusEvent* event) override
109 	{
110 		if (event && event->getWidget())
111 		{
112 			if (symbol != NOSYMBOL)
113 			{
114 				BUtilities::Point pos = event->getPosition();
115 				raiseToTop();
116 				focusLabel_.moveTo (pos.x - 0.5 * focusLabel_.getWidth(), pos.y - focusLabel_.getHeight());
117 				focusLabel_.show();
118 			}
119 
120 			else focusLabel_.hide();
121 		}
122 		Widget::onFocusIn (event);
123 	}
124 
onFocusOut(BEvents::FocusEvent * event)125 	virtual void onFocusOut (BEvents::FocusEvent* event) override
126 	{
127 		if (event && event->getWidget()) focusLabel_.hide();
128 		Widget::onFocusOut (event);
129 	}
130 
131 protected:
132 	SymbolIndex symbol;
133 	BColors::ColorSet fgColors;
134 	BColors::ColorSet txColors;
135 	BWidgets::Label focusLabel_;
136 
getPadColor()137 	virtual BColors::Color getPadColor ()
138 	{
139 		BColors::Color butColor = *fgColors.getColor (getState ());
140 		butColor.applyBrightness (getValue() ? BWIDGETS_DEFAULT_SHADOWED : BWIDGETS_DEFAULT_NORMALLIGHTED);
141 		return butColor;
142 	}
143 
getSymbolColor()144 	virtual BColors::Color getSymbolColor ()
145 	{
146 		BColors::Color symColor = *txColors.getColor (getState ());
147 		symColor.applyBrightness (getValue() ? BWIDGETS_DEFAULT_SHADOWED : BWIDGETS_DEFAULT_NORMALLIGHTED);
148 		return symColor;
149 	}
150 
draw(const BUtilities::RectArea & area)151 	virtual void draw (const BUtilities::RectArea& area) override
152 	{
153 		if ((!widgetSurface_) || (cairo_surface_status (widgetSurface_) != CAIRO_STATUS_SUCCESS)) return;
154 
155 		if ((getWidth () >= 6) && (getHeight () >= 6))
156 		{
157 			// Draw super class widget elements first
158 			Widget::draw (area);
159 
160 			cairo_t* cr = cairo_create (widgetSurface_);
161 			if (cairo_status (cr) == CAIRO_STATUS_SUCCESS)
162 			{
163 				// Limit cairo-drawing area
164 				cairo_rectangle (cr, area.getX (), area.getY (), area.getWidth (), area.getHeight ());
165 				cairo_clip (cr);
166 
167 				const double x0 = getXOffset ();
168 				const double y0 = getYOffset ();
169 				const double w = getEffectiveWidth ();
170 				const double h = getEffectiveHeight ();
171 
172 				const BColors::Color butColor = getPadColor();
173 				const BColors::Color symColor = getSymbolColor();
174 
175 				drawButton (cr, x0, y0, w, h, butColor);
176 				drawSymbol (cr, x0, y0, w, h, symColor, symbol);
177 
178 				cairo_destroy (cr);
179 			}
180 		}
181 	}
182 };
183 
184 #endif /* PADBUTTON_HPP_ */
185