/* Based up Neutrino-GUI - Tuxbox-Project Copyright (C) 2001 by Steffen Hehn 'McClean' Classes for generic GUI-related components. Copyright (C) 2012-2018, Thilo Graf 'dbt' Copyright (C) 2012, Michael Liebmann 'micha-bbg' License: GPL 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, see . */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include "cc_item.h" #include #include #include using namespace std; // y // x+------f-r-a-m-e-------+ // | | // height body | // | | // +--------width---------+ //abstract sub class CComponentsItem from CComponents CComponentsItem::CComponentsItem(CComponentsForm* parent) { cc_item_index = CC_NO_INDEX; cc_item_enabled = true; cc_item_selected = false; cc_page_number = 0; cc_has_focus = true; cc_parent = NULL; initParent(parent); } void CComponentsItem::initParent(CComponentsForm* parent) { if (cc_parent == parent) return; cc_parent = parent; if (cc_parent) cc_parent->addCCItem(this); } // init container properties in cc-items for shadow, background and frame. // This member must be called first in all paint() members before paint other items into the container. // If backround is not required, it's possible to override this with variable paint_bg=false, use doPaintBg(true/false) to set this! void CComponentsItem::paintInit(const bool &do_save_bg) { if (hasChanges()){ clearFbData(); is_painted = false; //force repaint if required } //calculate current needed frame thickeness and color, if item selected or not fb_pixel_t col_frame_cur = col_frame; int th = cc_enable_frame ? fr_thickness : 0; if (v_fbdata.empty()){ //set current position and dimensions int ix = x, iy = y, dx = width, dy = height; //and ensure sw is not larger than body dimensions, max x% int sw = (shadow) ? min(shadow_w, min(dx, dy)*50/100) : 0; /*ensure shadow is never < 0*/ sw = max(0, sw); //set current needed corner main box radius int box_rad = corner_type ? corner_rad : 0; //and ensure max main box radius < dimensions, avoids possible fb artefacts on screen int box_rad2 = box_rad/2; if(box_rad2 > dy || box_rad2 > dx){ int tmp_rad = box_rad; if (box_rad2 > dx) tmp_rad = (box_rad2-dx)*2; if (box_rad2 > dy) tmp_rad = (box_rad2-dy)*2; box_rad = tmp_rad; } //Workaround: ensure radius values >= 0, framebuffer methode paintBoxRel() gets confused box_rad = max(box_rad, 0); //if item is bound on a parent form,... if (cc_parent){ //...we must use real x/y values and from parent form as reference ix = cc_xr; iy = cc_yr; //...we must use color of parent body instead screen background col_shadow_clean = cc_parent->getColorBody(); } ///evaluate shadow layer parts //handle general shadow corner dimensions int sh_cdx = box_rad+sw+th; //width int sh_cdy = box_rad+sw+th; //height //adapt shadow corner dimensions if body dimensions are too small, use an offset if required int /*sh_cdx_size_offset = 0,*/ sh_cdy_size_offset = 0; if (sh_cdy*2 > dy) sh_cdy_size_offset = sh_cdy*2-dy; // if (sh_cdx*2 > dx) // sh_cdx_size_offset = sh_cdx*2-dx; //handle shadow positions //...corner bottom right int sh_cbr_x = ix+dx-sh_cdx+sw; int sh_cbr_y = iy+dy-sh_cdy+sw; //...corner top right int sh_ctr_x = sh_cbr_x; int sh_ctr_y = iy+sw; //...corner bottom left int sh_cbl_x = ix+sw; int sh_cbl_y = sh_cbr_y; //handle general shadow bar dimensions int sh_bdx = max(0, dx-sh_cdx-sh_cdx); /*ensure value is never < 0*/ int sh_rdy = dy-sh_cdy-sh_cdy; //...bar bottom int sh_bx = sh_cbl_x+sh_cdx; int sh_by = iy+dy; //...bar right int sh_rx = ix+dx; int sh_ry = sh_ctr_y+sh_cdy; //corners bool sh_ctr = (shadow & CC_SHADOW_CORNER_TOP_RIGHT); bool sh_cbr = (shadow & CC_SHADOW_CORNER_BOTTOM_RIGHT); bool sh_cbl = (shadow & CC_SHADOW_CORNER_BOTTOM_LEFT); //...shadow bar right bool sh_br = (shadow & CC_SHADOW_RIGHT); if (sh_rdy < 1) sh_br = false; //...shadow bar bottom bool sh_bb = (shadow & CC_SHADOW_BOTTOM); if (sh_bdx < 1) sh_bx = false; //init fb layers //buffered bg v_fbdata.push_back({true, CC_FBDATA_TYPE_BGSCREEN, ix, iy, dx+sw, dy+sw, 0, 0, 0, 0, NULL, NULL, NULL, false}); //shadow corner bottom left v_fbdata.push_back({sh_cbl, CC_FBDATA_TYPE_SHADOW_BOX, sh_cbl_x, sh_cbl_y, sh_cdx, sh_cdy, col_shadow, box_rad, corner_type & CORNER_BOTTOM_LEFT, 0, NULL, NULL, NULL, false}); //clean up inside body v_fbdata.push_back({sh_cbl, CC_FBDATA_TYPE_SHADOW_BOX, sh_cbl_x-sw+th, sh_cbl_y-sw, sh_cdx+sw, sh_cdy, col_shadow_clean, box_rad, corner_type & CORNER_BOTTOM_LEFT, 0, NULL, NULL, NULL, false}); //shadow bar bottom v_fbdata.push_back({sh_bb, CC_FBDATA_TYPE_SHADOW_BOX, sh_bx, sh_by, sh_bdx, sw, col_shadow, 0, CORNER_NONE, 0, NULL, NULL, NULL, false}); //shadow corner bottom right v_fbdata.push_back({sh_cbr, CC_FBDATA_TYPE_SHADOW_BOX, sh_cbr_x, sh_cbr_y, sh_cdx, sh_cdy, col_shadow, box_rad, corner_type & CORNER_BOTTOM_RIGHT, 0, NULL, NULL, NULL, false}); //clean up inside body v_fbdata.push_back({sh_cbr, CC_FBDATA_TYPE_SHADOW_BOX, sh_cbr_x-sw, sh_cbr_y-sw, sh_cdx, sh_cdy, col_shadow_clean, box_rad, corner_type & CORNER_BOTTOM_RIGHT, 0, NULL, NULL, NULL, false}); //shadow bar right v_fbdata.push_back({sh_br, CC_FBDATA_TYPE_SHADOW_BOX, sh_rx, sh_ry, sw, sh_rdy, col_shadow, 0, CORNER_NONE, 0, NULL, NULL, NULL, false}); //shadow corner top right v_fbdata.push_back({sh_ctr, CC_FBDATA_TYPE_SHADOW_BOX, sh_ctr_x, sh_ctr_y, sh_cdx, sh_cdy-sh_cdy_size_offset, col_shadow, box_rad, corner_type & CORNER_TOP_RIGHT, 0, NULL, NULL, NULL, false}); //clean up inside body v_fbdata.push_back({sh_ctr, CC_FBDATA_TYPE_SHADOW_BOX, sh_ctr_x-sw, sh_ctr_y-sw+th, sh_cdx, sh_cdy-sh_cdy_size_offset+sw, col_shadow_clean, box_rad, corner_type & CORNER_TOP_RIGHT, 0, NULL, NULL, NULL, false}); //main box v_fbdata.push_back({true, CC_FBDATA_TYPE_BOX, ix+th, iy+th, dx-2*th, dy-2*th, col_body, max(0,box_rad-th),corner_type, 0, NULL, NULL, NULL, false}); //frame if (fr_thickness) v_fbdata.push_back({true, CC_FBDATA_TYPE_FRAME, ix, iy, dx, dy, col_frame_cur, box_rad, corner_type, th, NULL, NULL, NULL, false}); } dprintf(DEBUG_DEBUG, "\033[1;32m[CComponentsItem]\t[%s - %d], init and paint item type = %d [%s]...\033[0m\n", __func__, __LINE__, cc_item_type.id, cc_item_type.name.c_str()); paintFbItems(do_save_bg); } //erase or paint over rendered objects void CComponentsItem::kill(const fb_pixel_t& bg_color, bool ignore_parent, const int& fblayer_type) { if(cc_parent == NULL){ CComponents::kill(bg_color, this->corner_rad, fblayer_type); }else{ if(ignore_parent) CComponents::kill(bg_color, this->corner_rad, fblayer_type); else CComponents::kill(cc_parent->getColorBody(), cc_parent->getCornerRadius(), fblayer_type); } } //synchronize colors for forms //This is usefull if the system colors are changed during runtime //so you can ensure correct applied system colors in relevant objects with unchanged instances. void CComponentsItem::syncSysColors() { col_body = COL_MENUCONTENT_PLUS_0; col_shadow = COL_SHADOW_PLUS_0; col_frame = COL_FRAME_PLUS_0; } //returns true if current item is added to a form bool CComponentsItem::isAdded() { if (cc_parent) return true; return false; } void CComponentsItem::setXPos(const int& xpos) { x = xpos; if (cc_parent) cc_xr = cc_parent->getRealXPos() + x; } void CComponentsItem::setYPos(const int& ypos) { y = ypos; if (cc_parent) cc_yr = cc_parent->getRealYPos() + y; } void CComponentsItem::setXPosP(const uint8_t& xpos_percent) { int x_tmp = cc_parent ? xpos_percent*cc_parent->getWidth() : xpos_percent*frameBuffer->getScreenWidth(); setXPos(x_tmp/100); } void CComponentsItem::setYPosP(const uint8_t& ypos_percent) { int y_tmp = cc_parent ? ypos_percent*cc_parent->getHeight() : ypos_percent*frameBuffer->getScreenHeight(); setYPos(y_tmp/100); } void CComponentsItem::setPosP(const uint8_t& xpos_percent, const uint8_t& ypos_percent) { setXPosP(xpos_percent); setYPosP(ypos_percent); } void CComponentsItem::setCenterPos(int along_mode) { if (along_mode & CC_ALONG_X) x = cc_parent ? cc_parent->getWidth() - width/2 : getScreenStartX(width); if (along_mode & CC_ALONG_Y) y = cc_parent ? cc_parent->getHeight() - height/2 : getScreenStartY(height); } void CComponentsItem::setHeightP(const uint8_t& h_percent) { height = cc_parent ? h_percent*cc_parent->getHeight()/100 : h_percent*frameBuffer->getScreenHeight(true)/100; } void CComponentsItem::setWidthP(const uint8_t& w_percent) { width = cc_parent ? w_percent*cc_parent->getWidth()/100 : w_percent*frameBuffer->getScreenWidth(true)/100; } void CComponentsItem::setFocus(bool focus) { if(cc_parent){ for(size_t i=0; isize(); i++){ if (focus) cc_parent->getCCItem(i)->setFocus(false); } } cc_has_focus = focus; } void CComponentsItem::setSelected(bool selected, const fb_pixel_t& sel_frame_col, const fb_pixel_t& frame_col, const fb_pixel_t& sel_body_col, const fb_pixel_t& body_col, const int& frame_w, const int& sel_frame_w) { cc_item_selected = selected; fr_thickness = cc_item_selected ? sel_frame_w : frame_w; col_body = cc_item_selected ? sel_body_col : body_col; col_frame = cc_item_selected ? sel_frame_col : frame_col; } uint8_t CComponentsItem::getPageNumber() { return cc_page_number; }