1 /* B.Shapr
2  * Beat / envelope shaper LV2 plugin
3  *
4  * Copyright (C) 2019 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, or (at your option)
9  * 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, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19  */
20 
21 #include "MonitorWidget.hpp"
22 #include <cmath>
23 
MonitorWidget()24 MonitorWidget::MonitorWidget () : MonitorWidget (0, 0, 0, 0, "monitor") {}
25 
MonitorWidget(const double x,const double y,const double width,const double height,const std::string & name)26 MonitorWidget::MonitorWidget (const double x, const double y, const double width, const double height, const std::string& name) :
27         Widget (x, y, width, height, name),
28         fgColors (BColors::whites), zoom (0.25), pat (nullptr)
29 {
30         clear ();
31         setClickable (false);
32         makePattern ();
33 }
34 
~MonitorWidget()35 MonitorWidget::~MonitorWidget ()
36 {
37         if (pat) cairo_pattern_destroy (pat);
38 }
39 
clear()40 void MonitorWidget::clear () {data.fill ({0.0f, 0.0f});}
41 
addData(const unsigned int pos,const Range range)42 void MonitorWidget::addData (const unsigned int pos, const Range range)
43 {
44         unsigned int nr = LIMIT (pos, 0, MONITORBUFFERSIZE - 1);
45         data[nr] = range;
46 }
47 
setZoom(const double factor)48 void MonitorWidget::setZoom (const double factor)
49 {
50         zoom = factor;
51         update ();
52 }
getZoom() const53 double MonitorWidget::getZoom () const {return zoom;}
54 
redrawRange(const unsigned int start,const unsigned int end)55 void MonitorWidget::redrawRange (const unsigned int start, const unsigned int end)
56 {
57         unsigned int s = LIMIT (int (start) - 1, 0, MONITORBUFFERSIZE - 1);
58         unsigned int e = LIMIT (end + 1, 0, MONITORBUFFERSIZE - 1);
59         double xabs = getAbsolutePosition().x;
60         double yabs = getAbsolutePosition().y;
61         double x1 = getWidth() * s / (MONITORBUFFERSIZE - 1);
62         double w = getWidth() * (e - s) / (MONITORBUFFERSIZE - 1);
63 
64         drawData (s, e);
65         if (isVisible ()) postRedisplay (BUtilities::RectArea (xabs + x1, yabs, w, getHeight()));
66 }
67 
applyTheme(BStyles::Theme & theme)68 void MonitorWidget::applyTheme (BStyles::Theme& theme) {applyTheme (theme, name_);}
69 
applyTheme(BStyles::Theme & theme,const std::string & name)70 void MonitorWidget::applyTheme (BStyles::Theme& theme, const std::string& name)
71 {
72 	Widget::applyTheme (theme, name);
73 
74 	void* fgPtr = theme.getStyle(name, BWIDGETS_KEYWORD_FGCOLORS);
75 	if (fgPtr)
76 	{
77 		fgColors = *((BColors::ColorSet*) fgPtr);
78 		update ();
79 	}
80 }
81 
update()82 void MonitorWidget::update ()
83 {
84         makePattern ();
85         Widget::update ();
86 }
87 
makePattern()88 void MonitorWidget::makePattern ()
89 {
90         if (pat) cairo_pattern_destroy (pat);
91         pat = cairo_pattern_create_linear (0, 0, 0, getHeight());
92         BColors::Color col = *fgColors.getColor (getState ());
93         cairo_pattern_add_color_stop_rgba (pat, 1, col.getRed (), col.getGreen (), col.getBlue (), 0.6 * col.getAlpha ());
94         cairo_pattern_add_color_stop_rgba (pat, 0.5, col.getRed (), col.getGreen (), col.getBlue (), 0.1 * col.getAlpha ());
95         cairo_pattern_add_color_stop_rgba (pat, 0, col.getRed (), col.getGreen (), col.getBlue (), 0.6 * col.getAlpha ());
96 }
97 
drawData(const unsigned int start,const unsigned int end)98 void MonitorWidget::drawData (const unsigned int start, const unsigned int end)
99 {
100         if ((!widgetSurface_) || (cairo_surface_status (widgetSurface_) != CAIRO_STATUS_SUCCESS)) return;
101 
102         BColors::Color col = *fgColors.getColor (getState ());
103 	cairo_t* cr = cairo_create (widgetSurface_);
104 
105 	if (cairo_status (cr) == CAIRO_STATUS_SUCCESS)
106 	{
107 		// Limit cairo-drawing area
108                 cairo_set_line_width (cr, 0);
109                 double x0 = ceil (getWidth() * start / (MONITORBUFFERSIZE - 1));
110                 double x1 = floor (getWidth() * end / (MONITORBUFFERSIZE - 1));
111 		cairo_rectangle (cr, x0, 0, x1 - x0, getHeight());
112 		cairo_clip (cr);
113 
114 		cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0);
115 		cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
116 		cairo_paint (cr);
117 
118                 cairo_set_line_width (cr, 2);
119                 cairo_move_to (cr, getWidth() * double (start) / (MONITORBUFFERSIZE - 1), getHeight() * (0.5  - (0.48 * LIMIT ((data[start].max / zoom), -1, 1))));
120                 for (int i = start + 1; i <= int (end); ++i)
121                 {
122                         cairo_line_to (cr, getWidth() * double (i) / (MONITORBUFFERSIZE - 1), getHeight() * (0.5  - (0.48 * LIMIT ((data[i].max / zoom), -1, 1))));
123                 }
124                 cairo_set_source_rgba (cr, CAIRO_RGBA (col));
125                 cairo_stroke_preserve (cr);
126                 cairo_set_line_width (cr, 0);
127                 cairo_line_to (cr, getWidth() * double (end) / (MONITORBUFFERSIZE - 1), getHeight() * 0.5);
128                 cairo_line_to (cr, getWidth() * double (start) / (MONITORBUFFERSIZE - 1), getHeight() * 0.5);
129                 cairo_close_path (cr);
130                 cairo_set_source (cr, pat);
131                 cairo_fill (cr);
132 
133                 cairo_set_line_width (cr, 2);
134                 cairo_move_to (cr, getWidth() * double (start) / (MONITORBUFFERSIZE - 1), getHeight() * (0.5  - (0.48 * LIMIT ((data[start].min / zoom), -1, 1))));
135                 for (int i = start + 1; i <= int (end); ++i)
136                 {
137                         cairo_line_to (cr, getWidth() * double (i) / (MONITORBUFFERSIZE - 1), getHeight() * (0.5  - (0.48 * LIMIT ((data[i].min / zoom), -1, 1))));
138                 }
139                 cairo_set_source_rgba (cr, CAIRO_RGBA (col));
140                 cairo_stroke_preserve (cr);
141                 cairo_set_line_width (cr, 0);
142                 cairo_line_to (cr, getWidth() * double (end) / (MONITORBUFFERSIZE - 1), getHeight() * 0.5);
143                 cairo_line_to (cr, getWidth() * double (start) / (MONITORBUFFERSIZE - 1), getHeight() * 0.5);
144                 cairo_close_path (cr);
145                 cairo_set_source (cr, pat);
146                 cairo_fill (cr);
147 
148                 cairo_destroy (cr);
149         }
150 }
151 
draw(const BUtilities::RectArea & area)152 void MonitorWidget::draw (const BUtilities::RectArea& area)
153 {
154         drawData (0, MONITORBUFFERSIZE - 1);
155 }
156