1 /*
2  * Copyright (C) 2020 Linux Studio Plugins Project <https://lsp-plug.in/>
3  *           (C) 2020 Vladimir Sadovnikov <sadko4u@gmail.com>
4  *
5  * This file is part of lsp-plugins
6  * Created on: 27 июл. 2017 г.
7  *
8  * lsp-plugins is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * any later version.
12  *
13  * lsp-plugins 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 Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with lsp-plugins. If not, see <https://www.gnu.org/licenses/>.
20  */
21 
22 #include <ui/ctl/ctl.h>
23 
24 namespace lsp
25 {
26     namespace ctl
27     {
28         const ctl_class_t CtlAxis::metadata = { "CtlAxis", &CtlWidget::metadata };
29 
CtlAxis(CtlRegistry * src,LSPAxis * axis)30         CtlAxis::CtlAxis(CtlRegistry *src, LSPAxis *axis): CtlWidget(src, axis)
31         {
32             pClass          = &metadata;
33             nFlags          = 0;
34             pPort           = NULL;
35         }
36 
~CtlAxis()37         CtlAxis::~CtlAxis()
38         {
39         }
40 
slot_graph_resize(LSPWidget * sender,void * ptr,void * data)41         status_t CtlAxis::slot_graph_resize(LSPWidget *sender, void *ptr, void *data)
42         {
43             CtlAxis *_this    = static_cast<CtlAxis *>(ptr);
44             if (_this != NULL)
45                 _this->trigger_expr();
46             return STATUS_OK;
47         }
48 
init()49         void CtlAxis::init()
50         {
51             CtlWidget::init();
52             sMin.init(pRegistry, this);
53             sMax.init(pRegistry, this);
54             sAngle.init(pRegistry, this);
55             sLength.init(pRegistry, this);
56             sDX.init(pRegistry, this);
57             sDY.init(pRegistry, this);
58 
59             LSPAxis *axis   = widget_cast<LSPAxis>(pWidget);
60             if (axis == NULL)
61                 return;
62 
63             // Initialize color controllers
64             sColor.init_hsl(pRegistry, axis, axis->color(), A_COLOR, A_HUE_ID, A_SAT_ID, A_LIGHT_ID);
65 
66             axis->slots()->bind(LSPSLOT_RESIZE_PARENT, slot_graph_resize, this);
67         }
68 
set(widget_attribute_t att,const char * value)69         void CtlAxis::set(widget_attribute_t att, const char *value)
70         {
71             LSPAxis *axis   = widget_cast<LSPAxis>(pWidget);
72 
73             switch (att)
74             {
75                 case A_ID:
76                     BIND_PORT(pRegistry, pPort, value);
77                     break;
78                 case A_ANGLE:
79                     BIND_EXPR(sAngle, value);
80                     break;
81                 case A_DX:
82                     BIND_EXPR(sDX, value);
83                     break;
84                 case A_DY:
85                     BIND_EXPR(sDY, value);
86                     break;
87                 case A_LENGTH:
88                     BIND_EXPR(sLength, value);
89                     break;
90                 case A_MIN:
91                     BIND_EXPR(sMin, value);
92                     nFlags |= F_MIN_SET;
93                     break;
94                 case A_MAX:
95                     BIND_EXPR(sMax, value);
96                     nFlags |= F_MAX_SET;
97                     break;
98                 case A_CENTER:
99                     if (axis != NULL)
100                         PARSE_INT(value, axis->set_center_id(__));
101                     break;
102                 case A_BASIS:
103                     if (axis != NULL)
104                         PARSE_BOOL(value, axis->set_basis(__));
105                     break;
106                 case A_LOGARITHMIC:
107                     PARSE_BOOL(value, {
108                             nFlags |= F_LOG_SET;
109                             if (__)
110                                 nFlags |= F_LOG;
111                             else
112                                 nFlags &= ~F_LOG;
113                         });
114                     break;
115                 case A_WIDTH:
116                     if (axis != NULL)
117                         PARSE_INT(value, axis->set_line_width(__));
118                     break;
119 
120                 default:
121                 {
122                     bool set = sColor.set(att, value);
123                     if (!set)
124                         CtlWidget::set(att, value);
125                     break;
126                 }
127             }
128         }
129 
end()130         void CtlAxis::end()
131         {
132             CtlWidget::end();
133             update_axis();
134             trigger_expr();
135         }
136 
eval_expr(CtlExpression * expr)137         float CtlAxis::eval_expr(CtlExpression *expr)
138         {
139             LSPAxis *axis = widget_cast<LSPAxis>(pWidget);
140             if (axis == NULL)
141                 return 0.0f;
142 
143             LSPGraph *g = axis->graph();
144             if (g == NULL)
145                 return 0.0f;
146 
147             expr->params()->clear();
148             expr->params()->set_int("_g_width", g->width());
149             expr->params()->set_int("_g_height", g->height());
150             expr->params()->set_int("_a_width", g->area_width());
151             expr->params()->set_int("_a_height", g->area_height());
152 
153             return expr->evaluate();
154         }
155 
trigger_expr()156         void CtlAxis::trigger_expr()
157         {
158             LSPAxis *axis   = widget_cast<LSPAxis>(pWidget);
159             if (axis == NULL)
160                 return;
161 
162             if (sAngle.valid())
163             {
164                 float angle = eval_expr(&sAngle);
165                 axis->set_angle(angle * M_PI);
166             }
167 
168             if (sLength.valid())
169             {
170                 float length = eval_expr(&sLength);
171                 axis->set_length(length);
172             }
173 
174             if (sDX.valid())
175             {
176                 float dx = eval_expr(&sDX);
177                 if (sDY.valid())
178                 {
179                     float dy = eval_expr(&sDY);
180                     axis->set_direction(dx, dy);
181                 }
182                 else
183                     axis->set_dir_x(dx);
184             }
185             else if (sDY.valid())
186             {
187                 float dy = eval_expr(&sDY);
188                 axis->set_dir_y(dy);
189             }
190         }
191 
update_axis()192         void CtlAxis::update_axis()
193         {
194             LSPAxis *axis   = widget_cast<LSPAxis>(pWidget);
195             if (axis == NULL)
196                 return;
197 
198             float amin = (sMin.valid()) ? sMin.evaluate() : 0.0f;
199             float amax = (sMax.valid()) ? sMax.evaluate() : 0.0f;
200 
201             const port_t *mdata = (pPort != NULL) ? pPort->metadata() : NULL;
202             if (mdata == NULL)
203             {
204                 if (nFlags & F_MIN_SET)
205                     axis->set_min_value(amin);
206                 if (nFlags & F_MAX_SET)
207                     axis->set_max_value(amax);
208                 if (nFlags & F_LOG_SET)
209                     axis->set_log_scale(nFlags & F_LOG);
210                 return;
211             }
212 
213             axis->set_min_value((nFlags & F_MIN_SET) ? pPort->get_value() * amin : mdata->min);
214             axis->set_max_value((nFlags & F_MAX_SET) ? pPort->get_value() * amax : mdata->max);
215             if (nFlags & F_LOG_SET)
216                 axis->set_log_scale(nFlags & F_LOG);
217             else
218                 axis->set_log_scale(((is_decibel_unit(mdata->unit)) || (mdata->flags & F_LOG)));
219         }
220 
notify(CtlPort * port)221         void CtlAxis::notify(CtlPort *port)
222         {
223             CtlWidget::notify(port);
224 
225             update_axis();
226             trigger_expr();
227         }
228 
229     } /* namespace ctl */
230 } /* namespace lsp */
231