From 9bac72cbb2e98af35c0ecb35998b72cc460aa0b4 Mon Sep 17 00:00:00 2001
From: Martin Schirrmacher <vdr.skinflatplus@schirrmacher.eu>
Date: Sat, 16 Nov 2013 11:42:24 +0100
Subject: fix menuwidth if no scrollbar

---
 baserender.c  |  55 ++++++++++++++----
 baserender.h  |   4 +-
 displaymenu.c | 184 +++++++++++++++++++++++++++++++++++++++++++++++-----------
 displaymenu.h |  17 ++++++
 4 files changed, 213 insertions(+), 47 deletions(-)

diff --git a/baserender.c b/baserender.c
index 4621ac12..f945abb5 100644
--- a/baserender.c
+++ b/baserender.c
@@ -183,7 +183,8 @@ void cFlatBaseRender::ButtonsCreate(void) {
 }
 
 void cFlatBaseRender::ButtonsSet(const char *Red, const char *Green, const char *Yellow, const char *Blue) {
-    int buttonWidth = (buttonsWidth / 4) - Config.decorBorderButtonSize*2;
+    int WidthMargin = buttonsWidth - marginItem*3;
+    int buttonWidth = (WidthMargin / 4) - Config.decorBorderButtonSize*2;
 
     buttonsPixmap->Fill(clrTransparent);
 
@@ -284,7 +285,7 @@ void cFlatBaseRender::ContentSet(const char *Text, bool FixedFont, tColor ColorF
         contentWrapper.Set(Text, fontFixed, contentWidth - marginItem*2);
     else
         contentWrapper.Set(Text, font, contentWidth - marginItem*2);
-        
+    
     contentColorFg = ColorFg;
     contentColorBg = ColorBg;
 
@@ -300,6 +301,9 @@ void cFlatBaseRender::ContentSet(const char *Text, bool FixedFont, tColor ColorF
         contentHasScrollbar = false;
     }
 
+    if( contentPixmap )
+        osd->DestroyPixmap(contentPixmap);
+        
     contentPixmap = osd->CreatePixmap(2, cRect(contentLeft, contentTop, contentWidth, contentHeight),
             cRect(0, 0, contentWidth, contentDrawPortHeight));
 
@@ -309,10 +313,31 @@ void cFlatBaseRender::ContentSet(const char *Text, bool FixedFont, tColor ColorF
     contentShown = true;
 }
 
+bool cFlatBaseRender::ContentWillItBeScrollable(int Width, int Height, const char *Text, bool FixedFont) {
+    cTextWrapper wrapper;
+    if( FixedFont )
+        wrapper.Set(Text, fontFixed, Width - marginItem*2);
+    else
+        wrapper.Set(Text, font, Width - marginItem*2);
+
+    int VisibleLines = Height / fontHeight;
+    if( FixedFont )
+        VisibleLines = Height / fontFixedHeight;
+
+    if( wrapper.Lines() > 0 && wrapper.Lines() > VisibleLines )
+        return true;
+    
+    return false;
+}
+
 bool cFlatBaseRender::ContentScrollable(void) {
     return contentHasScrollbar;
 }
 
+int cFlatBaseRender::ContentGetHeight(void) {
+    return contentHeight;
+}
+
 double cFlatBaseRender::ScrollbarSize(void) {
     return (double)contentHeight / (double)contentDrawPortHeight;
 }
@@ -321,16 +346,18 @@ int cFlatBaseRender::ContentScrollTotal(void) {
     return contentWrapper.Lines();
 }
 
-int cFlatBaseRender::ContentGetHeight(void) {
-    return contentHeight;
-}
-
 int cFlatBaseRender::ContentScrollOffset(void) {
     double offset;
-    if ( ((-1)*contentPixmap->DrawPort().Point().Y() + contentHeight + fontHeight) > contentDrawPortHeight)
+    int h = fontHeight;
+    if( contentFixedFont )
+        h = fontFixedHeight;
+    
+    if ( ((-1)*contentPixmap->DrawPort().Point().Y() + contentHeight + h) > contentDrawPortHeight) {
         offset = (double)1 - ScrollbarSize();
-    else
-        offset = (double)((-1)*contentPixmap->DrawPort().Point().Y())/(double)((-1)*contentPixmap->DrawPort().Point().Y() + contentHeight);
+    } else {
+        offset = (double)((-1)*contentPixmap->DrawPort().Point().Y()) / (double)((-1)*contentPixmap->DrawPort().Point().Y() + contentHeight);
+    }
+    
     return ContentScrollTotal() * offset;
 }
 
@@ -346,6 +373,8 @@ bool cFlatBaseRender::ContentScroll(bool Up, bool Page) {
     int totalHeight = contentPixmap->DrawPort().Height();
     int screenHeight = contentPixmap->ViewPort().Height();
     int lineHeight = fontHeight;
+    if( contentFixedFont )
+        lineHeight = fontFixedHeight;
     bool scrolled = false;
     if (Up) {
         if (Page) {
@@ -391,11 +420,13 @@ void cFlatBaseRender::contentDraw(void) {
     int linesText = contentWrapper.Lines();
     int currentHeight = 0;
     for (int i=0; i < linesText; i++) {
-        currentHeight = (i)*fontHeight;
-        if( contentFixedFont )
+        if( contentFixedFont ) {
+            currentHeight = (i)*fontFixedHeight;
             contentPixmap->DrawText(cPoint(marginItem, currentHeight), contentWrapper.GetLine(i), contentColorFg, contentColorBg, fontFixed, contentWidth - marginItem*2);
-        else
+        } else {
+            currentHeight = (i)*fontHeight;
             contentPixmap->DrawText(cPoint(marginItem, currentHeight), contentWrapper.GetLine(i), contentColorFg, contentColorBg, font, contentWidth - marginItem*2);
+        }
     }
 }
 
diff --git a/baserender.h b/baserender.h
index eba3edf8..15aa2a88 100644
--- a/baserender.h
+++ b/baserender.h
@@ -6,7 +6,8 @@
 
 enum eBorder {
     BorderMenuItem = 1,
-    BorderRecordJump = 2
+    BorderRecordJump = 2,
+    BorderMenuRecord = 3
 };
 
 struct sBorderFrom {
@@ -131,6 +132,7 @@ class cFlatBaseRender
         void ContentSet(const char *Text, bool FixedFont, tColor ColorFg, tColor ColorBg);
         bool ContentIsShown(void);
         bool ContentScrollable(void);
+        bool ContentWillItBeScrollable(int Width, int Height, const char *Text, bool FixedFont);
         int ContentScrollTotal(void);
         int ContentScrollOffset(void);
         int ContentVisibleLines(void);
diff --git a/displaymenu.c b/displaymenu.c
index 0f62bac5..f8716183 100644
--- a/displaymenu.c
+++ b/displaymenu.c
@@ -15,8 +15,12 @@ cFlatDisplayMenu::cFlatDisplayMenu(void) {
     scrollBarHeight = osdHeight - (topBarHeight + Config.decorBorderTopBarSize*2 + 
         buttonsHeight + Config.decorBorderButtonSize*2 + marginItem*3 );
     scrollBarTop = topBarHeight + marginItem + Config.decorBorderTopBarSize*2;
-
-    menuWidth = osdWidth; // - scrollBarWidth; // scrollbar only if needed
+    isScrolling = false;
+    ShowEvent = false;
+    ShowRecording = false;
+    ShowText = false;
+    
+    menuWidth = osdWidth;
     menuTop = topBarHeight + marginItem + Config.decorBorderTopBarSize*2 + Config.decorBorderMenuItemSize;
     menuPixmap = osd->CreatePixmap(1, cRect(0, menuTop, menuWidth, scrollBarHeight ));
     
@@ -26,15 +30,6 @@ cFlatDisplayMenu::cFlatDisplayMenu(void) {
     chHeight = fontHeight + fontSmlHeight*2 + marginItem*2;
     contentHeadPixmap = osd->CreatePixmap(1, cRect(chLeft, chTop, chWidth, chHeight));
     
-    cLeft = Config.decorBorderMenuContentSize;
-    cTop = chTop + marginItem*3 + fontHeight + fontSmlHeight*2 +
-        Config.decorBorderMenuContentSize + Config.decorBorderMenuContentHeadSize;
-    cWidth = menuWidth - Config.decorBorderMenuContentSize*2;
-    cHeight = osdHeight - (topBarHeight + Config.decorBorderTopBarSize*2 +
-        buttonsHeight + Config.decorBorderButtonSize*2 + marginItem*3 + 
-        chHeight + Config.decorBorderMenuContentHeadSize*2 + Config.decorBorderMenuContentSize*2);
-    ContentCreate(cLeft, cTop, cWidth, cHeight, false);
-
     scrollbarPixmap = osd->CreatePixmap(2, cRect(osdWidth - scrollBarWidth, scrollBarTop, scrollBarWidth, scrollBarHeight));
 
     menuPixmap->Fill(clrTransparent);
@@ -54,8 +49,17 @@ void cFlatDisplayMenu::SetMenuCategory(eMenuCategory MenuCategory) {
 }
 
 void cFlatDisplayMenu::DrawScrollbar(int Total, int Offset, int Shown, int Top, int Height, bool CanScrollUp, bool CanScrollDown) {
-    if (Total > 0 && Total > Shown)
-        menuPixmap->DrawRectangle(cRect(menuWidth - scrollBarWidth, 0, scrollBarWidth, scrollBarHeight), clrTransparent);
+    if( Total > 0 && Total > Shown ) {
+        if( isScrolling == false && ShowEvent == false && ShowRecording == false && ShowText == false ) {
+            isScrolling = true;
+            DecorBorderClearByFrom(BorderMenuItem);
+            ItemBorderDrawAllWithScrollbar();
+            ItemBorderClear();
+            menuPixmap->DrawRectangle(cRect(menuWidth - scrollBarWidth - Config.decorBorderMenuItemSize, 0, scrollBarWidth, scrollBarHeight), clrTransparent);
+        }
+    } else if( ShowEvent == false && ShowRecording == false && ShowText == false ) {
+        isScrolling = false;
+    }
 
     ScrollbarDraw(scrollbarPixmap, Config.MenuItemPadding, Top, Height, Total, Offset, Shown, CanScrollUp, CanScrollDown);
 }
@@ -144,7 +148,15 @@ void cFlatDisplayMenu::SetMessage(eMessageType Type, const char *Text) {
 }
 
 void cFlatDisplayMenu::SetItem(const char *Text, int Index, bool Current, bool Selectable) {
+    ShowEvent = false;
+    ShowRecording = false;
+    ShowText = false;
+    
     int y = Index * itemHeight;
+    int Width = menuWidth - Config.decorBorderMenuItemSize*2;
+    if( isScrolling )
+        Width -= scrollBarWidth;
+    
     tColor ColorFg, ColorBg;
     if (Current) {
         ColorFg = Theme.Color(clrItemCurrentFont);
@@ -180,30 +192,40 @@ void cFlatDisplayMenu::SetItem(const char *Text, int Index, bool Current, bool S
                     xt + Config.decorBorderMenuItemSize, colWidth, s, ColorFg, ColorBarFg, ColorBg);
             } else {
                 menuPixmap->DrawText(cPoint(xt + Config.decorBorderMenuItemSize, y), s, ColorFg, ColorBg, font,
-                    menuWidth - Config.decorBorderMenuItemSize*2 - xt);
+                    Width - xt);
             }
         }
         if (!Tab(i + 1))
             break;
     }
 
-    int left = Config.decorBorderMenuItemSize;
-    int top = topBarHeight + marginItem + Config.decorBorderTopBarSize*2 + Config.decorBorderMenuItemSize + y;
-
-    if( Current )
-        DecorBorderDraw(left, top, menuWidth - Config.decorBorderMenuItemSize*2, fontHeight,
-            Config.decorBorderMenuItemSize, Config.decorBorderMenuItemType, Config.decorBorderMenuItemCurFg,
-            Config.decorBorderMenuItemCurBg, BorderMenuItem);
-    else {
-        if( Selectable )
-            DecorBorderDraw(left, top, menuWidth - Config.decorBorderMenuItemSize*2, fontHeight,
-                Config.decorBorderMenuItemSize, Config.decorBorderMenuItemType, Config.decorBorderMenuItemSelFg,
-                Config.decorBorderMenuItemSelBg, BorderMenuItem);
-        else
-            DecorBorderDraw(left, top, menuWidth - Config.decorBorderMenuItemSize*2, fontHeight,
-                Config.decorBorderMenuItemSize, Config.decorBorderMenuItemType, Config.decorBorderMenuItemFg,
-                Config.decorBorderMenuItemBg, BorderMenuItem);
+    sDecorBorder ib;
+    ib.Left = Config.decorBorderMenuItemSize;
+    ib.Top = topBarHeight + marginItem + Config.decorBorderTopBarSize*2 + Config.decorBorderMenuItemSize + y;
+    ib.Width = menuWidth - Config.decorBorderMenuItemSize*2;
+    if( isScrolling )
+        ib.Width -= scrollBarWidth;
+    ib.Height = fontHeight;
+    ib.Size = Config.decorBorderMenuItemSize;
+    ib.Type = Config.decorBorderMenuItemType;
+
+    if( Current ) {
+        ib.ColorFg = Config.decorBorderMenuItemCurFg;
+        ib.ColorBg = Config.decorBorderMenuItemCurBg;
+    } else {
+        if( Selectable ) {
+            ib.ColorFg = Config.decorBorderMenuItemSelFg;
+            ib.ColorBg = Config.decorBorderMenuItemSelBg;
+        } else {
+            ib.ColorFg = Config.decorBorderMenuItemFg;
+            ib.ColorBg = Config.decorBorderMenuItemBg;
+        }
     }
+
+    DecorBorderDraw(ib.Left, ib.Top, ib.Width, ib.Height,
+        ib.Size, ib.Type, ib.ColorFg, ib.ColorBg, BorderMenuItem);
+    
+    ItemBorderInsertUnique(ib);
     
     SetEditableWidth(menuWidth - Tab(1));
 }
@@ -343,6 +365,26 @@ void cFlatDisplayMenu::SetEvent(const cEvent *Event) {
     if( !Event )
         return;
 
+    ShowEvent = true;
+    ShowRecording = false;
+    ShowText = false;
+    ItemBorderClear();
+
+    cLeft = Config.decorBorderMenuContentSize;
+    cTop = chTop + marginItem*3 + fontHeight + fontSmlHeight*2 +
+        Config.decorBorderMenuContentSize + Config.decorBorderMenuContentHeadSize;
+    cWidth = menuWidth - Config.decorBorderMenuContentSize*2;
+    cHeight = osdHeight - (topBarHeight + Config.decorBorderTopBarSize*2 +
+        buttonsHeight + Config.decorBorderButtonSize*2 + marginItem*3 + 
+        chHeight + Config.decorBorderMenuContentHeadSize*2 + Config.decorBorderMenuContentSize*2);
+
+    bool contentScrollable = ContentWillItBeScrollable(cWidth, cHeight, Event->Description(), false);
+    if( contentScrollable ) {
+        cWidth -= scrollBarWidth;
+    }
+
+    ContentCreate(cLeft, cTop, cWidth, cHeight, false);
+    
     contentHeadPixmap->Fill(clrTransparent);
     contentHeadPixmap->DrawRectangle(cRect(0, 0, menuWidth, fontHeight + fontSmlHeight*2 + marginItem*2), Theme.Color(clrScrollbarBg));
 
@@ -373,10 +415,38 @@ void cFlatDisplayMenu::SetEvent(const cEvent *Event) {
 void cFlatDisplayMenu::SetRecording(const cRecording *Recording) {
     if( !Recording )
         return;
+
+    ShowEvent = false;
+    ShowRecording = true;
+    ShowText = false;
+    ItemBorderClear();
+
+    const cRecordingInfo *recInfo = Recording->Info();
+
+    chLeft = Config.decorBorderMenuContentHeadSize;
+    chTop = topBarHeight + marginItem + Config.decorBorderTopBarSize*2 + Config.decorBorderMenuContentHeadSize;
+    chWidth = menuWidth - Config.decorBorderMenuContentHeadSize*2;
+    chHeight = fontHeight + fontSmlHeight*2 + marginItem*2;
+    contentHeadPixmap = osd->CreatePixmap(1, cRect(chLeft, chTop, chWidth, chHeight));
+    
+    cLeft = Config.decorBorderMenuContentSize;
+    cTop = chTop + marginItem*3 + fontHeight + fontSmlHeight*2 +
+        Config.decorBorderMenuContentSize + Config.decorBorderMenuContentHeadSize;
+    cWidth = menuWidth - Config.decorBorderMenuContentSize*2;
+    cHeight = osdHeight - (topBarHeight + Config.decorBorderTopBarSize*2 +
+        buttonsHeight + Config.decorBorderButtonSize*2 + marginItem*3 + 
+        chHeight + Config.decorBorderMenuContentHeadSize*2 + Config.decorBorderMenuContentSize*2);
+
+    bool contentScrollable = ContentWillItBeScrollable(cWidth, cHeight, recInfo->Description(), false);
+    if( contentScrollable ) {
+        cWidth -= scrollBarWidth;
+    }
+
+    ContentCreate(cLeft, cTop, cWidth, cHeight, false);
+    
     contentHeadPixmap->Fill(clrTransparent);
     contentHeadPixmap->DrawRectangle(cRect(0, 0, menuWidth, fontHeight + fontSmlHeight*2 + marginItem*2), Theme.Color(clrScrollbarBg));
 
-    const cRecordingInfo *recInfo = Recording->Info();
     cString timeString = cString::sprintf("%s  %s  %s", *DateString(Recording->Start()), *TimeString(Recording->Start()), recInfo->ChannelName() ? recInfo->ChannelName() : "");
 
     cString title = recInfo->Title();
@@ -392,16 +462,34 @@ void cFlatDisplayMenu::SetRecording(const cRecording *Recording) {
         Config.decorBorderMenuContentHeadFg, Config.decorBorderMenuContentHeadBg);
     
     ContentSet( recInfo->Description(), false, Theme.Color(clrMenuRecFontInfo), Theme.Color(clrMenuRecBg) );
-    if( ContentScrollable() )
+    if( ContentScrollable() ) {
         DrawScrollbar(ContentScrollTotal(), ContentScrollOffset(), ContentVisibleLines(), contentTop - scrollBarTop, ContentGetHeight(), ContentScrollOffset() > 0, ContentScrollOffset() + ContentVisibleLines() < ContentScrollTotal());
+    }
 
-    DecorBorderDraw(cLeft, cTop, cWidth, ContentGetHeight(), Config.decorBorderMenuContentSize, Config.decorBorderMenuContentType,
-        Config.decorBorderMenuContentFg, Config.decorBorderMenuContentBg);
+    RecordingBorder.Left = cLeft;
+    RecordingBorder.Top = cTop;
+    RecordingBorder.Width = cWidth;
+    RecordingBorder.Height = ContentGetHeight();
+    RecordingBorder.Size = Config.decorBorderMenuContentSize;
+    RecordingBorder.Type = Config.decorBorderMenuContentType;
+    RecordingBorder.ColorFg = Config.decorBorderMenuContentFg;
+    RecordingBorder.ColorBg = Config.decorBorderMenuContentBg;
+    RecordingBorder.From = BorderMenuRecord;
+    
+    DecorBorderDraw(RecordingBorder.Left, RecordingBorder.Top, RecordingBorder.Width, RecordingBorder.Height,
+        RecordingBorder.Size, RecordingBorder.Type,
+        RecordingBorder.ColorFg, RecordingBorder.ColorBg, RecordingBorder.From);
 }
 
 void cFlatDisplayMenu::SetText(const char *Text, bool FixedFont) {
     if( !Text )
         return;
+
+    ShowEvent = false;
+    ShowRecording = false;
+    ShowText = true;
+    ItemBorderClear();
+
     contentHeadPixmap->Fill(clrTransparent);
 
     int Left = Config.decorBorderMenuContentSize;
@@ -409,6 +497,12 @@ void cFlatDisplayMenu::SetText(const char *Text, bool FixedFont) {
     int Width = menuWidth - Config.decorBorderMenuContentSize*2;
     int Height = osdHeight - (topBarHeight + Config.decorBorderTopBarSize*2 +
         buttonsHeight + Config.decorBorderButtonSize*2 + marginItem*3);
+
+    bool contentScrollable = ContentWillItBeScrollable(Width, Height, Text, FixedFont);
+    if( contentScrollable ) {
+        Width -= scrollBarWidth;
+    }
+
     ContentCreate(Left, Top, Width, Height, FixedFont);
 
     ContentSet( Text, FixedFont, Theme.Color(clrMenuTextFont), Theme.Color(clrMenuTextBg) );
@@ -432,3 +526,25 @@ void cFlatDisplayMenu::Flush(void) {
     TopBarUpdate();
     osd->Flush();
 }
+
+void cFlatDisplayMenu::ItemBorderInsertUnique(sDecorBorder ib) {
+    std::list<sDecorBorder>::iterator it;
+    for( it = ItemsBorder.begin(); it != ItemsBorder.end(); it++ ) {
+        if( (*it).Left == ib.Left && (*it).Width == ib.Width && (*it).Top == ib.Top && (*it).Height == ib.Height ) {
+            return;
+        }
+    }
+    ItemsBorder.push_back(ib);
+}
+
+void cFlatDisplayMenu::ItemBorderDrawAllWithScrollbar(void) {
+    std::list<sDecorBorder>::iterator it;
+    for( it = ItemsBorder.begin(); it != ItemsBorder.end(); it++ ) {
+        DecorBorderDraw((*it).Left, (*it).Top, (*it).Width - scrollBarWidth, (*it).Height, (*it).Size, (*it).Type,
+            (*it).ColorFg, (*it).ColorBg, BorderMenuItem);
+    }
+}
+
+void cFlatDisplayMenu::ItemBorderClear(void) {
+    ItemsBorder.clear();
+}
\ No newline at end of file
diff --git a/displaymenu.h b/displaymenu.h
index c78ce7b9..aad214eb 100644
--- a/displaymenu.h
+++ b/displaymenu.h
@@ -1,6 +1,13 @@
 #pragma once
 
 #include "baserender.h"
+#include <list>
+
+struct sDecorBorder {
+    int Left, Top, Width, Height, Size, Type;
+    tColor ColorFg, ColorBg;
+    int From;
+};
 
 class cFlatDisplayMenu : public cFlatBaseRender,  public cSkinDisplayMenu {
     private:
@@ -19,6 +26,16 @@ class cFlatDisplayMenu : public cFlatBaseRender,  public cSkinDisplayMenu {
         int scrollBarTop, scrollBarWidth, scrollBarHeight;
 
         int itemHeight, itemChannelHeight;
+
+        std::list<sDecorBorder> ItemsBorder;
+        sDecorBorder EventBorder, RecordingBorder, TextBorder;
+    
+        bool isScrolling;
+        bool ShowEvent, ShowRecording, ShowText;
+    
+        void ItemBorderInsertUnique(sDecorBorder ib);
+        void ItemBorderDrawAllWithScrollbar(void);
+        void ItemBorderClear(void);
         
         void DrawScrollbar(int Total, int Offset, int Shown, int Top, int Height, bool CanScrollUp, bool CanScrollDown);
         int ItemsHeight(void);
-- 
cgit v1.2.3