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: 10 июл. 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/tk/tk.h>
23 
24 namespace lsp
25 {
26     namespace tk
27     {
28         const w_class_t LSPLed::metadata = { "LSPLed", &LSPWidget::metadata };
29 
LSPLed(LSPDisplay * dpy)30         LSPLed::LSPLed(LSPDisplay *dpy):
31             LSPWidget(dpy),
32             sColor(this),
33             sHoleColor(this)
34         {
35             nSize       = 8;
36             bOn         = false;
37             pClass      = &metadata;
38         }
39 
~LSPLed()40         LSPLed::~LSPLed()
41         {
42         }
43 
init()44         status_t LSPLed::init()
45         {
46             status_t result = LSPWidget::init();
47             if (result != STATUS_OK)
48                 return result;
49 
50             sHoleColor.bind("hole_color");
51             init_color(C_GREEN, &sColor);
52 
53             return STATUS_OK;
54         }
55 
set_on(bool on)56         void LSPLed::set_on(bool on)
57         {
58             if (bOn == on)
59                 return;
60             bOn   = on;
61             query_draw();
62         }
63 
set_off(bool off)64         void LSPLed::set_off(bool off)
65         {
66             bool on = ! off;
67             if (bOn == on)
68                 return;
69             bOn   = on;
70             query_draw();
71         }
72 
set_size(size_t size)73         void LSPLed::set_size(size_t size)
74         {
75             if (nSize == size)
76                 return;
77 
78             nSize = size;
79             query_resize();
80         }
81 
draw(ISurface * s)82         void LSPLed::draw(ISurface *s)
83         {
84             IGradient *cp;
85 
86             // Estimate palette
87             Color bg_color(sBgColor);
88             Color hole(sHoleColor);
89             Color col(sColor);
90             Color glass(sGlassColor);
91 
92             col.scale_lightness(brightness());
93             glass.scale_lightness(brightness());
94 
95             // Draw background
96             s->fill_rect(0, 0, sSize.nWidth, sSize.nHeight, bg_color);
97 
98             // Move to center of the led
99             ssize_t cx = (sSize.nWidth >> 1);
100             ssize_t cy = (sSize.nHeight >> 1);
101 
102             // Draw hole
103             s->fill_circle(cx, cy, (nSize >> 1) + 1, hole);
104 
105             bool aa = s->set_antialiasing(true);
106 
107             if (bOn)
108             {
109                 // Draw light
110                 cp = s->radial_gradient(cx, cy, 0, cx, cy, nSize);
111                 cp->add_color(0.0, col, 0.5f);
112                 cp->add_color(1.0, col, 1.0f);
113                 s->fill_circle(cx, cy, nSize, cp);
114                 delete cp;
115 
116                 // Draw led spot
117                 Color c_light(col);
118                 c_light.lightness(c_light.lightness() * 1.5);
119 
120                 cp = s->radial_gradient(cx, cy, nSize >> 3, cx, cy, nSize >> 1);
121                 cp->add_color(0.0f, c_light);
122                 cp->add_color(1.0f, col);
123                 s->fill_circle(cx, cy, nSize >> 1, cp);
124                 delete cp;
125 
126                 // Add blink
127                 cp = s->radial_gradient(cx + (nSize >> 3), cy - ssize_t(nSize >> 3), 0, cx, cy, nSize >> 1);
128                 cp->add_color(0.0, 1.0, 1.0, 1.0, 0.0f);
129                 cp->add_color(1.0, 1.0, 1.0, 1.0, 1.0f);
130                 s->fill_circle(cx, cy, (nSize >> 1) - 1, cp);
131                 delete cp;
132             }
133             else
134             {
135                 Color c;
136                 c.blend(col, glass, 0.4);
137 
138                 // Draw led glass
139                 cp = s->radial_gradient(cx, cy, nSize >> 3, cx, cy, nSize >> 1);
140                 cp->add_color(0.0, col);
141                 cp->add_color(1.0, glass);
142                 s->fill_circle(cx, cy, (nSize >> 1)+1, cp);
143                 delete cp;
144 
145                 // Add blink
146                 cp = s->radial_gradient(cx + (nSize >> 3), cy - ssize_t(nSize >> 3), cx, cy, 0, nSize >> 1);
147                 cp->add_color(0.0, 1.0, 1.0, 1.0, 0.8);
148                 cp->add_color(1.0, 1.0, 1.0, 1.0, 1.0);
149                 s->fill_circle(cx, cy, (nSize >> 1) - 1, cp);
150                 delete cp;
151             }
152 
153             s->set_antialiasing(aa);
154         }
155 
size_request(size_request_t * r)156         void LSPLed::size_request(size_request_t *r)
157         {
158             r->nMinWidth        = (nSize << 1);
159             r->nMinHeight       = (nSize << 1);
160             r->nMaxWidth        = r->nMinWidth;
161             r->nMaxHeight       = r->nMinHeight;
162         }
163     } /* namespace tk */
164 } /* namespace lsp */
165