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: 6 июл. 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 LSPLabel::metadata = { "LSPLabel", &LSPWidget::metadata }; 29 LSPLabel(LSPDisplay * dpy)30 LSPLabel::LSPLabel(LSPDisplay *dpy): 31 LSPWidget(dpy), 32 sFont(dpy, this), 33 sText(this) 34 { 35 fVAlign = 0.5f; 36 fHAlign = 0.5f; 37 nBorder = 0; 38 nMinWidth = -1; 39 nMinHeight = -1; 40 pClass = &metadata; 41 42 sFont.set_size(12.0f); 43 } 44 ~LSPLabel()45 LSPLabel::~LSPLabel() 46 { 47 } 48 init()49 status_t LSPLabel::init() 50 { 51 status_t result = LSPWidget::init(); 52 if (result != STATUS_OK) 53 return result; 54 55 sFont.init(); 56 init_color(C_LABEL_TEXT, sFont.color()); 57 58 sText.bind(); 59 60 return STATUS_OK; 61 } 62 destroy()63 void LSPLabel::destroy() 64 { 65 } 66 set_valign(float align)67 void LSPLabel::set_valign(float align) 68 { 69 fVAlign = align; 70 query_draw(); 71 } 72 set_halign(float align)73 void LSPLabel::set_halign(float align) 74 { 75 fHAlign = align; 76 query_draw(); 77 } 78 set_align(float halign,float valign)79 void LSPLabel::set_align(float halign, float valign) 80 { 81 fVAlign = valign; 82 fHAlign = halign; 83 query_draw(); 84 } 85 set_border(float border)86 void LSPLabel::set_border(float border) 87 { 88 nBorder = border; 89 query_resize(); 90 } 91 draw(ISurface * s)92 void LSPLabel::draw(ISurface *s) 93 { 94 // Initialize palette 95 Color bg_color(sBgColor); 96 Color font_color(sFont.raw_color()); 97 98 font_color.scale_lightness(brightness()); 99 100 // Draw background 101 s->clear(bg_color); 102 103 // Get text parameters 104 font_parameters_t fp; 105 text_parameters_t tp; 106 sFont.get_parameters(s, &fp); 107 108 // Estimate number of lines 109 LSPString text; 110 sText.format(&text); 111 112 ssize_t n_lines = 1 + text.count('\n'); 113 ssize_t dy = sSize.nHeight - fp.Height*n_lines - (nBorder << 1); 114 ssize_t y = nBorder - fp.Descent + dy * fVAlign; 115 116 // Estimate text size 117 ssize_t last = 0, curr = 0, tail = 0, len = text.length(); 118 119 while (curr < len) 120 { 121 // Get next line indexes 122 curr = text.index_of(last, '\n'); 123 if (curr < 0) 124 { 125 curr = len; 126 tail = len; 127 } 128 else 129 { 130 tail = curr; 131 if ((tail > last) && (text.at(tail-1) == '\r')) 132 --tail; 133 } 134 135 // Calculate text location 136 sFont.get_text_parameters(s, &tp, &text, last, tail); 137 ssize_t dx = sSize.nWidth - tp.Width - (nBorder << 1); 138 ssize_t x = nBorder + dx * fHAlign - tp.XBearing; 139 y += fp.Height; 140 141 sFont.draw(s, x, y, font_color, &text, last, tail); 142 last = curr + 1; 143 144 // s->line(x - 3, y - 3, x + 3, y + 3, 1, red); 145 // s->line(x + 3, y - 3, x - 3, y + 3, 1, red); 146 // 147 // s->line(x - 3 + tp.XAdvance, y - 3, x + 3 + tp.XAdvance, y + 3, 1, yellow); 148 // s->line(x + 3 + tp.XAdvance, y - 3, x - 3 + tp.XAdvance, y + 3, 1, yellow); 149 // s->line(x - 3 + tp.XAdvance, y - 3, x + 3 + tp.XAdvance, y + 3, 1, yellow); 150 // s->line(x + 3 + tp.XBearing, y - 3, x - 3 + tp.XBearing, y + 3, 1, yellow); 151 } 152 } 153 set_min_width(ssize_t value)154 void LSPLabel::set_min_width(ssize_t value) 155 { 156 if (nMinWidth == value) 157 return; 158 nMinWidth = value; 159 query_resize(); 160 } 161 set_min_height(ssize_t value)162 void LSPLabel::set_min_height(ssize_t value) 163 { 164 if (nMinHeight == value) 165 return; 166 nMinHeight = value; 167 query_resize(); 168 } 169 size_request(size_request_t * r)170 void LSPLabel::size_request(size_request_t *r) 171 { 172 r->nMinWidth = 0; 173 r->nMinHeight = 0; 174 r->nMaxWidth = -1; 175 r->nMaxHeight = -1; 176 177 LSPString text; 178 sText.format(&text); 179 180 if (pDisplay == NULL) 181 return; 182 ISurface *s = pDisplay->create_surface(1, 1); 183 if (s == NULL) 184 return; 185 186 text_parameters_t tp; 187 font_parameters_t fp; 188 sFont.get_parameters(s, &fp); 189 sFont.get_multiline_text_parameters(s, &tp, &text); 190 if (tp.Height < fp.Height) 191 tp.Height = fp.Height; 192 193 r->nMinWidth = tp.Width + (nBorder + 1) * 2; 194 r->nMinHeight = tp.Height + (nBorder + 1) * 2; 195 if (fill()) 196 { 197 r->nMaxWidth = -1; 198 r->nMaxHeight = -1; 199 } 200 else 201 { 202 r->nMaxWidth = r->nMinWidth; 203 r->nMaxHeight = r->nMinHeight; 204 } 205 206 // Apply size constraints 207 if ((nMinWidth >= 0) && (r->nMinWidth < nMinWidth)) 208 r->nMinWidth = nMinWidth; 209 if ((nMinHeight >= 0) && (r->nMinHeight < nMinHeight)) 210 r->nMinHeight = nMinHeight; 211 212 s->destroy(); 213 delete s; 214 } 215 query_safe_resize()216 void LSPLabel::query_safe_resize() 217 { 218 size_request_t sr; 219 size_request(&sr); 220 if (sr.nMinWidth < 0) 221 sr.nMinWidth = sSize.nWidth; 222 if (sr.nMinHeight < 0) 223 sr.nMinHeight = sSize.nHeight; 224 225 if ((sr.nMinWidth > sSize.nWidth) || (sr.nMinHeight > sSize.nHeight)) 226 query_resize(); 227 else if ((((sSize.nWidth - sr.nMinWidth) > 4) || ((sSize.nHeight - sr.nMinHeight) > 4)) && (!fill())) 228 query_resize(); 229 else 230 query_draw(); 231 } 232 233 } /* namespace tk */ 234 } /* namespace lsp */ 235