vdr-plugin-tvguide/timeline.c

277 lines
12 KiB
C
Raw Normal View History

2019-07-11 11:07:13 +02:00
#include "imageloader.h"
#include "timeline.h"
2019-07-11 14:34:31 +02:00
cTimeLine::cTimeLine(cTimeManager *timeManager) {
this->timeManager = timeManager;
2019-10-13 12:16:34 +02:00
lastClock = "";
timeBase = NULL;
2020-01-06 14:09:56 +01:00
int x11, x21, y11, y21, x12, x22, y12, y22;
2019-07-11 11:28:11 +02:00
if (config.displayMode == eVertical) {
2020-01-06 14:09:56 +01:00
x11 = 0;
x21 = geoManager.dateVieverWidth;
y11 = geoManager.statusHeaderHeight + geoManager.clockHeight;
y21 = geoManager.dateVieverHeight;
x12 = 0;
x22 = geoManager.timeLineWidth;
y12 = geoManager.statusHeaderHeight + geoManager.channelHeaderHeight + geoManager.channelGroupsHeight;
y22 = geoManager.osdHeight - geoManager.statusHeaderHeight - geoManager.channelHeaderHeight - geoManager.channelGroupsHeight - geoManager.footerHeight;
2019-07-11 11:28:11 +02:00
} else if (config.displayMode == eHorizontal) {
2020-01-06 14:09:56 +01:00
x11 = geoManager.clockWidth;
x21 = geoManager.dateVieverWidth;
y11 = geoManager.statusHeaderHeight;
y21 = geoManager.dateVieverHeight;
x12 = geoManager.channelHeaderWidth + geoManager.channelGroupsWidth;
x22 = geoManager.osdWidth - geoManager.channelHeaderWidth - geoManager.channelGroupsWidth;
y12 = geoManager.statusHeaderHeight;
y22 = geoManager.timeLineHeight;
2019-07-11 11:07:13 +02:00
}
2019-11-10 15:37:28 +01:00
dateViewer = new cStyledPixmap(osdManager.CreatePixmap(1, cRect(x11, y11, x21, y21)));
timeline = osdManager.CreatePixmap(2, cRect(x12, y12, x22, y22));
clock = new cStyledPixmap(osdManager.CreatePixmap(3, cRect(0,
2019-10-19 13:25:02 +02:00
geoManager.statusHeaderHeight,
2019-07-11 11:07:13 +02:00
geoManager.clockWidth,
geoManager.clockHeight)));
}
cTimeLine::~cTimeLine(void) {
if (clock)
delete clock;
2019-11-10 15:37:28 +01:00
osdManager.DestroyPixmap(timeBase);
osdManager.DestroyPixmap(timeline);
2020-01-06 14:09:56 +01:00
if (dateViewer)
delete dateViewer;
2019-07-11 11:07:13 +02:00
}
2020-01-06 14:09:56 +01:00
void cTimeLine::DrawDateViewer(void) {
2019-07-11 14:34:31 +02:00
cString weekDay = timeManager->GetWeekday();
cString date = timeManager->GetDate();
2019-07-11 11:28:11 +02:00
if (config.style != eStyleGraphical) {
2019-07-11 11:07:13 +02:00
dateViewer->setColor(theme.Color(clrHeader), theme.Color(clrHeaderBlending));
dateViewer->drawBackground();
dateViewer->drawBorder();
} else {
cImage *imgBack = imgCache.GetOsdElement(oeDateViewer);
if (imgBack)
dateViewer->DrawImage(cPoint(0,0), *imgBack);
else
dateViewer->Fill(clrTransparent);
}
tColor colorFont = theme.Color(clrButtonYellow);
2019-07-11 11:28:11 +02:00
tColor colorFontBack = (config.style == eStyleFlat) ? theme.Color(clrHeader) : clrTransparent;
2019-07-11 11:07:13 +02:00
2019-07-11 11:28:11 +02:00
if (config.displayMode == eVertical) {
2019-07-11 11:07:13 +02:00
int textHeightWeekday = fontManager.FontTimeLineWeekday->Height();
int textHeightDate = fontManager.FontTimeLineDate->Height();
int weekdayWidth = fontManager.FontTimeLineWeekday->Width(*weekDay);
int dateWidth = fontManager.FontTimeLineDate->Width(*date);
int y = ((geoManager.dateVieverHeight - textHeightWeekday - textHeightDate) / 2);
dateViewer->DrawText(cPoint((geoManager.timeLineWidth - weekdayWidth) / 2, y), *weekDay, colorFont, colorFontBack, fontManager.FontTimeLineWeekday);
dateViewer->DrawText(cPoint((geoManager.timeLineWidth - dateWidth) / 2, y + textHeightWeekday), *date, colorFont, colorFontBack, fontManager.FontTimeLineDate);
2019-07-11 11:28:11 +02:00
} else if (config.displayMode == eHorizontal) {
2019-07-11 11:07:13 +02:00
cString strDate = cString::sprintf("%s %s", *weekDay, *date);
int x = ((dateViewer->Width() - fontManager.FontTimeLineDateHorizontal->Width(*strDate)) / 2);
int y = ((dateViewer->Height() - fontManager.FontTimeLineDateHorizontal->Height()) / 2);
dateViewer->DrawText(cPoint(x, y), *strDate, colorFont, colorFontBack, fontManager.FontTimeLineDateHorizontal);
}
}
2020-01-06 14:09:56 +01:00
void cTimeLine::DrawTimeline(void) {
// timeline->SetTile(true);
2019-07-11 11:07:13 +02:00
timeline->Fill(clrTransparent);
tColor colorFont, colorBackground;
int imgWidth = geoManager.timeLineGridWidth;
int imgHeight = geoManager.timeLineGridHeight;
const cImage *img1 = NULL;
const cImage *img2 = NULL;
2019-07-11 11:28:11 +02:00
if (config.style == eStyleGraphical) {
2019-07-11 11:07:13 +02:00
img1 = imgCache.GetOsdElement(oeTimeline1);
img2 = imgCache.GetOsdElement(oeTimeline2);
} else {
2020-01-06 14:09:56 +01:00
img1 = CreateBackgroundImage(imgWidth, imgHeight, theme.Color(clrTimeline1), theme.Color(clrTimeline1Blending));
img2 = CreateBackgroundImage(imgWidth, imgHeight, theme.Color(clrTimeline2), theme.Color(clrTimeline2Blending));
2019-07-11 11:07:13 +02:00
}
const cImage *img = NULL;
if (!img1 || !img2)
return;
int textWidth, posX, posY;
char timetext[10];
2020-01-06 14:09:56 +01:00
int halfHours;
if (config.displayMode == eVertical)
halfHours = config.displayTime / 30 + 1;
else
halfHours = config.displayHorizontalTime / 30 + 1;
time_t tStart = timeManager->GetStart();
tm *t = localtime ( &tStart );
int x = 2 * t->tm_hour + ((t->tm_min == 0) ? 0 : 1);
for (int j = x; j < (x + halfHours); j++) {
int i = (j >= 48) ? (j - 48) : j;
if (i % 2 == 0) {
2019-07-11 11:07:13 +02:00
img = img1;
colorFont = theme.Color(clrTimeline2);
2019-07-11 11:28:11 +02:00
colorBackground = (config.style == eStyleFlat)?theme.Color(clrTimeline1):clrTransparent;
if (config.timeFormat == e12Hours) {
2019-07-11 11:07:13 +02:00
if (i == 0)
sprintf(timetext, "12:00 PM");
else if (i/2 < 13)
2020-01-06 14:09:56 +01:00
sprintf(timetext, "%d:00 AM", i / 2);
2019-07-11 11:07:13 +02:00
else
2020-01-06 14:09:56 +01:00
sprintf(timetext, "%d:00 PM", i / 2 - 12);
2019-07-11 11:07:13 +02:00
} else {
2020-01-06 14:09:56 +01:00
sprintf(timetext, "%d:00", i / 2);
2019-07-11 11:07:13 +02:00
}
} else {
img = img2;
colorFont = theme.Color(clrTimeline1);
2019-07-11 11:28:11 +02:00
colorBackground = (config.style == eStyleFlat)?theme.Color(clrTimeline2):clrTransparent;
if (config.timeFormat == e12Hours) {
2019-07-11 11:07:13 +02:00
if (i == 1)
sprintf(timetext, "12:30 PM");
else if (i/2 < 13)
2020-01-06 14:09:56 +01:00
sprintf(timetext, "%d:30 AM", i / 2);
2019-07-11 11:07:13 +02:00
else
2020-01-06 14:09:56 +01:00
sprintf(timetext, "%d:30 PM", i / 2 - 12);
2019-07-11 11:07:13 +02:00
} else {
2020-01-06 14:09:56 +01:00
sprintf(timetext, "%d:30", i / 2);
2019-07-11 11:07:13 +02:00
}
}
2019-07-11 11:28:11 +02:00
if (config.displayMode == eVertical) {
2020-01-06 14:09:56 +01:00
posY = (j - x) * geoManager.minutePixel * 30;
2019-07-11 11:07:13 +02:00
timeline->DrawImage(cPoint(0, posY), *img);
2019-07-11 11:28:11 +02:00
if (config.style != eStyleGraphical) {
2020-01-06 14:09:56 +01:00
DecorateTile(0, posY, imgWidth + 2, imgHeight);
2019-07-11 11:07:13 +02:00
}
textWidth = fontManager.FontTimeLineTime->Width(timetext);
2020-01-06 14:09:56 +01:00
timeline->DrawText(cPoint((geoManager.timeLineWidth-textWidth) / 2, posY + 5), timetext, colorFont, colorBackground, fontManager.FontTimeLineTime);
2019-07-11 11:28:11 +02:00
} else if (config.displayMode == eHorizontal) {
2020-01-06 14:09:56 +01:00
posX = (j - x) * geoManager.minutePixel * 30;
2019-07-11 11:07:13 +02:00
timeline->DrawImage(cPoint(posX, 0), *img);
2019-07-11 11:28:11 +02:00
if (config.style != eStyleGraphical) {
2020-01-06 14:09:56 +01:00
DecorateTile(posX, 0, imgWidth, imgHeight + 2);
2019-07-11 11:07:13 +02:00
}
2020-01-06 14:09:56 +01:00
timeline->DrawText(cPoint(posX + 15, (dateViewer->Height() - fontManager.FontTimeLineTimeHorizontal->Height()) / 2), timetext, colorFont, colorBackground, fontManager.FontTimeLineTimeHorizontal);
2019-07-11 11:07:13 +02:00
}
}
2020-01-06 14:09:56 +01:00
DrawTimeIndicator();
2019-07-11 11:28:11 +02:00
if (config.style != eStyleGraphical) {
2019-07-11 11:07:13 +02:00
delete img1;
delete img2;
}
}
2020-01-06 14:09:56 +01:00
void cTimeLine::DecorateTile(int posX, int posY, int tileWidth, int tileHeight) {
2019-07-11 11:07:13 +02:00
timeline->DrawRectangle(cRect(posX,posY,tileWidth,2), clrTransparent); //top
timeline->DrawRectangle(cRect(posX,posY,2,tileHeight), clrTransparent); //left
timeline->DrawRectangle(cRect(posX,posY + tileHeight-2,tileWidth,2), clrTransparent); //bottom
timeline->DrawRectangle(cRect(posX + tileWidth-2,posY,2,tileHeight), clrTransparent); //right
timeline->DrawRectangle(cRect(2+posX,posY+2,tileWidth-4,1), theme.Color(clrBorder)); //top
timeline->DrawRectangle(cRect(2+posX,posY+2,1,tileHeight-4), theme.Color(clrBorder)); //left
timeline->DrawRectangle(cRect(2+posX,posY+tileHeight-3,tileWidth-4,1), theme.Color(clrBorder)); //bottom
timeline->DrawRectangle(cRect(posX+tileWidth-3,posY+2,1,tileHeight-4), theme.Color(clrBorder)); //right
2019-07-11 11:28:11 +02:00
if (config.roundedCorners) {
2019-07-11 11:07:13 +02:00
int borderRadius = 12;
2020-01-06 14:09:56 +01:00
DrawRoundedCorners(posX, posY, tileWidth, tileHeight, borderRadius);
2019-07-11 11:07:13 +02:00
}
}
2020-01-06 14:09:56 +01:00
void cTimeLine::DrawRoundedCorners(int posX, int posY, int width, int height, int radius) {
2019-07-11 11:07:13 +02:00
timeline->DrawEllipse(cRect(posX+2,posY+2,radius,radius), theme.Color(clrBorder), -2);
timeline->DrawEllipse(cRect(posX+1,posY+1,radius,radius), clrTransparent, -2);
timeline->DrawEllipse(cRect(posX+width-radius - 2,posY+2,radius,radius), theme.Color(clrBorder), -1);
timeline->DrawEllipse(cRect(posX+width-radius - 1,posY+1,radius,radius), clrTransparent, -1);
if( height > 2*radius) {
timeline->DrawEllipse(cRect(posX+2,posY+height-radius - 2,radius,radius), theme.Color(clrBorder), -3);
timeline->DrawEllipse(cRect(posX+1,posY+height-radius - 1,radius,radius), clrTransparent, -3);
timeline->DrawEllipse(cRect(posX+width-radius - 2,posY+height-radius - 2,radius,radius), theme.Color(clrBorder), -4);
timeline->DrawEllipse(cRect(posX+width-radius - 1,posY+height-radius - 1,radius,radius), clrTransparent, -4);
}
}
2020-01-06 14:09:56 +01:00
void cTimeLine::DrawTimeIndicator(void) {
if (!config.displayTimeBase)
return;
if (!timeManager->NowVisible()) {
if (timeBase)
timeBase->Fill(clrTransparent);
return;
}
2020-01-06 14:09:56 +01:00
int deltaTime = (time(0) - timeManager->GetStart()) / 60 * geoManager.minutePixel;
2019-11-10 15:37:28 +01:00
osdManager.DestroyPixmap(timeBase);
int x1, x2, y1, y2;
2019-07-11 11:28:11 +02:00
if (config.displayMode == eVertical) {
x1 = 0;
y1 = geoManager.statusHeaderHeight + geoManager.channelGroupsHeight + geoManager.channelHeaderHeight + deltaTime - 2;
x2 = geoManager.osdWidth;
y2 = 4;
2019-07-11 11:07:13 +02:00
} else {
x1 = geoManager.channelGroupsWidth + geoManager.channelHeaderWidth + deltaTime - 2;
y1 = geoManager.statusHeaderHeight;
x2 = 4;
y2 = geoManager.timeLineHeight + config.channelRows * geoManager.rowHeight;
2019-07-11 11:07:13 +02:00
}
2019-11-10 15:37:28 +01:00
timeBase = osdManager.CreatePixmap(3, cRect(x1, y1, x2, y2));
timeBase->Fill(clrTransparent);
timeBase->DrawRectangle(cRect(0, 0, timeBase->ViewPort().Width(), timeBase->ViewPort().Height()), theme.Color(clrTimeBase));
2019-07-11 11:07:13 +02:00
}
2020-01-06 14:09:56 +01:00
cImage *cTimeLine::CreateBackgroundImage(int width, int height, tColor clrBgr, tColor clrBlend) {
2019-07-11 11:07:13 +02:00
cImage *image = NULL;
2019-07-11 11:28:11 +02:00
if (config.style == eStyleBlendingDefault) {
2019-07-11 11:07:13 +02:00
image = new cImage(cSize(width, height));
image->Fill(clrBgr);
int stepY = 0.5*height / 64;
int alpha = 0x00;
tColor clr;
for (int i = 0; i<64; i++) {
clr = AlphaBlend(clrBgr, clrBlend, alpha);
for (int y = i*stepY; y < (i+1)*stepY; y++) {
for (int x=0; x<width; x++) {
image->SetPixel(cPoint(x,y), clr);
}
}
alpha += 0x04;
}
2019-07-11 11:28:11 +02:00
} else if (config.style == eStyleBlendingMagick) {
2019-07-11 11:07:13 +02:00
cImageLoader imgLoader;
if (imgLoader.DrawBackground(clrBgr, clrBlend, width, height)) {
image = new cImage(imgLoader.GetImage());
}
} else {
image = new cImage(cSize(width, height));
image->Fill(clrBgr);
}
return image;
}
2020-01-06 14:09:56 +01:00
bool cTimeLine::DrawClock(void) {
2019-07-11 14:34:31 +02:00
cString currentTime = timeManager->GetCurrentTime();
2019-10-13 12:16:34 +02:00
if (strcmp(currentTime, lastClock)) {
2019-10-19 13:25:02 +02:00
clock->Fill(clrTransparent);
2019-10-13 12:16:34 +02:00
const cFont *font = (config.displayMode == eVertical) ? fontManager.FontTimeLineTime : fontManager.FontTimeLineTimeHorizontal;
int textHeight = font->Height();
int clockTextWidth = font->Width(*currentTime);
tColor colorFontBack = (config.style == eStyleFlat) ? theme.Color(clrHeader) : clrTransparent;
if (config.style == eStyleGraphical) {
clock->drawBackgroundGraphical(bgClock);
} else {
clock->setColor(theme.Color(clrHeader), theme.Color(clrHeaderBlending));
clock->drawBackground();
clock->drawBorder();
}
clock->DrawText(cPoint((geoManager.clockWidth - clockTextWidth) / 2, (geoManager.clockHeight - textHeight) / 2), *currentTime, theme.Color(clrFont), colorFontBack, font);
lastClock = currentTime;
2020-01-06 14:09:56 +01:00
DrawTimeIndicator();
2019-10-13 12:16:34 +02:00
return true;
2019-07-11 11:07:13 +02:00
}
2019-10-13 12:16:34 +02:00
return false;
2019-07-11 11:07:13 +02:00
}