mirror of
https://github.com/tuxbox-fork-migrations/recycled-ni-neutrino.git
synced 2025-08-29 08:21:07 +02:00
* INFOBAR_SHADOW to SHADOW because it's not only used in infoviewer
* INFOBAR_SHADOW_TEXT to MENUFOOT_TEXT because it's the proper name
This is in preparation to make footer colors configurable
Origin commit data
------------------
Commit: bc39d1e14e
Author: vanhofen <vanhofen@gmx.de>
Date: 2016-08-14 (Sun, 14 Aug 2016)
Origin message was:
------------------
- colors: some internal renamings
* INFOBAR_SHADOW to SHADOW because it's not only used in infoviewer
* INFOBAR_SHADOW_TEXT to MENUFOOT_TEXT because it's the proper name
This is in preparation to make footer colors configurable
470 lines
14 KiB
C++
470 lines
14 KiB
C++
/*
|
|
* $Id: buttons.cpp,v 1.10 2010/07/12 08:24:55 dbt Exp $
|
|
*
|
|
* (C) 2003 by thegoodguy <thegoodguy@berlios.de>
|
|
* (C) 2011 B1 Systems GmbH, Author: Stefan Seyfried
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program 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 General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <config.h>
|
|
#endif
|
|
|
|
#include <global.h>
|
|
#include <neutrino.h>
|
|
|
|
#include <gui/widget/buttons.h>
|
|
#include <gui/customcolor.h>
|
|
#include <system/settings.h>
|
|
// #include <driver/stacktrace.h>
|
|
|
|
|
|
|
|
/* paintButtons usage,
|
|
use this function for painting icons with captions in horizontal or vertical direction.
|
|
Icons automatically use the available maxwidth.
|
|
If not enough space is available, captions are shortened.
|
|
If there is extra space, space between icons is increased.
|
|
|
|
* x set horizontal startposition
|
|
* y set vertical startposition
|
|
* footerwidth set width of buttonbar as similar to footer, value 0 (default) means: do nothing,
|
|
then paint it extra
|
|
* count set count of buttons
|
|
* content set struct buttonlabel with iconfile and locales, for an empty text let locale
|
|
constant empty, so you can paint icons without captions,
|
|
* maxwidth maximum horizontal space for the buttons
|
|
* footerheight set height of buttonbar as similar to footer, value 0 (default) means:
|
|
value calculates automaticly depends of maximal height of icon and caption
|
|
* show optional, default value is true (show button), if false, then no show and return the height of the button.
|
|
*/
|
|
|
|
int paintButtons( const int &x,
|
|
const int &y,
|
|
const int &footerwidth,
|
|
const int &count,
|
|
const button_label * const content,
|
|
const int &maxwidth,
|
|
const int &footerheight) {
|
|
return paintButtons(content, count, x, y, footerwidth, footerheight, maxwidth, true, NULL, NULL);
|
|
};
|
|
|
|
int paintButtons( const button_label * const content,
|
|
const int &count,
|
|
const int &x,
|
|
const int &y,
|
|
const int &footerwidth,
|
|
const int &footerheight,
|
|
const int &maxwidth,
|
|
bool show,
|
|
int *wantedwidth,
|
|
int *wantedheight)
|
|
{
|
|
button_label_ext content_ext[count];
|
|
for (int i = 0; i < count; i++) {
|
|
content_ext[i].button = content[i].button;
|
|
content_ext[i].locale = content[i].locale;
|
|
content_ext[i].text = NULL;
|
|
content_ext[i].width = 0;
|
|
content_ext[i].maximize = false;
|
|
}
|
|
return paintButtons(content_ext, count, x, y, footerwidth, footerheight, maxwidth, show, wantedwidth, wantedheight);
|
|
}
|
|
|
|
int paintButtons( const button_label_ext * const content,
|
|
const int &count,
|
|
const int &x,
|
|
const int &y,
|
|
const int &footerwidth,
|
|
const int &footerheight,
|
|
const int &maxwidth,
|
|
bool show,
|
|
int *wantedwidth,
|
|
int *wantedheight)
|
|
{
|
|
CFrameBuffer *frameBuffer = CFrameBuffer::getInstance();
|
|
Font * font = g_Font[SNeutrinoSettings::FONT_TYPE_INFOBAR_SMALL];
|
|
int cnt = count;
|
|
int x_footer = x;
|
|
int y_footer = y;
|
|
int w_footer = footerwidth;
|
|
int h_footer = 0;
|
|
|
|
int w_space = 10; //minimal space between buttons
|
|
int h_space = 4; //minimal space between caption and/or icon and border
|
|
int x_icon = x_footer + w_space;
|
|
int x_caption = 0;
|
|
|
|
int x_button = x_icon;
|
|
int h_button = 0;
|
|
|
|
//calculate max of h + w
|
|
//icon
|
|
int h_max_icon = 0;
|
|
int w_icons = 0;
|
|
|
|
//text
|
|
int w_text = 0;
|
|
int h_max_text = font->getHeight();
|
|
|
|
int count_icons = 0;
|
|
int count_labels = 0;
|
|
/* more than 16 buttons? noooooo*/
|
|
int iconw[16];
|
|
int iconh[16];
|
|
int fwidth[16];
|
|
const char *buttontext[16];
|
|
|
|
/* sanity check... */
|
|
if (count > 16 || count == 0)
|
|
{
|
|
fprintf(stderr, "paintButtons does only support max 16 buttons yet (%d)\n", count);
|
|
// print_stacktrace();
|
|
return 0;
|
|
}
|
|
if (maxwidth < 200 && show)
|
|
{
|
|
fprintf(stderr, "paintButtons: maxwidth very small\n");
|
|
fprintf(stderr, " x: %d y: %d footw: %d count: %d maxw: %d footh: %d\n ",
|
|
x, y, footerwidth, count, maxwidth, footerheight);
|
|
// print_stacktrace();
|
|
}
|
|
|
|
bool maximize = false;
|
|
for (int i = 0; i < cnt; i++)
|
|
maximize |= content[i].maximize;
|
|
|
|
for (int i = 0; i < cnt; i++)
|
|
{
|
|
//icon
|
|
int w = 0;
|
|
int h = 0;
|
|
frameBuffer->getIconSize(content[i].button, &w, &h);
|
|
iconw[i] = w;
|
|
iconh[i] = h;
|
|
h_max_icon = std::max(h_max_icon, h);
|
|
w_icons += w;
|
|
if (w)
|
|
count_icons++;
|
|
|
|
if (content[i].text) {
|
|
buttontext[i] = content[i].text;
|
|
fwidth[i] = std::max(content[i].width, font->getRenderWidth(buttontext[i]));
|
|
w_text += fwidth[i];
|
|
count_labels++;
|
|
} else if (content[i].locale) {
|
|
buttontext[i] = g_Locale->getText(content[i].locale);
|
|
fwidth[i] = std::max(content[i].width, font->getRenderWidth(buttontext[i]));
|
|
w_text += fwidth[i];
|
|
count_labels++;
|
|
} else {
|
|
buttontext[i] = "";
|
|
fwidth[i] = 0;
|
|
}
|
|
if (maximize && i < cnt - 1)
|
|
fwidth[i] += w, w_text += w;
|
|
}
|
|
|
|
//calculate button heigth
|
|
h_button = std::max(h_max_icon, h_max_text); //calculate optimal button height
|
|
|
|
//calculate footer heigth
|
|
h_footer = footerheight == 0 ? (h_button + 2*h_space) : footerheight;
|
|
|
|
if (!show) {
|
|
if (wantedheight)
|
|
*wantedheight = h_button + 2*h_space;
|
|
if (wantedwidth)
|
|
*wantedwidth = w_space * 2 + w_text + w_icons + (count_icons + count_labels - 1) * h_space;
|
|
return h_footer;
|
|
}
|
|
|
|
//paint footer
|
|
if (w_footer > 0)
|
|
frameBuffer->paintBoxRel(x_footer, y_footer, w_footer, h_footer, COL_SHADOW_PLUS_1, RADIUS_LARGE, CORNER_BOTTOM); //round
|
|
|
|
|
|
//baseline
|
|
int y_base = y_footer + h_footer/2;
|
|
int spacing = maxwidth - w_space * 2 - w_text - w_icons - (count_icons + count_labels - 1) * h_space;
|
|
#if 0
|
|
/* debug */
|
|
fprintf(stderr, "PB: sp %d mw %d w_t %d w_i %d w_s %d c_i %d\n",
|
|
spacing, maxwidth, w_text, w_icons, w_space, count_items);
|
|
#endif
|
|
if (fwidth[cnt - 1] == 0) /* divisor needs to be labels+1 unless rightmost icon has a label */
|
|
count_labels++; /* side effect: we don't try to divide by 0 :-) */
|
|
|
|
if (maximize) {
|
|
while (spacing > 0) {
|
|
for (int i = 0; i < cnt && spacing > 0; i++) {
|
|
if (content[i].maximize) {
|
|
fwidth[i]++;
|
|
spacing--;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (spacing >= 0)
|
|
{
|
|
int tmp = count_labels ? count_labels : 1;//avoid division by zero
|
|
/* add half of the inter-object space to the */
|
|
spacing /= tmp; /* left and right (this might break vertical */
|
|
x_button += spacing / 2; /* alignment, but nobody is using this (yet) */
|
|
} /* and I'm don't know how it should work. */
|
|
else
|
|
{
|
|
w_text = w_text ? w_text : 1;
|
|
/* shorten captions relative to their length */
|
|
for (int i = 0; i < cnt; i++)
|
|
fwidth[i] = (fwidth[i] * (w_text + spacing)) / w_text; /* spacing is negative...*/
|
|
spacing = 0;
|
|
}
|
|
|
|
for (int j = 0; j < cnt; j++)
|
|
{
|
|
const char * caption = NULL;
|
|
//set caption...
|
|
caption = buttontext[j];
|
|
|
|
const char * icon = content[j].button ? content[j].button : "";
|
|
|
|
// calculate baseline startposition of icon and text in y
|
|
int y_caption = y_base + h_max_text/2+1;
|
|
|
|
// paint icon and text
|
|
frameBuffer->paintIcon(icon, x_button , y_base - iconh[j]/2);
|
|
x_caption = x_button + iconw[j] + h_space;
|
|
font->RenderString(x_caption, y_caption, fwidth[j], caption, COL_MENUFOOT_TEXT);
|
|
|
|
/* set next startposition x, if text is length=0 then offset is =renderwidth of icon,
|
|
* for generating buttons without captions,
|
|
*/
|
|
|
|
/* increase x position */
|
|
x_button = x_caption;
|
|
if (fwidth[j])
|
|
x_button += fwidth[j] + spacing + h_space;
|
|
}
|
|
|
|
return h_footer;
|
|
}
|
|
|
|
/* paintButtons usage,
|
|
use this function for painting icons with captions in horizontal or vertical direction.
|
|
Icons automatically use the available maxwidth.
|
|
If not enough space is available, captions are shortened.
|
|
If there is extra space, space between icons is increased.
|
|
|
|
* x set horizontal startposition
|
|
* y set vertical startposition
|
|
* footerwidth set width of buttonbar as similar to footer, value 0 (default) means: do nothing,
|
|
then paint it extra
|
|
* count set count of buttons
|
|
* content set struct buttonlabel with iconfile and locales, for an empty text let locale
|
|
constant empty, so you can paint icons without captions,
|
|
* maxwidth maximum horizontal space for the buttons
|
|
* footerheight set height of buttonbar as similar to footer, value 0 (default) means:
|
|
value calculates automaticly depends of maximal height of icon and caption
|
|
|
|
* stuff below here was obviously not tested recently
|
|
* vertical_paint optional, default value is false (horizontal) sets direction of painted buttons
|
|
* fcolor optional, default value is COL_MENUFOOT_TEXT, use it to render font with other color
|
|
* alt_buttontext optional, default NULL, overwrites button caption at definied buttonlabel id (see parameter alt_buttontext_id) with this text
|
|
* alt_buttontext_id optional, default 0, means id from buttonlable struct which text you will change
|
|
* show optional, default value is true (show button), if false, then no show and return the height of the button.
|
|
*/
|
|
|
|
int paintButtons( const int &x,
|
|
const int &y,
|
|
const int &footerwidth,
|
|
const uint &count,
|
|
const struct button_label * const content,
|
|
const int &maxwidth,
|
|
const int &footerheight,
|
|
std::string /* just to make sure nobody uses anything below */,
|
|
bool vertical_paint,
|
|
const uint32_t fcolor,
|
|
const char * alt_buttontext,
|
|
const uint &buttontext_id,
|
|
bool show,
|
|
const std::vector<neutrino_locale_t>& /*all_buttontext_id*/)
|
|
{
|
|
CFrameBuffer *frameBuffer = CFrameBuffer::getInstance();
|
|
Font * font = g_Font[SNeutrinoSettings::FONT_TYPE_INFOBAR_SMALL];
|
|
uint cnt = count;
|
|
int x_footer = x;
|
|
int y_footer = y;
|
|
int w_footer = footerwidth;
|
|
int h_footer = 0;
|
|
|
|
int w_space = 10; //minimal space between buttons
|
|
int h_space = 4; //minimal space between caption and/or icon and border
|
|
int x_icon = x_footer + w_space;
|
|
int x_caption = 0;
|
|
|
|
int x_button = x_icon;
|
|
int h_button = 0;
|
|
|
|
//calculate max of h + w
|
|
//icon
|
|
int h_max_icon = 0;
|
|
int w_icons = 0;
|
|
|
|
//text
|
|
int w_text = 0;
|
|
int h_max_text = font->getHeight();
|
|
int count_icons = 0;
|
|
int count_labels = 0;
|
|
/* more than 16 buttons? noooooo*/
|
|
int iconw[16];
|
|
int iconh[16];
|
|
int fwidth[16];
|
|
const char *buttontext[16];
|
|
|
|
/* sanity check... */
|
|
if (count > 16 || count == 0)
|
|
{
|
|
fprintf(stderr, "paintButtons does only support max 16 buttons yet (%d)\n", count);
|
|
//print_stacktrace();
|
|
return 0;
|
|
}
|
|
if (maxwidth < 200 && show)
|
|
{
|
|
fprintf(stderr, "paintButtons: maxwidth very small\n");
|
|
fprintf(stderr, " x: %d y: %d footw: %d count: %d maxw: %d footh: %d\n ",
|
|
x, y, footerwidth, count, maxwidth, footerheight);
|
|
//print_stacktrace();
|
|
}
|
|
|
|
uint i;
|
|
for (i = 0; i < cnt; i++)
|
|
{
|
|
//icon
|
|
int w = 0;
|
|
int h = 0;
|
|
frameBuffer->getIconSize(content[i].button, &w, &h);
|
|
iconw[i] = w;
|
|
iconh[i] = h;
|
|
h_max_icon = std::max(h_max_icon, h);
|
|
w_icons += w;
|
|
if (w)
|
|
count_icons++;
|
|
|
|
if (content[i].locale) {
|
|
buttontext[i] = g_Locale->getText(content[i].locale);
|
|
//text width
|
|
if (alt_buttontext != NULL && i == buttontext_id)
|
|
fwidth[i] = font->getRenderWidth(alt_buttontext); //...with an alternate buttontext
|
|
else
|
|
fwidth[i] = font->getRenderWidth(buttontext[i]);
|
|
w_text += fwidth[i];
|
|
count_labels++;
|
|
} else {
|
|
buttontext[i] = "";
|
|
fwidth[i] = 0;
|
|
}
|
|
}
|
|
|
|
//calculate button heigth
|
|
h_button = std::max(h_max_icon, h_max_text); //calculate optimal button height
|
|
|
|
//calculate footer heigth
|
|
h_footer = footerheight == 0 ? (h_button + 2*h_space) : footerheight;
|
|
|
|
if (!show)
|
|
return h_footer;
|
|
|
|
//paint footer
|
|
if (w_footer > 0)
|
|
frameBuffer->paintBoxRel(x_footer, y_footer, w_footer, h_footer, COL_SHADOW_PLUS_1, RADIUS_LARGE, CORNER_BOTTOM); //round
|
|
|
|
|
|
//baseline
|
|
int y_base = y_footer + h_footer/2;
|
|
int spacing = maxwidth - w_space * 2 - w_text - w_icons - (count_icons + count_labels - 1) * h_space;
|
|
#if 0
|
|
/* debug */
|
|
fprintf(stderr, "PB: sp %d mw %d w_t %d w_i %d w_s %d c_i %d\n",
|
|
spacing, maxwidth, w_text, w_icons, w_space, count_items);
|
|
#endif
|
|
if (fwidth[cnt - 1] == 0) /* divisor needs to be labels+1 unless rightmost icon has a label */
|
|
count_labels++; /* side effect: we don't try to divide by 0 :-) */
|
|
if (spacing >= 0)
|
|
{ /* add half of the inter-object space to the */
|
|
spacing /= count_labels; /* left and right (this might break vertical */
|
|
x_button += spacing / 2; /* alignment, but nobody is using this (yet) */
|
|
} /* and I'm don't know how it should work. */
|
|
else
|
|
{
|
|
/* shorten captions relative to their length */
|
|
int tmp = w_text ? w_text : 1;//avoid division by zero
|
|
for (i = 0; i < cnt; i++)
|
|
fwidth[i] = (fwidth[i] * (w_text + spacing)) / tmp; /* spacing is negative...*/
|
|
spacing = 0;
|
|
}
|
|
|
|
for (uint j = 0; j < cnt; j++)
|
|
{
|
|
const char * caption = NULL;
|
|
//set caption...
|
|
if (alt_buttontext != NULL && j == buttontext_id)
|
|
caption = alt_buttontext; //...with an alternate buttontext
|
|
else
|
|
caption = buttontext[j];
|
|
|
|
const char * icon = content[j].button ? content[j].button : "";
|
|
|
|
// calculate baseline startposition of icon and text in y
|
|
int y_caption = y_base + h_max_text/2+1;
|
|
|
|
// paint icon and text
|
|
frameBuffer->paintIcon(icon, x_button , y_base - iconh[j]/2);
|
|
x_caption = x_button + iconw[j] + h_space;
|
|
font->RenderString(x_caption, y_caption, fwidth[j], caption, fcolor);
|
|
|
|
/* set next startposition x, if text is length=0 then offset is =renderwidth of icon,
|
|
* for generating buttons without captions,
|
|
*/
|
|
|
|
int lentext = strlen(caption);
|
|
if (vertical_paint)
|
|
// set x_icon for painting buttons with vertical arrangement
|
|
{
|
|
if (lentext !=0)
|
|
{
|
|
x_button = x;
|
|
y_base += h_footer;
|
|
}
|
|
else
|
|
{
|
|
x_button = x_caption;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* increase x position */
|
|
x_button = x_caption;
|
|
if (fwidth[j])
|
|
x_button += fwidth[j] + spacing + h_space;
|
|
}
|
|
}
|
|
|
|
return h_footer;
|
|
}
|