vdr  1.7.27
skinclassic.c
Go to the documentation of this file.
00001 /*
00002  * skinclassic.c: The 'classic' VDR skin
00003  *
00004  * See the main source file 'vdr.c' for copyright information and
00005  * how to reach the author.
00006  *
00007  * $Id: skinclassic.c 2.6 2011/08/21 11:02:06 kls Exp $
00008  */
00009 
00010 #include "skinclassic.h"
00011 #include "font.h"
00012 #include "i18n.h"
00013 #include "osd.h"
00014 #include "themes.h"
00015 
00016 #define ScrollWidth (Setup.FontOsdSize / 4)
00017 #define TextFrame   (Setup.FontOsdSize / 10)
00018 #define TextSpacing (Setup.FontOsdSize / 4)
00019 
00020 static cTheme Theme;
00021 
00022 THEME_CLR(Theme, clrBackground,             clrGray50);
00023 THEME_CLR(Theme, clrButtonRedFg,            clrWhite);
00024 THEME_CLR(Theme, clrButtonRedBg,            clrRed);
00025 THEME_CLR(Theme, clrButtonGreenFg,          clrBlack);
00026 THEME_CLR(Theme, clrButtonGreenBg,          clrGreen);
00027 THEME_CLR(Theme, clrButtonYellowFg,         clrBlack);
00028 THEME_CLR(Theme, clrButtonYellowBg,         clrYellow);
00029 THEME_CLR(Theme, clrButtonBlueFg,           clrWhite);
00030 THEME_CLR(Theme, clrButtonBlueBg,           clrBlue);
00031 THEME_CLR(Theme, clrMessageStatusFg,        clrBlack);
00032 THEME_CLR(Theme, clrMessageStatusBg,        clrCyan);
00033 THEME_CLR(Theme, clrMessageInfoFg,          clrBlack);
00034 THEME_CLR(Theme, clrMessageInfoBg,          clrGreen);
00035 THEME_CLR(Theme, clrMessageWarningFg,       clrBlack);
00036 THEME_CLR(Theme, clrMessageWarningBg,       clrYellow);
00037 THEME_CLR(Theme, clrMessageErrorFg,         clrWhite);
00038 THEME_CLR(Theme, clrMessageErrorBg,         clrRed);
00039 THEME_CLR(Theme, clrVolumePrompt,           clrGreen);
00040 THEME_CLR(Theme, clrVolumeBarUpper,         clrWhite);
00041 THEME_CLR(Theme, clrVolumeBarLower,         clrGreen);
00042 THEME_CLR(Theme, clrChannelName,            clrWhite);
00043 THEME_CLR(Theme, clrChannelDate,            clrWhite);
00044 THEME_CLR(Theme, clrChannelEpgTimeFg,       clrWhite);
00045 THEME_CLR(Theme, clrChannelEpgTimeBg,       clrRed);
00046 THEME_CLR(Theme, clrChannelEpgTitle,        clrCyan);
00047 THEME_CLR(Theme, clrChannelEpgShortText,    clrYellow);
00048 THEME_CLR(Theme, clrMenuTitleFg,            clrBlack);
00049 THEME_CLR(Theme, clrMenuTitleBg,            clrCyan);
00050 THEME_CLR(Theme, clrMenuDate,               clrBlack);
00051 THEME_CLR(Theme, clrMenuItemCurrentFg,      clrBlack);
00052 THEME_CLR(Theme, clrMenuItemCurrentBg,      clrCyan);
00053 THEME_CLR(Theme, clrMenuItemSelectable,     clrWhite);
00054 THEME_CLR(Theme, clrMenuItemNonSelectable,  clrCyan);
00055 THEME_CLR(Theme, clrMenuEventTime,          clrWhite);
00056 THEME_CLR(Theme, clrMenuEventVpsFg,         clrBlack);
00057 THEME_CLR(Theme, clrMenuEventVpsBg,         clrWhite);
00058 THEME_CLR(Theme, clrMenuEventTitle,         clrCyan);
00059 THEME_CLR(Theme, clrMenuEventShortText,     clrWhite);
00060 THEME_CLR(Theme, clrMenuEventDescription,   clrCyan);
00061 THEME_CLR(Theme, clrMenuScrollbarTotal,     clrWhite);
00062 THEME_CLR(Theme, clrMenuScrollbarShown,     clrCyan);
00063 THEME_CLR(Theme, clrMenuText,               clrWhite);
00064 THEME_CLR(Theme, clrReplayTitle,            clrWhite);
00065 THEME_CLR(Theme, clrReplayCurrent,          clrWhite);
00066 THEME_CLR(Theme, clrReplayTotal,            clrWhite);
00067 THEME_CLR(Theme, clrReplayModeJump,         clrWhite);
00068 THEME_CLR(Theme, clrReplayProgressSeen,     clrGreen);
00069 THEME_CLR(Theme, clrReplayProgressRest,     clrWhite);
00070 THEME_CLR(Theme, clrReplayProgressSelected, clrRed);
00071 THEME_CLR(Theme, clrReplayProgressMark,     clrBlack);
00072 THEME_CLR(Theme, clrReplayProgressCurrent,  clrRed);
00073 
00074 // --- cSkinClassicDisplayChannel --------------------------------------------
00075 
00076 class cSkinClassicDisplayChannel : public cSkinDisplayChannel {
00077 private:
00078   cOsd *osd;
00079   int lineHeight;
00080   int timeWidth;
00081   bool message;
00082   cString lastDate;
00083 public:
00084   cSkinClassicDisplayChannel(bool WithInfo);
00085   virtual ~cSkinClassicDisplayChannel();
00086   virtual void SetChannel(const cChannel *Channel, int Number);
00087   virtual void SetEvents(const cEvent *Present, const cEvent *Following);
00088   virtual void SetMessage(eMessageType Type, const char *Text);
00089   virtual void Flush(void);
00090   };
00091 
00092 cSkinClassicDisplayChannel::cSkinClassicDisplayChannel(bool WithInfo)
00093 {
00094   int Lines = WithInfo ? 5 : 1;
00095   const cFont *font = cFont::GetFont(fontOsd);
00096   lineHeight = font->Height();
00097   message = false;
00098   osd = cOsdProvider::NewOsd(cOsd::OsdLeft(), cOsd::OsdTop() + (Setup.ChannelInfoPos ? 0 : cOsd::OsdHeight() - Lines * lineHeight));
00099   timeWidth = font->Width("00:00") + 2 * TextFrame;
00100   tArea Areas[] = { { 0, 0, cOsd::OsdWidth() - 1, Lines * lineHeight - 1, 8 } };
00101   if (Setup.AntiAlias && osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
00102      osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
00103   else {
00104      tArea Areas[] = { { 0, 0, cOsd::OsdWidth() - 1, Lines * lineHeight - 1, 4 } };
00105      osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
00106      }
00107   osd->DrawRectangle(0, 0, osd->Width() - 1, osd->Height() - 1, Theme.Color(clrBackground));
00108 }
00109 
00110 cSkinClassicDisplayChannel::~cSkinClassicDisplayChannel()
00111 {
00112   delete osd;
00113 }
00114 
00115 void cSkinClassicDisplayChannel::SetChannel(const cChannel *Channel, int Number)
00116 {
00117   osd->DrawRectangle(0, 0, osd->Width() - 1, lineHeight - 1, Theme.Color(clrBackground));
00118   osd->DrawText(TextFrame, 0, ChannelString(Channel, Number), Theme.Color(clrChannelName), Theme.Color(clrBackground), cFont::GetFont(fontOsd));
00119   lastDate = NULL;
00120 }
00121 
00122 void cSkinClassicDisplayChannel::SetEvents(const cEvent *Present, const cEvent *Following)
00123 {
00124   osd->DrawRectangle(0, lineHeight, timeWidth - 1, osd->Height(), Theme.Color(clrChannelEpgTimeBg));
00125   osd->DrawRectangle(timeWidth, lineHeight, osd->Width() - 1, osd->Height(), Theme.Color(clrBackground));
00126   for (int i = 0; i < 2; i++) {
00127       const cEvent *e = !i ? Present : Following;
00128       if (e) {
00129          osd->DrawText(                  TextFrame, (2 * i + 1) * lineHeight, e->GetTimeString(), Theme.Color(clrChannelEpgTimeFg), Theme.Color(clrChannelEpgTimeBg), cFont::GetFont(fontOsd));
00130          osd->DrawText(timeWidth + 2 * TextSpacing, (2 * i + 1) * lineHeight, e->Title(), Theme.Color(clrChannelEpgTitle), Theme.Color(clrBackground), cFont::GetFont(fontOsd));
00131          osd->DrawText(timeWidth + 2 * TextSpacing, (2 * i + 2) * lineHeight, e->ShortText(), Theme.Color(clrChannelEpgShortText), Theme.Color(clrBackground), cFont::GetFont(fontSml));
00132          }
00133       }
00134 }
00135 
00136 void cSkinClassicDisplayChannel::SetMessage(eMessageType Type, const char *Text)
00137 {
00138   const cFont *font = cFont::GetFont(fontOsd);
00139   if (Text) {
00140      osd->SaveRegion(0, 0, osd->Width() - 1, lineHeight - 1);
00141      osd->DrawText(0, 0, Text, Theme.Color(clrMessageStatusFg + 2 * Type), Theme.Color(clrMessageStatusBg + 2 * Type), font, osd->Width(), 0, taCenter);
00142      message = true;
00143      }
00144   else {
00145      osd->RestoreRegion();
00146      message = false;
00147      }
00148 }
00149 
00150 void cSkinClassicDisplayChannel::Flush(void)
00151 {
00152   if (!message) {
00153      cString date = DayDateTime();
00154      if (!*lastDate || strcmp(date, lastDate)) {
00155         const cFont *font = cFont::GetFont(fontSml);
00156         int w = font->Width(date);
00157         osd->DrawText(osd->Width() - w - TextFrame, 0, date, Theme.Color(clrChannelDate), Theme.Color(clrBackground), cFont::GetFont(fontSml), w);
00158         lastDate = date;
00159         }
00160      }
00161   osd->Flush();
00162 }
00163 
00164 // --- cSkinClassicDisplayMenu -----------------------------------------------
00165 
00166 class cSkinClassicDisplayMenu : public cSkinDisplayMenu {
00167 private:
00168   cOsd *osd;
00169   int x0, x1, x2, x3;
00170   int y0, y1, y2, y3, y4, y5;
00171   int lineHeight;
00172   int dateWidth;
00173   cString lastDate;
00174   void DrawScrollbar(int Total, int Offset, int Shown, int Top, int Height, bool CanScrollUp, bool CanScrollDown);
00175   void SetTextScrollbar(void);
00176 public:
00177   cSkinClassicDisplayMenu(void);
00178   virtual ~cSkinClassicDisplayMenu();
00179   virtual void Scroll(bool Up, bool Page);
00180   virtual int MaxItems(void);
00181   virtual void Clear(void);
00182   virtual void SetTitle(const char *Title);
00183   virtual void SetButtons(const char *Red, const char *Green = NULL, const char *Yellow = NULL, const char *Blue = NULL);
00184   virtual void SetMessage(eMessageType Type, const char *Text);
00185   virtual void SetItem(const char *Text, int Index, bool Current, bool Selectable);
00186   virtual void SetScrollbar(int Total, int Offset);
00187   virtual void SetEvent(const cEvent *Event);
00188   virtual void SetRecording(const cRecording *Recording);
00189   virtual void SetText(const char *Text, bool FixedFont);
00190   virtual int GetTextAreaWidth(void) const;
00191   virtual const cFont *GetTextAreaFont(bool FixedFont) const;
00192   virtual void Flush(void);
00193   };
00194 
00195 cSkinClassicDisplayMenu::cSkinClassicDisplayMenu(void)
00196 {
00197   const cFont *font = cFont::GetFont(fontOsd);
00198   lineHeight = font->Height();
00199   dateWidth = 0;
00200   x0 = 0;
00201   x1 = x0 + 2 * TextSpacing;
00202   x3 = cOsd::OsdWidth();
00203   x2 = x3 - 2 * ScrollWidth;
00204   y0 = 0;
00205   y1 = lineHeight;
00206   y2 = y1 + lineHeight;
00207   y5 = cOsd::OsdHeight();
00208   y4 = y5 - lineHeight;
00209   y3 = y4 - lineHeight;
00210   osd = cOsdProvider::NewOsd(cOsd::OsdLeft(), cOsd::OsdTop());
00211   tArea Areas[] = { { x0, y0, x3 - 1, y5 - 1, 8 } };
00212   if (Setup.AntiAlias && osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
00213      osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
00214   else {
00215      tArea Areas[] = { { x0, y0, x3 - 1, y5 - 1, 4 } };
00216      if (osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
00217         osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
00218      else {
00219         tArea Areas[] = { { x0, y0, x3 - 1, y1 - 1, 2 },
00220                           { x0, y1, x3 - 1, y3 - 1, 2 },
00221                           { x0, y3, x3 - 1, y5 - 1, 4 }
00222                         };
00223         osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
00224         }
00225      }
00226   osd->DrawRectangle(x0, y0, x3 - 1, y5 - 1, Theme.Color(clrBackground));
00227 }
00228 
00229 cSkinClassicDisplayMenu::~cSkinClassicDisplayMenu()
00230 {
00231   delete osd;
00232 }
00233 
00234 void cSkinClassicDisplayMenu::DrawScrollbar(int Total, int Offset, int Shown, int Top, int Height, bool CanScrollUp, bool CanScrollDown)
00235 {
00236   if (Total > 0 && Total > Shown) {
00237      int yt = Top;
00238      int yb = yt + Height;
00239      int st = yt;
00240      int sb = yb;
00241      int th = max(int((sb - st) * double(Shown) / Total + 0.5), ScrollWidth);
00242      int tt = min(int(st + (sb - st) * double(Offset) / Total + 0.5), sb - th);
00243      int tb = min(tt + th, sb);
00244      int xl = x3 - ScrollWidth;
00245      osd->DrawRectangle(xl, st, x3 - 1, sb - 1, Theme.Color(clrMenuScrollbarTotal));
00246      osd->DrawRectangle(xl, tt, x3 - 1, tb - 1, Theme.Color(clrMenuScrollbarShown));
00247      }
00248 }
00249 
00250 void cSkinClassicDisplayMenu::SetTextScrollbar(void)
00251 {
00252   if (textScroller.CanScroll())
00253      DrawScrollbar(textScroller.Total(), textScroller.Offset(), textScroller.Shown(), textScroller.Top(), textScroller.Height(), textScroller.CanScrollUp(), textScroller.CanScrollDown());
00254 }
00255 
00256 void cSkinClassicDisplayMenu::Scroll(bool Up, bool Page)
00257 {
00258   cSkinDisplayMenu::Scroll(Up, Page);
00259   SetTextScrollbar();
00260 }
00261 
00262 int cSkinClassicDisplayMenu::MaxItems(void)
00263 {
00264   return (y3 - y2) / lineHeight;
00265 }
00266 
00267 void cSkinClassicDisplayMenu::Clear(void)
00268 {
00269   textScroller.Reset();
00270   osd->DrawRectangle(x0, y1, x3 - 1, y4 - 1, Theme.Color(clrBackground));
00271 }
00272 
00273 void cSkinClassicDisplayMenu::SetTitle(const char *Title)
00274 {
00275   const cFont *font = cFont::GetFont(fontOsd);
00276   osd->DrawText(x0, y0, Title, Theme.Color(clrMenuTitleFg), Theme.Color(clrMenuTitleBg), font, x3 - x0 - dateWidth);
00277 }
00278 
00279 void cSkinClassicDisplayMenu::SetButtons(const char *Red, const char *Green, const char *Yellow, const char *Blue)
00280 {
00281   const cFont *font = cFont::GetFont(fontOsd);
00282   int w = x3 - x0;
00283   int t0 = x0;
00284   int t1 = x0 + w / 4;
00285   int t2 = x0 + w / 2;
00286   int t3 = x3 - w / 4;
00287   int t4 = x3;
00288   osd->DrawText(t0, y4, Red,    Theme.Color(clrButtonRedFg),    Red    ? Theme.Color(clrButtonRedBg)    : Theme.Color(clrBackground), font, t1 - t0, 0, taCenter);
00289   osd->DrawText(t1, y4, Green,  Theme.Color(clrButtonGreenFg),  Green  ? Theme.Color(clrButtonGreenBg)  : Theme.Color(clrBackground), font, t2 - t1, 0, taCenter);
00290   osd->DrawText(t2, y4, Yellow, Theme.Color(clrButtonYellowFg), Yellow ? Theme.Color(clrButtonYellowBg) : Theme.Color(clrBackground), font, t3 - t2, 0, taCenter);
00291   osd->DrawText(t3, y4, Blue,   Theme.Color(clrButtonBlueFg),   Blue   ? Theme.Color(clrButtonBlueBg)   : Theme.Color(clrBackground), font, t4 - t3, 0, taCenter);
00292 }
00293 
00294 void cSkinClassicDisplayMenu::SetMessage(eMessageType Type, const char *Text)
00295 {
00296   const cFont *font = cFont::GetFont(fontOsd);
00297   if (Text)
00298      osd->DrawText(x0, y3, Text, Theme.Color(clrMessageStatusFg + 2 * Type), Theme.Color(clrMessageStatusBg + 2 * Type), font, x3 - x0, 0, taCenter);
00299   else
00300      osd->DrawRectangle(x0, y3, x3 - 1, y4 - 1, Theme.Color(clrBackground));
00301 }
00302 
00303 void cSkinClassicDisplayMenu::SetItem(const char *Text, int Index, bool Current, bool Selectable)
00304 {
00305   int y = y2 + Index * lineHeight;
00306   tColor ColorFg, ColorBg;
00307   if (Current) {
00308      ColorFg = Theme.Color(clrMenuItemCurrentFg);
00309      ColorBg = Theme.Color(clrMenuItemCurrentBg);
00310      }
00311   else {
00312      ColorFg = Theme.Color(Selectable ? clrMenuItemSelectable : clrMenuItemNonSelectable);
00313      ColorBg = Theme.Color(clrBackground);
00314      }
00315   const cFont *font = cFont::GetFont(fontOsd);
00316   for (int i = 0; i < MaxTabs; i++) {
00317       const char *s = GetTabbedText(Text, i);
00318       if (s) {
00319          int xt = x0 + Tab(i);
00320          osd->DrawText(xt, y, s, ColorFg, ColorBg, font, x2 - xt);
00321          }
00322       if (!Tab(i + 1))
00323          break;
00324       }
00325   SetEditableWidth(x2 - x0 - Tab(1));
00326 }
00327 
00328 void cSkinClassicDisplayMenu::SetScrollbar(int Total, int Offset)
00329 {
00330   DrawScrollbar(Total, Offset, MaxItems(), y2, MaxItems() * lineHeight, Offset > 0, Offset + MaxItems() < Total);
00331 }
00332 
00333 void cSkinClassicDisplayMenu::SetEvent(const cEvent *Event)
00334 {
00335   if (!Event)
00336      return;
00337   const cFont *font = cFont::GetFont(fontOsd);
00338   int y = y2;
00339   cTextScroller ts;
00340   char t[32];
00341   snprintf(t, sizeof(t), "%s  %s - %s", *Event->GetDateString(), *Event->GetTimeString(), *Event->GetEndTimeString());
00342   ts.Set(osd, x1, y, x2 - x1, y3 - y, t, font, Theme.Color(clrMenuEventTime), Theme.Color(clrBackground));
00343   if (Event->Vps() && Event->Vps() != Event->StartTime()) {
00344      cString buffer = cString::sprintf(" VPS: %s ", *Event->GetVpsString());
00345      const cFont *font = cFont::GetFont(fontSml);
00346      int w = font->Width(buffer);
00347      osd->DrawText(x3 - w, y, buffer, Theme.Color(clrMenuEventVpsFg), Theme.Color(clrMenuEventVpsBg), font, w);
00348      }
00349   y += ts.Height();
00350   if (Event->ParentalRating()) {
00351      cString buffer = cString::sprintf(" %s ", *Event->GetParentalRatingString());
00352      const cFont *font = cFont::GetFont(fontSml);
00353      int w = font->Width(buffer);
00354      osd->DrawText(x3 - w, y, buffer, Theme.Color(clrMenuEventVpsFg), Theme.Color(clrMenuEventVpsBg), font, w);
00355      }
00356   y += font->Height();
00357   ts.Set(osd, x1, y, x2 - x1, y3 - y, Event->Title(), font, Theme.Color(clrMenuEventTitle), Theme.Color(clrBackground));
00358   y += ts.Height();
00359   if (!isempty(Event->ShortText())) {
00360      const cFont *font = cFont::GetFont(fontSml);
00361      ts.Set(osd, x1, y, x2 - x1, y3 - y, Event->ShortText(), font, Theme.Color(clrMenuEventShortText), Theme.Color(clrBackground));
00362      y += ts.Height();
00363      }
00364   y += font->Height();
00365   if (!isempty(Event->Description())) {
00366      textScroller.Set(osd, x1, y, x2 - x1, y3 - y, Event->Description(), font, Theme.Color(clrMenuEventDescription), Theme.Color(clrBackground));
00367      SetTextScrollbar();
00368      }
00369 }
00370 
00371 void cSkinClassicDisplayMenu::SetRecording(const cRecording *Recording)
00372 {
00373   if (!Recording)
00374      return;
00375   const cRecordingInfo *Info = Recording->Info();
00376   const cFont *font = cFont::GetFont(fontOsd);
00377   int y = y2;
00378   cTextScroller ts;
00379   char t[32];
00380   snprintf(t, sizeof(t), "%s  %s", *DateString(Recording->Start()), *TimeString(Recording->Start()));
00381   ts.Set(osd, x1, y, x2 - x1, y3 - y, t, font, Theme.Color(clrMenuEventTime), Theme.Color(clrBackground));
00382   y += ts.Height();
00383   if (Info->GetEvent()->ParentalRating()) {
00384      cString buffer = cString::sprintf(" %s ", *Info->GetEvent()->GetParentalRatingString());
00385      const cFont *font = cFont::GetFont(fontSml);
00386      int w = font->Width(buffer);
00387      osd->DrawText(x3 - w, y, buffer, Theme.Color(clrMenuEventVpsFg), Theme.Color(clrMenuEventVpsBg), font, w);
00388      }
00389   y += font->Height();
00390   const char *Title = Info->Title();
00391   if (isempty(Title))
00392      Title = Recording->Name();
00393   ts.Set(osd, x1, y, x2 - x1, y3 - y, Title, font, Theme.Color(clrMenuEventTitle), Theme.Color(clrBackground));
00394   y += ts.Height();
00395   if (!isempty(Info->ShortText())) {
00396      const cFont *font = cFont::GetFont(fontSml);
00397      ts.Set(osd, x1, y, x2 - x1, y3 - y, Info->ShortText(), font, Theme.Color(clrMenuEventShortText), Theme.Color(clrBackground));
00398      y += ts.Height();
00399      }
00400   y += font->Height();
00401   if (!isempty(Info->Description())) {
00402      textScroller.Set(osd, x1, y, x2 - x1, y3 - y, Info->Description(), font, Theme.Color(clrMenuEventDescription), Theme.Color(clrBackground));
00403      SetTextScrollbar();
00404      }
00405 }
00406 
00407 void cSkinClassicDisplayMenu::SetText(const char *Text, bool FixedFont)
00408 {
00409   textScroller.Set(osd, x1, y2, GetTextAreaWidth(), y3 - y2, Text, GetTextAreaFont(FixedFont), Theme.Color(clrMenuText), Theme.Color(clrBackground));
00410   SetTextScrollbar();
00411 }
00412 
00413 int cSkinClassicDisplayMenu::GetTextAreaWidth(void) const
00414 {
00415 return x2 - x1;
00416 }
00417 
00418 const cFont *cSkinClassicDisplayMenu::GetTextAreaFont(bool FixedFont) const
00419 {
00420   return cFont::GetFont(FixedFont ? fontFix : fontOsd);
00421 }
00422 
00423 void cSkinClassicDisplayMenu::Flush(void)
00424 {
00425   cString date = DayDateTime();
00426   if (!*lastDate || strcmp(date, lastDate)) {
00427      const cFont *font = cFont::GetFont(fontOsd);
00428      int w = font->Width(date);
00429      osd->DrawText(x3 - w - TextFrame, y0, date, Theme.Color(clrMenuDate), Theme.Color(clrMenuTitleBg), font, w);
00430      lastDate = date;
00431      dateWidth = max(w + TextFrame, dateWidth);
00432      }
00433   osd->Flush();
00434 }
00435 
00436 // --- cSkinClassicDisplayReplay ---------------------------------------------
00437 
00438 class cSkinClassicDisplayReplay : public cSkinDisplayReplay {
00439 private:
00440   cOsd *osd;
00441   int x0, x1;
00442   int y0, y1, y2, y3;
00443   int lastCurrentWidth;
00444 public:
00445   cSkinClassicDisplayReplay(bool ModeOnly);
00446   virtual ~cSkinClassicDisplayReplay();
00447   virtual void SetTitle(const char *Title);
00448   virtual void SetMode(bool Play, bool Forward, int Speed);
00449   virtual void SetProgress(int Current, int Total);
00450   virtual void SetCurrent(const char *Current);
00451   virtual void SetTotal(const char *Total);
00452   virtual void SetJump(const char *Jump);
00453   virtual void SetMessage(eMessageType Type, const char *Text);
00454   virtual void Flush(void);
00455   };
00456 
00457 cSkinClassicDisplayReplay::cSkinClassicDisplayReplay(bool ModeOnly)
00458 {
00459   const cFont *font = cFont::GetFont(fontOsd);
00460   int lineHeight = font->Height();
00461   lastCurrentWidth = 0;
00462   x0 = 0;
00463   x1 = cOsd::OsdWidth();
00464   y0 = 0;
00465   y1 = lineHeight;
00466   y2 = 2 * lineHeight;
00467   y3 = 3 * lineHeight;
00468   osd = cOsdProvider::NewOsd(cOsd::OsdLeft(), cOsd::OsdTop() + cOsd::OsdHeight() - y3);
00469   tArea Areas[] = { { x0, y0, x1 - 1, y3 - 1, 8 } };
00470   if (Setup.AntiAlias && osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
00471      osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
00472   else {
00473      tArea Areas[] = { { x0, y0, x1 - 1, y3 - 1, 4 } };
00474      osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
00475      }
00476   osd->DrawRectangle(x0, y0, x1 - 1, y3 - 1, ModeOnly ? clrTransparent : Theme.Color(clrBackground));
00477 }
00478 
00479 cSkinClassicDisplayReplay::~cSkinClassicDisplayReplay()
00480 {
00481   delete osd;
00482 }
00483 
00484 void cSkinClassicDisplayReplay::SetTitle(const char *Title)
00485 {
00486   osd->DrawText(x0, y0, Title, Theme.Color(clrReplayTitle), Theme.Color(clrBackground), cFont::GetFont(fontOsd), x1 - x0);
00487 }
00488 
00489 void cSkinClassicDisplayReplay::SetMode(bool Play, bool Forward, int Speed)
00490 {
00491   if (Setup.ShowReplayMode) {
00492      const char *Mode;
00493      if (Speed == -1) Mode = Play    ? "  >  " : " ||  ";
00494      else if (Play)   Mode = Forward ? " X>> " : " <<X ";
00495      else             Mode = Forward ? " X|> " : " <|X ";
00496      char buf[16];
00497      strn0cpy(buf, Mode, sizeof(buf));
00498      char *p = strchr(buf, 'X');
00499      if (p)
00500         *p = Speed > 0 ? '1' + Speed - 1 : ' ';
00501      SetJump(buf);
00502      }
00503 }
00504 
00505 void cSkinClassicDisplayReplay::SetProgress(int Current, int Total)
00506 {
00507   cProgressBar pb(x1 - x0, y2 - y1, Current, Total, marks, Theme.Color(clrReplayProgressSeen), Theme.Color(clrReplayProgressRest), Theme.Color(clrReplayProgressSelected), Theme.Color(clrReplayProgressMark), Theme.Color(clrReplayProgressCurrent));
00508   osd->DrawBitmap(x0, y1, pb);
00509 }
00510 
00511 void cSkinClassicDisplayReplay::SetCurrent(const char *Current)
00512 {
00513   const cFont *font = cFont::GetFont(fontOsd);
00514   int w = font->Width(Current);
00515   osd->DrawText(x0, y2, Current, Theme.Color(clrReplayCurrent), Theme.Color(clrBackground), font, lastCurrentWidth > w ? lastCurrentWidth : w);
00516   lastCurrentWidth = w;
00517 }
00518 
00519 void cSkinClassicDisplayReplay::SetTotal(const char *Total)
00520 {
00521   const cFont *font = cFont::GetFont(fontOsd);
00522   int w = font->Width(Total);
00523   osd->DrawText(x1 - font->Width(Total), y2, Total, Theme.Color(clrReplayTotal), Theme.Color(clrBackground), font, w);
00524 }
00525 
00526 void cSkinClassicDisplayReplay::SetJump(const char *Jump)
00527 {
00528   osd->DrawText(x0 + (x1 - x0) / 4, y2, Jump, Theme.Color(clrReplayModeJump), Theme.Color(clrBackground), cFont::GetFont(fontOsd), (x1 - x0) / 2, 0, taCenter);
00529 }
00530 
00531 void cSkinClassicDisplayReplay::SetMessage(eMessageType Type, const char *Text)
00532 {
00533   const cFont *font = cFont::GetFont(fontOsd);
00534   if (Text) {
00535      osd->SaveRegion(x0, y2, x1 - 1, y3 - 1);
00536      osd->DrawText(x0, y2, Text, Theme.Color(clrMessageStatusFg + 2 * Type), Theme.Color(clrMessageStatusBg + 2 * Type), font, x1 - x0, y3 - y2, taCenter);
00537      }
00538   else
00539      osd->RestoreRegion();
00540 }
00541 
00542 void cSkinClassicDisplayReplay::Flush(void)
00543 {
00544   osd->Flush();
00545 }
00546 
00547 // --- cSkinClassicDisplayVolume ---------------------------------------------
00548 
00549 class cSkinClassicDisplayVolume : public cSkinDisplayVolume {
00550 private:
00551   cOsd *osd;
00552 public:
00553   cSkinClassicDisplayVolume(void);
00554   virtual ~cSkinClassicDisplayVolume();
00555   virtual void SetVolume(int Current, int Total, bool Mute);
00556   virtual void Flush(void);
00557   };
00558 
00559 cSkinClassicDisplayVolume::cSkinClassicDisplayVolume(void)
00560 {
00561   const cFont *font = cFont::GetFont(fontOsd);
00562   int lineHeight = font->Height();
00563   osd = cOsdProvider::NewOsd(cOsd::OsdLeft(), cOsd::OsdTop() + cOsd::OsdHeight() - lineHeight);
00564   tArea Areas[] = { { 0, 0, cOsd::OsdWidth() - 1, lineHeight - 1, 8 } };
00565   if (Setup.AntiAlias && osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
00566      osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
00567   else {
00568      tArea Areas[] = { { 0, 0, cOsd::OsdWidth() - 1, lineHeight - 1, 4 } };
00569      osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
00570      }
00571 }
00572 
00573 cSkinClassicDisplayVolume::~cSkinClassicDisplayVolume()
00574 {
00575   delete osd;
00576 }
00577 
00578 void cSkinClassicDisplayVolume::SetVolume(int Current, int Total, bool Mute)
00579 {
00580   const cFont *font = cFont::GetFont(fontOsd);
00581   if (Mute) {
00582      osd->DrawRectangle(0, 0, osd->Width() - 1, osd->Height() - 1, clrTransparent);
00583      osd->DrawText(0, 0, tr("Key$Mute"), Theme.Color(clrVolumePrompt), Theme.Color(clrBackground), font);
00584      }
00585   else {
00586      // TRANSLATORS: note the trailing blank!
00587      const char *Prompt = tr("Volume ");
00588      int l = font->Width(Prompt);
00589      int p = (osd->Width() - l) * Current / Total;
00590      osd->DrawText(0, 0, Prompt, Theme.Color(clrVolumePrompt), Theme.Color(clrBackground), font);
00591      osd->DrawRectangle(l, 0, l + p - 1, osd->Height() - 1, Theme.Color(clrVolumeBarLower));
00592      osd->DrawRectangle(l + p, 0, osd->Width() - 1, osd->Height() - 1, Theme.Color(clrVolumeBarUpper));
00593      }
00594 }
00595 
00596 void cSkinClassicDisplayVolume::Flush(void)
00597 {
00598   osd->Flush();
00599 }
00600 
00601 // --- cSkinClassicDisplayTracks ---------------------------------------------
00602 
00603 class cSkinClassicDisplayTracks : public cSkinDisplayTracks {
00604 private:
00605   cOsd *osd;
00606   int x0, x1;
00607   int y0, y1, y2;
00608   int lineHeight;
00609   int currentIndex;
00610   void SetItem(const char *Text, int Index, bool Current);
00611 public:
00612   cSkinClassicDisplayTracks(const char *Title, int NumTracks, const char * const *Tracks);
00613   virtual ~cSkinClassicDisplayTracks();
00614   virtual void SetTrack(int Index, const char * const *Tracks);
00615   virtual void SetAudioChannel(int AudioChannel) {}
00616   virtual void Flush(void);
00617   };
00618 
00619 cSkinClassicDisplayTracks::cSkinClassicDisplayTracks(const char *Title, int NumTracks, const char * const *Tracks)
00620 {
00621   const cFont *font = cFont::GetFont(fontOsd);
00622   lineHeight = font->Height();
00623   currentIndex = -1;
00624   int ItemsWidth = font->Width(Title);
00625   for (int i = 0; i < NumTracks; i++)
00626       ItemsWidth = max(ItemsWidth, font->Width(Tracks[i]));
00627   ItemsWidth += 2 * TextSpacing;
00628   x0 = 0;
00629   x1 = cOsd::OsdWidth();
00630   int d = x1 - x0;
00631   if (d > ItemsWidth) {
00632      d = (d - ItemsWidth) & ~0x07; // must be multiple of 8
00633      x1 -= d;
00634      }
00635   y0 = 0;
00636   y1 = lineHeight;
00637   y2 = y1 + NumTracks * lineHeight;
00638   osd = cOsdProvider::NewOsd(cOsd::OsdLeft(), cOsd::OsdTop() + cOsd::OsdHeight() - y2);
00639   tArea Areas[] = { { x0, y0, x1 - 1, y2 - 1, 8 } };
00640   if (Setup.AntiAlias && osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
00641      osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
00642   else {
00643      tArea Areas[] = { { x0, y0, x1 - 1, y2 - 1, 4 } };
00644      osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
00645      }
00646   osd->DrawText(x0, y0, Title, Theme.Color(clrMenuTitleFg), Theme.Color(clrMenuTitleBg), font, x1 - x0);
00647   for (int i = 0; i < NumTracks; i++)
00648       SetItem(Tracks[i], i, false);
00649 }
00650 
00651 cSkinClassicDisplayTracks::~cSkinClassicDisplayTracks()
00652 {
00653   delete osd;
00654 }
00655 
00656 void cSkinClassicDisplayTracks::SetItem(const char *Text, int Index, bool Current)
00657 {
00658   int y = y1 + Index * lineHeight;
00659   tColor ColorFg, ColorBg;
00660   if (Current) {
00661      ColorFg = Theme.Color(clrMenuItemCurrentFg);
00662      ColorBg = Theme.Color(clrMenuItemCurrentBg);
00663      currentIndex = Index;
00664      }
00665   else {
00666      ColorFg = Theme.Color(clrMenuItemSelectable);
00667      ColorBg = Theme.Color(clrBackground);
00668      }
00669   const cFont *font = cFont::GetFont(fontOsd);
00670   osd->DrawText(x0, y, Text, ColorFg, ColorBg, font, x1 - x0);
00671 }
00672 
00673 void cSkinClassicDisplayTracks::SetTrack(int Index, const char * const *Tracks)
00674 {
00675   if (currentIndex >= 0)
00676      SetItem(Tracks[currentIndex], currentIndex, false);
00677   SetItem(Tracks[Index], Index, true);
00678 }
00679 
00680 void cSkinClassicDisplayTracks::Flush(void)
00681 {
00682   osd->Flush();
00683 }
00684 
00685 // --- cSkinClassicDisplayMessage --------------------------------------------
00686 
00687 class cSkinClassicDisplayMessage : public cSkinDisplayMessage {
00688 private:
00689   cOsd *osd;
00690 public:
00691   cSkinClassicDisplayMessage(void);
00692   virtual ~cSkinClassicDisplayMessage();
00693   virtual void SetMessage(eMessageType Type, const char *Text);
00694   virtual void Flush(void);
00695   };
00696 
00697 cSkinClassicDisplayMessage::cSkinClassicDisplayMessage(void)
00698 {
00699   const cFont *font = cFont::GetFont(fontOsd);
00700   int lineHeight = font->Height();
00701   osd = cOsdProvider::NewOsd(cOsd::OsdLeft(), cOsd::OsdTop() + cOsd::OsdHeight() - lineHeight);
00702   tArea Areas[] = { { 0, 0, cOsd::OsdWidth() - 1, lineHeight - 1, 8 } };
00703   if (Setup.AntiAlias && osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
00704      osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
00705   else {
00706      tArea Areas[] = { { 0, 0, cOsd::OsdWidth() - 1, lineHeight - 1, 2 } };
00707      osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
00708      }
00709 }
00710 
00711 cSkinClassicDisplayMessage::~cSkinClassicDisplayMessage()
00712 {
00713   delete osd;
00714 }
00715 
00716 void cSkinClassicDisplayMessage::SetMessage(eMessageType Type, const char *Text)
00717 {
00718   const cFont *font = cFont::GetFont(fontOsd);
00719   osd->DrawText(0, 0, Text, Theme.Color(clrMessageStatusFg + 2 * Type), Theme.Color(clrMessageStatusBg + 2 * Type), font, cOsd::OsdWidth(), 0, taCenter);
00720 }
00721 
00722 void cSkinClassicDisplayMessage::Flush(void)
00723 {
00724   osd->Flush();
00725 }
00726 
00727 // --- cSkinClassic ----------------------------------------------------------
00728 
00729 cSkinClassic::cSkinClassic(void)
00730 :cSkin("classic", &::Theme)//XXX naming problem???
00731 {
00732 }
00733 
00734 const char *cSkinClassic::Description(void)
00735 {
00736   return tr("Classic VDR");
00737 }
00738 
00739 cSkinDisplayChannel *cSkinClassic::DisplayChannel(bool WithInfo)
00740 {
00741   return new cSkinClassicDisplayChannel(WithInfo);
00742 }
00743 
00744 cSkinDisplayMenu *cSkinClassic::DisplayMenu(void)
00745 {
00746   return new cSkinClassicDisplayMenu;
00747 }
00748 
00749 cSkinDisplayReplay *cSkinClassic::DisplayReplay(bool ModeOnly)
00750 {
00751   return new cSkinClassicDisplayReplay(ModeOnly);
00752 }
00753 
00754 cSkinDisplayVolume *cSkinClassic::DisplayVolume(void)
00755 {
00756   return new cSkinClassicDisplayVolume;
00757 }
00758 
00759 
00760 cSkinDisplayTracks *cSkinClassic::DisplayTracks(const char *Title, int NumTracks, const char * const *Tracks)
00761 {
00762   return new cSkinClassicDisplayTracks(Title, NumTracks, Tracks);
00763 }
00764 
00765 cSkinDisplayMessage *cSkinClassic::DisplayMessage(void)
00766 {
00767   return new cSkinClassicDisplayMessage;
00768 }