CComponentsFrmClock: add new class CComponentsFrmClock

This commit is contained in:
2013-05-25 22:09:38 +02:00
parent 73cf6e9410
commit 9d52071c39
6 changed files with 449 additions and 0 deletions

View 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);
}