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 CtlMarker::metadata = { "CtlMarker", &CtlWidget::metadata }; 29 CtlMarker(CtlRegistry * src,LSPMarker * mark)30 CtlMarker::CtlMarker(CtlRegistry *src, LSPMarker *mark): CtlWidget(src, mark) 31 { 32 pClass = &metadata; 33 pPort = NULL; 34 fTransparency = 0.0f; 35 } 36 ~CtlMarker()37 CtlMarker::~CtlMarker() 38 { 39 } 40 slot_change(LSPWidget * sender,void * ptr,void * data)41 status_t CtlMarker::slot_change(LSPWidget *sender, void *ptr, void *data) 42 { 43 CtlMarker *_this = static_cast<CtlMarker *>(ptr); 44 if (_this != NULL) 45 _this->submit_values(); 46 return STATUS_OK; 47 } 48 slot_graph_resize(LSPWidget * sender,void * ptr,void * data)49 status_t CtlMarker::slot_graph_resize(LSPWidget *sender, void *ptr, void *data) 50 { 51 CtlMarker *_this = static_cast<CtlMarker *>(ptr); 52 if (_this != NULL) 53 _this->trigger_expr(); 54 return STATUS_OK; 55 } 56 submit_values()57 void CtlMarker::submit_values() 58 { 59 if (pPort == NULL) 60 return; 61 LSPMarker *mark = widget_cast<LSPMarker>(pWidget); 62 if (mark == NULL) 63 return; 64 65 if (mark->editable()) 66 { 67 float v = mark->value(); 68 if (v == pPort->get_value()) 69 return; 70 71 pPort->set_value(v); 72 pPort->notify_all(); 73 } 74 } 75 init()76 void CtlMarker::init() 77 { 78 CtlWidget::init(); 79 if (pWidget == NULL) 80 return; 81 82 LSPMarker *mark = widget_cast<LSPMarker>(pWidget); 83 if (mark == NULL) 84 return; 85 86 // Initialize color controllers 87 sColor.init_hsl(pRegistry, mark, mark->color(), A_COLOR, A_HUE_ID, A_SAT_ID, A_LIGHT_ID); 88 89 // Bind slots 90 mark->slots()->bind(LSPSLOT_CHANGE, slot_change, this); 91 mark->slots()->bind(LSPSLOT_RESIZE_PARENT, slot_graph_resize, this); 92 93 sAngle.init(pRegistry, this); 94 sDX.init(pRegistry, this); 95 sDY.init(pRegistry, this); 96 sValue.init(pRegistry, this); 97 } 98 set(widget_attribute_t att,const char * value)99 void CtlMarker::set(widget_attribute_t att, const char *value) 100 { 101 LSPMarker *mark = widget_cast<LSPMarker>(pWidget); 102 103 switch (att) 104 { 105 case A_ID: 106 if (mark != NULL) 107 BIND_PORT(pRegistry, pPort, value); 108 break; 109 case A_VALUE: 110 BIND_EXPR(sValue, value); 111 break; 112 case A_OFFSET: 113 if (mark != NULL) 114 PARSE_FLOAT(value, mark->set_offset(__)); 115 break; 116 case A_ANGLE: 117 BIND_EXPR(sAngle, value); 118 break; 119 case A_DX: 120 BIND_EXPR(sDX, value); 121 break; 122 case A_DY: 123 BIND_EXPR(sDY, value); 124 break; 125 case A_SMOOTH: 126 if (mark != NULL) 127 PARSE_BOOL(value, mark->set_smooth(__)); 128 break; 129 case A_FILL: 130 PARSE_FLOAT(value, fTransparency = __); 131 break; 132 case A_BASIS: 133 if (mark != NULL) 134 PARSE_INT(value, mark->set_basis_id(__)); 135 break; 136 case A_PARALLEL: 137 if (mark != NULL) 138 PARSE_INT(value, mark->set_parallel_id(__)); 139 break; 140 case A_WIDTH: 141 if (mark != NULL) 142 PARSE_INT(value, mark->set_width(__)); 143 break; 144 case A_CENTER: 145 if (mark != NULL) 146 PARSE_INT(value, mark->set_center(__)); 147 break; 148 case A_BORDER: 149 if (mark != NULL) 150 PARSE_INT(value, mark->set_border(__)); 151 break; 152 case A_EDITABLE: 153 if (mark != NULL) 154 PARSE_BOOL(value, mark->set_editable(__)); 155 break; 156 case A_MIN: 157 if (mark != NULL) 158 PARSE_FLOAT(value, mark->set_minimum(__)); 159 break; 160 case A_MAX: 161 if (mark != NULL) 162 PARSE_FLOAT(value, mark->set_maximum(__)); 163 break; 164 default: 165 { 166 bool set = sColor.set(att, value); 167 if (!set) 168 CtlWidget::set(att, value); 169 break; 170 } 171 } 172 } 173 end()174 void CtlMarker::end() 175 { 176 if (pPort != NULL) 177 notify(pPort); 178 sColor.set_alpha(fTransparency); 179 180 LSPMarker *mark = widget_cast<LSPMarker>(pWidget); 181 if ((mark != NULL) && (mark->editable())) 182 { 183 const port_t *p = (pPort != NULL) ? pPort->metadata() : NULL; 184 if (p != NULL) 185 { 186 if (p->flags & F_LOWER) 187 mark->set_minimum(p->min); 188 if (p->flags & F_UPPER) 189 mark->set_maximum(p->max); 190 } 191 } 192 193 trigger_expr(); 194 195 CtlWidget::end(); 196 } 197 eval_expr(CtlExpression * expr)198 float CtlMarker::eval_expr(CtlExpression *expr) 199 { 200 LSPMarker *mark = widget_cast<LSPMarker>(pWidget); 201 if (mark == NULL) 202 return 0.0f; 203 204 LSPGraph *g = mark->graph(); 205 if (g == NULL) 206 return 0.0f; 207 208 expr->params()->clear(); 209 expr->params()->set_int("_g_width", g->width()); 210 expr->params()->set_int("_g_height", g->height()); 211 expr->params()->set_int("_a_width", g->area_width()); 212 expr->params()->set_int("_a_height", g->area_height()); 213 214 return expr->evaluate(); 215 } 216 trigger_expr()217 void CtlMarker::trigger_expr() 218 { 219 LSPMarker *mark = widget_cast<LSPMarker>(pWidget); 220 if (mark == NULL) 221 return; 222 223 if (sAngle.valid()) 224 { 225 float angle = eval_expr(&sAngle); 226 mark->set_angle(angle * M_PI); 227 } 228 229 if (sValue.valid()) 230 { 231 float value = eval_expr(&sValue); 232 mark->set_value(value); 233 } 234 235 if (sDX.valid()) 236 { 237 float dx = eval_expr(&sDX); 238 if (sDY.valid()) 239 { 240 float dy = eval_expr(&sDY); 241 mark->set_direction(dx, dy); 242 } 243 else 244 mark->set_dir_x(dx); 245 } 246 else if (sDY.valid()) 247 { 248 float dy = eval_expr(&sDY); 249 mark->set_dir_y(dy); 250 } 251 } 252 notify(CtlPort * port)253 void CtlMarker::notify(CtlPort *port) 254 { 255 CtlWidget::notify(port); 256 257 if (pPort == port) 258 { 259 LSPMarker *mark = widget_cast<LSPMarker>(pWidget); 260 if (mark != NULL) 261 mark->set_value(pPort->get_value()); 262 } 263 264 trigger_expr(); 265 } 266 } /* namespace ctl */ 267 } /* namespace lsp */ 268