/*
* Copyright (C) 2020 Linux Studio Plugins Project
* (C) 2020 Vladimir Sadovnikov
*
* This file is part of lsp-plugins
* Created on: 17 июл. 2017 г.
*
* lsp-plugins is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* lsp-plugins is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with lsp-plugins. If not, see .
*/
#include
namespace lsp
{
namespace tk
{
const w_class_t LSPGroup::metadata = { "LSPGroup", &LSPWidgetContainer::metadata };
LSPGroup::LSPGroup(LSPDisplay *dpy):
LSPWidgetContainer(dpy),
sText(this),
sColor(this),
sFont(this)
{
nRadius = 10;
nBorder = 0;
pWidget = NULL;
bEmbed = false;
pClass = &metadata;
}
LSPGroup::~LSPGroup()
{
do_destroy();
}
status_t LSPGroup::init()
{
sText.bind();
status_t result = LSPWidgetContainer::init();
if (result != STATUS_OK)
return result;
if (pDisplay != NULL)
{
LSPTheme *theme = pDisplay->theme();
if (theme != NULL)
{
sFont.init(theme->font());
sFont.set_size(12.0f);
init_color(C_BACKGROUND, sFont.color());
}
}
init_color(C_LABEL_TEXT, &sColor);
return STATUS_OK;
}
void LSPGroup::destroy()
{
do_destroy();
LSPWidgetContainer::destroy();
}
LSPWidget *LSPGroup::find_widget(ssize_t x, ssize_t y)
{
if (pWidget == NULL)
return NULL;
return (pWidget->inside(x, y)) ? pWidget : NULL;
}
void LSPGroup::query_dimensions(dimensions_t *d)
{
size_t bw = (bEmbed) ? 1 : ::round(nRadius * M_SQRT2 * 0.5) + 1;
size_t dd = bw + nBorder + 1;
d->nGapLeft = dd;
d->nGapRight = dd;
d->nGapTop = dd;
d->nGapBottom = dd;
d->nMinWidth = nBorder*2;
d->nMinHeight = nBorder*2;
LSPString text;
sText.format(&text);
if (!text.is_empty())
{
// Create temporary surface
ISurface *s = (pDisplay != NULL) ? pDisplay->create_surface(1, 1) : NULL;
if (s == NULL)
return;
font_parameters_t fp;
text_parameters_t tp;
sFont.get_parameters(s, &fp);
sFont.get_text_parameters(s, &tp, &text);
d->nMinWidth += tp.Width + nRadius * 3;
d->nMinHeight += fp.Height + nRadius * 2;
d->nGapTop += fp.Height;
// Destroy surface
s->destroy();
delete s;
}
}
void LSPGroup::do_destroy()
{
if (pWidget != NULL)
{
unlink_widget(pWidget);
pWidget = NULL;
}
}
void LSPGroup::set_radius(size_t value)
{
if (nRadius == value)
return;
nRadius = value;
query_resize();
}
void LSPGroup::set_border(size_t value)
{
if (nBorder == value)
return;
nBorder = value;
query_resize();
}
void LSPGroup::set_embed(bool embed)
{
if (bEmbed == embed)
return;
bEmbed = embed;
query_resize();
}
void LSPGroup::render(ISurface *s, bool force)
{
if (nFlags & REDRAW_SURFACE)
force = true;
// Prepare palette
Color bg_color(sBgColor);
Color color(sColor);
color.scale_lightness(brightness());
// lsp_trace("Rendering this=%p, force=%d", this, int(force));
// Draw child
if (pWidget != NULL)
{
if ((force) || (pWidget->redraw_pending()))
{
pWidget->render(s, force);
pWidget->commit_redraw();
}
}
if (force)
{
// Get resource
ssize_t cx = sSize.nLeft + nBorder + 1;
ssize_t cy = sSize.nTop + nBorder + 1;
ssize_t sx = sSize.nWidth - (nBorder << 1) - 1;
ssize_t sy = sSize.nHeight - (nBorder << 1) - 1;
// size_t bw = round(nRadius * M_SQRT2 * 0.5f) + 1;
// Draw background
if (pWidget == NULL)
s->fill_rect(sSize.nLeft, sSize.nTop, sSize.nWidth, sSize.nHeight, bg_color);
else
{
realize_t r;
pWidget->get_dimensions(&r);
// Color red(1.0f, 0.0f, 0.0f);
if ((bEmbed) && (nRadius > 1))
s->fill_round_frame(
sSize.nLeft, sSize.nTop, sSize.nWidth, sSize.nHeight,
r.nLeft, r.nTop, r.nWidth, r.nHeight,
nRadius-1, SURFMASK_B_CORNER,
bg_color
);
else
s->fill_frame(
sSize.nLeft, sSize.nTop, sSize.nWidth, sSize.nHeight,
r.nLeft, r.nTop, r.nWidth, r.nHeight,
bg_color
);
}
// Draw frame
bool aa = s->set_antialiasing(true);
s->wire_round_rect(cx, cy, sx-1, sy-1, nRadius, 0x0e, 2.0f, color);
// Draw text frame
LSPString text;
sText.format(&text);
if (!text.is_empty())
{
// Draw text border
font_parameters_t fp;
text_parameters_t tp;
sFont.get_parameters(s, &fp);
sFont.get_text_parameters(s, &tp, &text);
s->fill_round_rect(cx-1, cy-1, 4 + nRadius + tp.Width, fp.Height + 4, nRadius, 0x04, color);
// Show text
Color font(sFont.raw_color());
font.scale_lightness(brightness());
sFont.draw(s, cx + 4, cy + fp.Ascent + nBorder, font, &text);
}
s->set_antialiasing(aa);
}
}
status_t LSPGroup::add(LSPWidget *widget)
{
if (pWidget != NULL)
return STATUS_ALREADY_EXISTS;
widget->set_parent(this);
pWidget = widget;
query_resize();
return STATUS_OK;
}
status_t LSPGroup::remove(LSPWidget *widget)
{
if (pWidget != widget)
return STATUS_NOT_FOUND;
unlink_widget(pWidget);
pWidget = NULL;
return STATUS_OK;
}
void LSPGroup::size_request(size_request_t *r)
{
if (pWidget != NULL)
pWidget->size_request(r);
if (r->nMinWidth < 0)
r->nMinWidth = 0;
if (r->nMinHeight < 0)
r->nMinHeight = 0;
if (pWidget != NULL)
{
r->nMinWidth += pWidget->padding()->horizontal();
r->nMinHeight += pWidget->padding()->vertical();
}
dimensions_t d;
query_dimensions(&d);
if (r->nMinWidth >= 0)
{
size_t n = r->nMinWidth + d.nGapLeft + d.nGapRight;
if (n < d.nMinWidth)
r->nMinWidth = d.nMinWidth;
else
r->nMinWidth = n;
}
if (r->nMinHeight >= 0)
{
size_t n = r->nMinHeight + d.nGapTop + d.nGapBottom;
if (n < d.nMinHeight)
r->nMinHeight = d.nMinHeight;
else
r->nMinHeight = n;
}
// Align to 8-pixel grid
// r->nMinWidth = ((r->nMinWidth + 7) >> 3) << 3;
// r->nMinHeight = ((r->nMinHeight + 7) >> 3) << 3;
if ((r->nMaxWidth >= 0) && (r->nMaxWidth < r->nMinWidth))
r->nMaxWidth = r->nMinWidth;
if ((r->nMaxHeight >= 0) && (r->nMaxHeight < r->nMinHeight))
r->nMaxHeight = r->nMinHeight;
}
void LSPGroup::realize(const realize_t *r)
{
LSPWidgetContainer::realize(r);
if (pWidget == NULL)
return;
dimensions_t d;
query_dimensions(&d);
size_request_t sr;
pWidget->size_request(&sr);
realize_t rc;
rc.nLeft = r->nLeft + d.nGapLeft + pWidget->padding()->left();
rc.nTop = r->nTop + d.nGapTop + pWidget->padding()->top();
rc.nWidth = r->nWidth - d.nGapLeft - d.nGapRight - pWidget->padding()->horizontal();
rc.nHeight = r->nHeight - d.nGapTop - d.nGapBottom - pWidget->padding()->vertical();
if ((sr.nMaxWidth > 0) && (sr.nMaxWidth < rc.nWidth))
{
rc.nLeft += (rc.nWidth - sr.nMaxWidth) >> 1;
rc.nWidth = sr.nMaxWidth;
}
if ((sr.nMaxHeight > 0) && (sr.nMaxHeight < rc.nHeight))
{
rc.nTop += (rc.nHeight - sr.nMaxHeight) >> 1;
rc.nHeight = sr.nMaxHeight;
}
pWidget->realize(&rc);
}
} /* namespace tk */
} /* namespace lsp */