mirror of
https://github.com/tuxbox-neutrino/neutrino.git
synced 2025-08-28 16:01:20 +02:00
CComponentsFrmClock: add new class CComponentsFrmClock
This commit is contained in:
302
src/gui/components/cc_frm_clock.cpp
Normal file
302
src/gui/components/cc_frm_clock.cpp
Normal file
@@ -0,0 +1,302 @@
|
||||
/*
|
||||
Based up Neutrino-GUI - Tuxbox-Project
|
||||
Copyright (C) 2001 by Steffen Hehn 'McClean'
|
||||
|
||||
Generic GUI-related component.
|
||||
Copyright (C) 2013, Thilo Graf 'dbt'
|
||||
|
||||
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, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <global.h>
|
||||
#include <neutrino.h>
|
||||
|
||||
#include "cc_frm_clock.h"
|
||||
#include <time.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
CComponentsFrmClock::CComponentsFrmClock( const int x_pos, const int y_pos, const int w, const int h,
|
||||
const char* format_str, bool has_shadow,
|
||||
fb_pixel_t color_frame, fb_pixel_t color_body, fb_pixel_t color_shadow)
|
||||
|
||||
{
|
||||
initVarClock();
|
||||
|
||||
x = x_pos;
|
||||
y = y_pos;
|
||||
width = w;
|
||||
height = h;
|
||||
shadow = has_shadow;
|
||||
shadow_w = SHADOW_OFFSET;
|
||||
col_frame = color_frame;
|
||||
col_body = color_body;
|
||||
col_shadow = color_shadow;
|
||||
|
||||
cl_format_str = format_str;
|
||||
}
|
||||
|
||||
void CComponentsFrmClock::initVarClock()
|
||||
{
|
||||
initVarForm();
|
||||
cc_item_type = CC_ITEMTYPE_FRM_CLOCK;
|
||||
corner_rad = RADIUS_SMALL;
|
||||
|
||||
cl_font_type = SNeutrinoSettings::FONT_TYPE_INFOBAR_INFO;
|
||||
cl_font = NULL;
|
||||
cl_format_str = "%H:%M";
|
||||
cl_align = CC_ALIGN_VER_CENTER | CC_ALIGN_HOR_CENTER;
|
||||
// cl_force_segment_paint = false;
|
||||
|
||||
cl_thread = 0;
|
||||
cl_interval = 1;
|
||||
}
|
||||
|
||||
CComponentsFrmClock::~CComponentsFrmClock()
|
||||
{
|
||||
cleanCCForm();
|
||||
if(cl_thread)
|
||||
pthread_cancel(cl_thread);
|
||||
cl_thread = 0;
|
||||
}
|
||||
|
||||
void CComponentsFrmClock::initTimeString()
|
||||
{
|
||||
time_t tm = time(0);
|
||||
strftime((char*) &cl_timestr, sizeof(cl_timestr), cl_format_str, localtime(&tm));
|
||||
}
|
||||
|
||||
// How does it works?
|
||||
// We don't paint complete date or time string at once, because of individual possible formats,
|
||||
// so we split timestring and assign only one char to one lable (segment)
|
||||
|
||||
// x/y width
|
||||
// +--------------------------+
|
||||
// ||lbl0|lbl1|lbl2|lbl3|lbl4||
|
||||
// || | | | | ||height
|
||||
// || | | | | ||
|
||||
// +--------------------------+
|
||||
|
||||
// So every item (lable or segment) contains only one char depending on specified format. eg: format %H:%M gives 5 items.
|
||||
// The effort is slightly greater and it's necessary to avoid flicker effect, but it's more flexible.
|
||||
|
||||
void CComponentsFrmClock::initCCLockItems()
|
||||
{
|
||||
initTimeString();
|
||||
string s_time = cl_timestr;
|
||||
|
||||
cl_font = g_Font[cl_font_type];
|
||||
|
||||
//get minimal required height, width from raw text
|
||||
int min_text_w = cl_font->getRenderWidth(s_time, true);;
|
||||
int min_text_h = cl_font->getHeight();
|
||||
height = max(height, min_text_h);
|
||||
width = max(width, min_text_w);
|
||||
|
||||
int cl_x = 0;
|
||||
int cl_h = min_text_h;
|
||||
int cl_y = 0;
|
||||
int w_lbl_tmp = 0;
|
||||
|
||||
//create label objects and add to container, ensure count of items = count of chars (one char = one segment)
|
||||
if (v_cc_items.size() != s_time.size()){
|
||||
|
||||
//clean up possible old items before add new items
|
||||
clearCCItems();
|
||||
|
||||
//create new empty label objects, set some general properties and add to container
|
||||
for (size_t i = 0; i < s_time.size(); i++){
|
||||
CComponentsLabel * lbl = new CComponentsLabel();
|
||||
addCCItem(lbl);
|
||||
|
||||
//background paint of item is not required
|
||||
lbl->doPaintBg(false);
|
||||
|
||||
//set corner properties of label item
|
||||
lbl->setCornerRadius(corner_rad-fr_thickness);
|
||||
lbl->setCornerType(corner_type);
|
||||
}
|
||||
}
|
||||
|
||||
//modifie available lable items with current segment chars
|
||||
for (size_t i = 0; i < v_cc_items.size(); i++)
|
||||
{
|
||||
//v_cc_items are only available as CComponent-items here, so we must cast them before
|
||||
CComponentsLabel *lbl = static_cast <CComponentsLabel*> (v_cc_items[i]);
|
||||
|
||||
//add rounded corners only to 1st and last segment
|
||||
if (corner_type) {
|
||||
if (i == 0)
|
||||
lbl->setCornerType(corner_type & CORNER_LEFT);// 1st label item
|
||||
else if (i == v_cc_items.size()-1)
|
||||
lbl->setCornerType(corner_type & CORNER_RIGHT);// last label item
|
||||
else
|
||||
lbl->setCornerType(0);// inner items
|
||||
}
|
||||
|
||||
//extract timestring segment (char)
|
||||
string stmp = s_time.substr(i, 1);
|
||||
|
||||
//get width of current segment
|
||||
int wtmp = cl_font->getRenderWidth(stmp, true);
|
||||
|
||||
//set size, text, color of current item
|
||||
lbl->setDimensionsAll(cl_x, cl_y, wtmp, cl_h);
|
||||
lbl->setTextColor(COL_MENUCONTENT);
|
||||
lbl->setText(stmp, CTextBox::CENTER, cl_font);
|
||||
|
||||
//use matching height for digits for better vertical centerring into form
|
||||
CTextBox* ctb = lbl->getCTextBoxObject();
|
||||
if (ctb)
|
||||
ctb->setFontUseDigitHeight();
|
||||
|
||||
//ensure paint of text and label bg on changed text or painted form background
|
||||
bool force_txt_and_bg = (lbl->textChanged() || this->paint_bg);
|
||||
lbl->forceTextPaint(force_txt_and_bg);
|
||||
lbl->doPaintTextBoxBg(force_txt_and_bg);
|
||||
|
||||
//set xpos of item
|
||||
cl_x += wtmp;
|
||||
|
||||
lbl->setWidth(wtmp);
|
||||
|
||||
//set current width for form
|
||||
w_lbl_tmp += wtmp;
|
||||
}
|
||||
|
||||
//set required width
|
||||
width = max(width, w_lbl_tmp);
|
||||
|
||||
initSegmentAlign(&w_lbl_tmp, &min_text_h);
|
||||
}
|
||||
|
||||
//handle alignment
|
||||
void CComponentsFrmClock::initSegmentAlign(int* segment_width, int* segment_height)
|
||||
{
|
||||
int wadd = 0;
|
||||
int hadd = 0;
|
||||
int* w_lbl_tmp = segment_width;
|
||||
int* min_text_h = segment_height;
|
||||
|
||||
//use first item as reference and set x and y position to the 1st segement item with definied alignment
|
||||
if (cl_align & CC_ALIGN_RIGHT){
|
||||
wadd = width-*w_lbl_tmp;
|
||||
v_cc_items[0]->setXPos(wadd);
|
||||
}
|
||||
else if (cl_align & CC_ALIGN_LEFT){
|
||||
v_cc_items[0]->setXPos(wadd);
|
||||
}
|
||||
else if (cl_align & CC_ALIGN_HOR_CENTER){
|
||||
hadd = height/2-*min_text_h/2;
|
||||
v_cc_items[0]->setYPos(hadd);
|
||||
}
|
||||
|
||||
if (cl_align & CC_ALIGN_TOP){
|
||||
v_cc_items[0]->setYPos(hadd);
|
||||
}
|
||||
else if (cl_align & CC_ALIGN_BOTTOM){
|
||||
hadd = height-*min_text_h;
|
||||
v_cc_items[0]->setYPos(hadd);
|
||||
}
|
||||
else if (cl_align & CC_ALIGN_VER_CENTER){
|
||||
wadd = width/2-*w_lbl_tmp/2;
|
||||
v_cc_items[0]->setXPos(wadd);
|
||||
}
|
||||
|
||||
//set all evaluated position values to all other segement items
|
||||
for (size_t i = 1; i < v_cc_items.size(); i++){
|
||||
wadd += v_cc_items[i-1]->getWidth();
|
||||
v_cc_items[i]->setPos(wadd, hadd);
|
||||
}
|
||||
}
|
||||
|
||||
//thread handle
|
||||
void* CComponentsFrmClock::initClockThread(void *arg)
|
||||
{
|
||||
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,0);
|
||||
pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS,0);
|
||||
|
||||
CComponentsFrmClock *clock = static_cast<CComponentsFrmClock*>(arg);
|
||||
|
||||
//ensure paint of segements on first paint
|
||||
clock->paint();
|
||||
|
||||
//start loop for paint
|
||||
while(1) {
|
||||
sleep(clock->cl_interval);
|
||||
|
||||
//paint segements, but wihtout saved backgrounds
|
||||
clock->paint(CC_SAVE_SCREEN_NO);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//start up ticking clock with own thread, return true on succses
|
||||
bool CComponentsFrmClock::Start()
|
||||
{
|
||||
void *ptr = static_cast<void*>(this);
|
||||
|
||||
if(!cl_thread) {
|
||||
int res1 = pthread_create (&cl_thread, NULL, initClockThread, ptr) ;
|
||||
int res2 = pthread_detach(cl_thread);
|
||||
|
||||
if (res1 != 0){
|
||||
printf("[CComponentsFrmClock] [%s] pthread_create %s\n", __FUNCTION__, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
if (res2 != 0){
|
||||
printf("[CComponentsFrmClock] [%s] pthread_detach %s\n", __FUNCTION__, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//stop ticking clock and kill thread, return true on succses
|
||||
bool CComponentsFrmClock::Stop()
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
if(cl_thread)
|
||||
res = pthread_cancel(cl_thread);
|
||||
|
||||
if (res != 0){
|
||||
printf("[CComponentsFrmClock] [%s] pthread_cancel %s\n", __FUNCTION__, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
cl_thread = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void CComponentsFrmClock::paint(bool do_save_bg)
|
||||
{
|
||||
//prepare items before paint
|
||||
initCCLockItems();
|
||||
|
||||
//paint form contents
|
||||
paintForm(do_save_bg);
|
||||
}
|
Reference in New Issue
Block a user