From c5f60b5b47863d32ff5eaa86f14227bcb4b8808a Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Sun, 8 Jul 2012 21:33:59 +0400 Subject: [PATCH] gui/widget/menue.cpp: add menu hints paint --- src/gui/widget/menue.cpp | 189 ++++++++++++++++++++++++++++++++------- src/gui/widget/menue.h | 11 ++- 2 files changed, 168 insertions(+), 32 deletions(-) diff --git a/src/gui/widget/menue.cpp b/src/gui/widget/menue.cpp index 53414aaf1..901a4aba9 100644 --- a/src/gui/widget/menue.cpp +++ b/src/gui/widget/menue.cpp @@ -1,27 +1,17 @@ /* - $port: menue.cpp,v 1.178 2010/12/08 19:49:30 tuxbox-cvs Exp $ - Neutrino-GUI - DBoxII-Project Copyright (C) 2001 Steffen Hehn 'McClean' Homepage: http://dbox.cyberphoria.org/ (C) 2008, 2009 Stefan Seyfried + Copyright (C) 2012 CoolStream International Ltd - Kommentar: - - Diese GUI wurde von Grund auf neu programmiert und sollte nun vom - Aufbau und auch den Ausbaumoeglichkeiten gut aussehen. Neutrino basiert - auf der Client-Server Idee, diese GUI ist also von der direkten DBox- - Steuerung getrennt. Diese wird dann von Daemons uebernommen. - - - License: GPL + License: GPLv2 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. + the Free Software Foundation This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -73,6 +63,7 @@ CMenuItem::CMenuItem() can_arrow = false; used = false; icon_frame_w = 10; + hint = NONEXISTANT_LOCALE; } void CMenuItem::init(const int X, const int Y, const int DX, const int OFFX) @@ -370,6 +361,9 @@ void CMenuWidget::Init(const std::string & Icon, const int mwidth, const mn_widg fade = true; savescreen = false; background = NULL; + has_hints = false; + hint_painted = false; + hint_height = 0; } void CMenuWidget::move(int xoff, int yoff) @@ -503,6 +497,7 @@ int CMenuWidget::exec(CMenuTarget* parent, const std::string &) } } } + GenericMenuBack->setHint(NEUTRINO_ICON_HINT_BACK, LOCALE_MENU_HINT_BACK); if(savescreen) { calcSize(); saveScreen(); @@ -599,6 +594,7 @@ int CMenuWidget::exec(CMenuTarget* parent, const std::string &) if ((pos < (int)page_start[current_page + 1]) && (pos >= (int)page_start[current_page])) { items[selected]->paint( false ); item->paint( true ); + paintHint(pos); selected = pos; } else { selected=pos; @@ -633,6 +629,7 @@ int CMenuWidget::exec(CMenuTarget* parent, const std::string &) items[selected]->paint( false ); //select new item->paint( true ); + paintHint(pos); selected = pos; } else { selected=pos; @@ -695,6 +692,11 @@ int CMenuWidget::exec(CMenuTarget* parent, const std::string &) retval = menu_return::RETURN_EXIT_ALL; } break; + case (CRCInput::RC_help): + hide(); + g_settings.show_menu_hints = !g_settings.show_menu_hints; + paint(); + break; default: if ( CNeutrinoApp::getInstance()->handleMsg( msg, data ) & messages_return::cancel_all ) { @@ -747,8 +749,10 @@ void CMenuWidget::hide() //frameBuffer->paintBackgroundBoxRel(x, y, width+15+SHADOW_OFFSET,height+10+SHADOW_OFFSET); if(savescreen && background) restoreScreen();//FIXME - else + else { frameBuffer->paintBackgroundBoxRel(x, y, full_width, full_height); + paintHint(-1); + } /* setActive() paints item for hidden parent menu, if called from child menu */ for (unsigned int count = 0; count < items.size(); count++) @@ -760,9 +764,6 @@ void CMenuWidget::calcSize() if (name != NONEXISTANT_LOCALE) nameString = g_Locale->getText(name); - /* set the max height to 9/10 of usable screen height - debatable, if the callers need a possibility to set this */ - height = frameBuffer->getScreenHeight() / 20 * 18; /* make sure its a multiple of 2 */ width = min_width; int wi, hi; @@ -778,7 +779,24 @@ void CMenuWidget::calcSize() int tmpw = items[i]->getWidth() + 10 + 10 + wi; /* 10 pixels to the left and right of the text */ if (tmpw > width) width = tmpw; + + if(g_settings.show_menu_hints && (!items[i]->hintIcon.empty() || items[i]->hint != NONEXISTANT_LOCALE)) { + has_hints = true; + } } + hint_height = 0; + if(g_settings.show_menu_hints && has_hints) { + int fheight = g_Font[SNeutrinoSettings::FONT_TYPE_MENU]->getHeight(); + hint_height = 10 + 2*fheight; + /* assuming all hint icons has the same size ! */ + int iw, ih; + frameBuffer->getIconSize(NEUTRINO_ICON_HINT_TVMODE, &iw, &ih); + if(hint_height < (ih+10)) + hint_height = ih+10; + } + /* set the max height to 9/10 of usable screen height + debatable, if the callers need a possibility to set this */ + height = (frameBuffer->getScreenHeight() - hint_height) / 20 * 18; /* make sure its a multiple of 2 */ if(height > ((int)frameBuffer->getScreenHeight() - 10)) height = frameBuffer->getScreenHeight() - 10; @@ -796,13 +814,14 @@ void CMenuWidget::calcSize() total_pages=1; for (unsigned int i= 0; i< items.size(); i++) { int item_height=items[i]->getHeight(); - itemHeightTotal+=item_height; heightCurrPage+=item_height; if(heightCurrPage > (height-hheight)) { page_start.push_back(i); total_pages++; heightCurrPage=item_height; } + if(total_pages == 1) + itemHeightTotal+=item_height; } page_start.push_back(items.size()); @@ -837,7 +856,7 @@ void CMenuWidget::calcSize() sb_width=15; full_width = width+sb_width+SHADOW_OFFSET; - full_height = height+RADIUS_LARGE-2+SHADOW_OFFSET; + full_height = height+RADIUS_LARGE-2+SHADOW_OFFSET+hint_height; setMenuPos(width - sb_width); } @@ -874,19 +893,17 @@ void CMenuWidget::paint() void CMenuWidget::setMenuPos(const int& menu_width) { - int mn_width = menu_width; - int scr_x = frameBuffer->getScreenX(); int scr_y = frameBuffer->getScreenY(); int scr_w = frameBuffer->getScreenWidth(); int scr_h = frameBuffer->getScreenHeight(); - + //configured positions switch(g_settings.menu_pos) { case MENU_POS_CENTER: - x = offx + scr_x + ((scr_w - mn_width ) >> 1 ); - y = offy + scr_y + ((scr_h - height) >> 1 ); + x = offx + scr_x + ((scr_w - menu_width ) >> 1 ); + y = offy + scr_y + ((scr_h - height - hint_height) >> 1 ); break; case MENU_POS_TOP_LEFT: @@ -896,17 +913,17 @@ void CMenuWidget::setMenuPos(const int& menu_width) case MENU_POS_TOP_RIGHT: y = offy + scr_y + 10; - x = offx + scr_x + scr_w - mn_width - 10; + x = offx + scr_x + scr_w - menu_width - 10; break; case MENU_POS_BOTTOM_LEFT: - y = offy + scr_y + scr_h - height - 10; + y = offy + scr_y + scr_h - height - hint_height - 10; x = offx + scr_x + 10; break; case MENU_POS_BOTTOM_RIGHT: - y = offy + scr_y + scr_h - height - 10; - x = offx + scr_x + scr_w - mn_width - 10; + y = offy + scr_y + scr_h - height - hint_height - 10; + x = offx + scr_x + scr_w - menu_width - 10; break; } } @@ -942,12 +959,15 @@ void CMenuWidget::paintItems() item->init(x, ypos, width, iconOffset); if( (item->isSelectable()) && (selected==-1) ) { + paintHint(count); ypos = item->paint(true); selected = count; } else { bool sel = selected==((signed int) count) ; + if(sel) + paintHint(count); ypos = item->paint(sel); } } @@ -1016,12 +1036,117 @@ void CMenuWidget::restoreScreen() void CMenuWidget::enableSaveScreen(bool enable) { savescreen = enable; - if(!enable && background) { + if (!enable && background) { delete[] background; background = NULL; } } +void CMenuWidget::paintHint(int pos) +{ +#define ConnectLineBox_Width 16 + if (!g_settings.show_menu_hints) + return; + + if (pos < 0 && !hint_painted) + return; + + fb_pixel_t col1 = COL_MENUCONTENT_PLUS_6; + fb_pixel_t col2 = COL_MENUCONTENT_PLUS_1; + int rad = RADIUS_LARGE; + + int xpos = x - ConnectLineBox_Width; + int ypos2 = y + height + rad + SHADOW_OFFSET; + int iwidth = width+sb_width+SHADOW_OFFSET; + + if (hint_painted) { + /* clear line box */ + frameBuffer->paintBackgroundBoxRel(xpos, y, ConnectLineBox_Width, height+hint_height+rad); + /* clear info box */ + frameBuffer->paintBackgroundBoxRel(x, ypos2, iwidth, hint_height); + + hint_painted = false; + } + if (pos < 0) + return; + + CMenuItem* item = items[pos]; +printf("paintHint: icon %s text %s\n", item->hintIcon.c_str(), g_Locale->getText(item->hint)); + + if (item->hintIcon.empty() && item->hint == NONEXISTANT_LOCALE) + return; + + hint_painted = true; + + int iheight = item->getHeight(); + + int ypos1 = item->getYPosition(); + int ypos1a = ypos1 + (iheight/2)-2; + int ypos2a = ypos2 + (hint_height/2)-2; + + int markh = hint_height > rad*2 ? hint_height - rad*2 : hint_height; + int imarkh = iheight/2; + int imarkoff = iheight/4; + + /* horizontal item mark - */ + frameBuffer->paintBoxRel(xpos+ConnectLineBox_Width-4, ypos1+imarkoff, 4, imarkh, col1); + frameBuffer->paintBoxRel(xpos+ConnectLineBox_Width-4, ypos1+imarkoff, 1, imarkh, col2); + + /* horizontal info mark - */ + frameBuffer->paintBoxRel(xpos+ConnectLineBox_Width-4, ypos2+rad, 4, markh, col1); + frameBuffer->paintBoxRel(xpos+ConnectLineBox_Width-4, ypos2+rad, 1 , markh, col2); + + /* vertical connect line [ */ + frameBuffer->paintBoxRel(xpos+ConnectLineBox_Width-16, ypos1a, 4, ypos2a-ypos1a, col1); + frameBuffer->paintBoxRel(xpos+ConnectLineBox_Width-16, ypos1a, 1, ypos2a-ypos1a+4, col2); + + /* vertical item line | */ + frameBuffer->paintBoxRel(xpos+ConnectLineBox_Width-16, ypos1a, 12, 4, col1); + frameBuffer->paintBoxRel(xpos+ConnectLineBox_Width-16, ypos1a, 12, 1, col2); + + /* vertical info line | */ + frameBuffer->paintBoxRel(xpos+ConnectLineBox_Width-16, ypos2a, 12, 4, col1); + frameBuffer->paintBoxRel(xpos+ConnectLineBox_Width-12, ypos2a, 8, 1, col2); +#if 0 + /* box shadow */ + frameBuffer->paintBoxRel(x+SHADOW_OFFSET, ypos2+SHADOW_OFFSET, width + sb_width, hint_height, COL_MENUCONTENTDARK_PLUS_0, rad); +#endif + /* box frame and fill */ + frameBuffer->paintBoxFrame(x, ypos2, iwidth, hint_height, 2, col1, rad); + /* box frame and fill */ + frameBuffer->paintBoxRel(x+2, ypos2+2, iwidth-4, hint_height-4, COL_MENUCONTENTDARK_PLUS_0, rad); + + int offset = 10; + if (!item->hintIcon.empty()) { + int iw, ih; + frameBuffer->getIconSize(item->hintIcon.c_str(), &iw, &ih); + if (iw && ih) { + int ix = x + offset; + int iy = ypos2 + (hint_height - ih)/2; + frameBuffer->paintIcon(item->hintIcon.c_str(), ix, iy); + offset += iw + 10; + } + } + if (item->hint == NONEXISTANT_LOCALE) + return; + + int fheight = g_Font[SNeutrinoSettings::FONT_TYPE_MENU]->getHeight(); + + std::string str1, str2; + std::string str = g_Locale->getText(item->hint); + std::string::size_type spos = str.find_first_of("\n"); + if (spos != std::string::npos) { + str1 = str.substr(0, spos); + str2 = str.substr(spos+1); + } else { + str1 = str; + } + if (!str1.empty()) + g_Font[SNeutrinoSettings::FONT_TYPE_MENU]->RenderString(x+offset, ypos2+5+fheight, iwidth-4-offset, str1, COL_MENUCONTENT, 0, true); // UTF-8 + if (!str2.empty()) + g_Font[SNeutrinoSettings::FONT_TYPE_MENU]->RenderString(x+offset, ypos2+5+fheight*2, iwidth-4-offset, str2, COL_MENUCONTENT, 0, true); // UTF-8 +} + //------------------------------------------------------------------------------------------------------------------------------- CMenuOptionNumberChooser::CMenuOptionNumberChooser(const neutrino_locale_t name, int * const OptionValue, const bool Active, const int min_value, const int max_value, CChangeObserver * const Observ, const int print_offset, const int special_value, const neutrino_locale_t special_value_name, const char * non_localized_name, bool sliderOn) { @@ -1201,7 +1326,9 @@ int CMenuOptionChooser::exec(CMenuTarget*) int select = -1; char cnt[5]; CMenuWidget* menu = new CMenuWidget(optionNameString.c_str(), NEUTRINO_ICON_SETTINGS); - menu->addIntroItems(); + /* FIXME: BACK button with hints enabled - parent menu getting holes, possible solution + * to hide parent, or add hints ? */ + menu->addIntroItems(NONEXISTANT_LOCALE, NONEXISTANT_LOCALE, CMenuWidget::BTN_TYPE_CANCEL); // menu->move(20, 0); CMenuSelectorTarget * selector = new CMenuSelectorTarget(&select); for(unsigned int count = 0; count < number_of_options; count++) @@ -1360,7 +1487,7 @@ int CMenuOptionStringChooser::exec(CMenuTarget* parent) parent->hide(); CMenuWidget* menu = new CMenuWidget(optionName, NEUTRINO_ICON_SETTINGS); - menu->addIntroItems(); + menu->addIntroItems(NONEXISTANT_LOCALE, NONEXISTANT_LOCALE, CMenuWidget::BTN_TYPE_CANCEL); //if(parent) menu->move(20, 0); CMenuSelectorTarget * selector = new CMenuSelectorTarget(&select); for(unsigned int count = 0; count < options.size(); count++) diff --git a/src/gui/widget/menue.h b/src/gui/widget/menue.h index 8a4fa70b6..3a353444d 100644 --- a/src/gui/widget/menue.h +++ b/src/gui/widget/menue.h @@ -96,6 +96,9 @@ class CMenuItem std::string iconName; std::string selected_iconName; std::string iconName_Info_right; + std::string hintIcon; + neutrino_locale_t hint; + CMenuItem(); virtual ~CMenuItem(){} @@ -112,6 +115,7 @@ class CMenuItem { return 0; } + virtual int getYPosition(void) const { return y; } virtual bool isSelectable(void) const { @@ -137,6 +141,7 @@ class CMenuItem virtual void paintItemSlider( const bool select_mode, const int &item_height, const int &optionvalue, const int &factor, const char * left_text=NULL, const char * right_text=NULL); virtual int isMenueOptionChooser(void) const{return 0;} + void setHint(std::string icon, neutrino_locale_t text) { hintIcon = icon; hint = text; } }; class CMenuSeparator : public CMenuItem @@ -420,7 +425,10 @@ class CMenuWidget : public CMenuTarget fb_pixel_t *background; int full_width, full_height; bool savescreen; - + int hint_height; + bool has_hints; // is any items has hints + bool hint_painted; // is hint painted + unsigned int item_start_y; unsigned int current_page; unsigned int total_pages; @@ -470,6 +478,7 @@ class CMenuWidget : public CMenuTarget void setWizardMode(bool _from_wizard) { from_wizard = _from_wizard;}; void enableFade(bool _enable) { fade = _enable; }; void enableSaveScreen(bool enable); + void paintHint(int num); enum { MENU_POS_CENTER ,