//************************************************************************
// The Logitech LCD SDK, including all acompanying documentation,
// is protected by intellectual property laws. All use of the Logitech
// LCD SDK is subject to the License Agreement found in the
// "Logitech LCD SDK License Agreement" file and in the Reference Manual.
// All rights not expressly granted by Logitech are reserved.
//************************************************************************
//************************************************************************
//
// LCDPopup.cpp
//
// Color LCD Popup class
//
// Logitech LCD SDK
//
// Copyright 2010 Logitech Inc.
//************************************************************************
#include "LCDUI.h"
#include "LCDPopup.h"
#if LCDIU_GDIPLUS_ENABLE
#include <gdiplus.h>
// This uses GDI+
using namespace Gdiplus;
#endif
//************************************************************************
//
// CLCDPopupBackground::CLCDPopupBackground
//
//************************************************************************
CLCDPopupBackground::CLCDPopupBackground(void)
{
m_bUseGradient = FALSE;
m_cAlphaStart = 0x9f;
m_cAlphaEnd = m_cAlphaStart/2;
m_cfColor = 0;
m_nRectRadius = 15;
#if LCDIU_GDIPLUS_ENABLE
m_pGraphicsPath = NULL;
#endif
}
//************************************************************************
//
// CLCDPopupBackground::~CLCDPopupBackground
//
//************************************************************************
CLCDPopupBackground::~CLCDPopupBackground(void)
{
#if LCDIU_GDIPLUS_ENABLE
if (m_pGraphicsPath)
{
delete m_pGraphicsPath;
m_pGraphicsPath = NULL;
}
#endif
}
//************************************************************************
//
// CLCDPopupBackground::SetSize
//
//************************************************************************
void CLCDPopupBackground::SetSize(int nCX, int nCY)
{
CLCDBase::SetSize(nCX, nCY);
RecalcRoundedRectangle();
}
//************************************************************************
//
// CLCDPopupBackground::OnDraw
//
//************************************************************************
void CLCDPopupBackground::OnDraw(CLCDGfxBase &rGfx)
{
#if LCDIU_GDIPLUS_ENABLE
if (NULL == m_pGraphicsPath)
{
// Size has not been set
return;
}
// Draw to the extent of the control
Rect r(0, 0, GetWidth(), GetHeight());
Graphics gfx(rGfx.GetHDC());
if (m_bUseGradient)
{
LinearGradientBrush brush(
r,
Color(Color::MakeARGB(m_cAlphaStart, GetRValue(m_cfColor), GetGValue(m_cfColor), GetBValue(m_cfColor))),
Color(Color::MakeARGB(m_cAlphaEnd, GetRValue(m_cfColor), GetGValue(m_cfColor), GetBValue(m_cfColor))),
LinearGradientModeVertical
); // blue
gfx.FillPath(&brush, m_pGraphicsPath);
}
else
{
SolidBrush brush(Color::MakeARGB(m_cAlphaStart, GetRValue(m_cfColor), GetGValue(m_cfColor), GetBValue(m_cfColor)));
gfx.FillPath(&brush, m_pGraphicsPath);
}
#endif
}
//************************************************************************
//
// CLCDPopupBackground::SetAlphaLevel
//
//************************************************************************
void CLCDPopupBackground::SetAlphaLevel(BYTE cAlphaStart, BYTE cAlphaEnd)
{
m_cAlphaStart = cAlphaStart;
m_cAlphaEnd = cAlphaEnd;
}
//************************************************************************
//
// CLCDPopupBackground::SetGradientMode
//
//************************************************************************
void CLCDPopupBackground::SetGradientMode(BOOL bGradient)
{
m_bUseGradient = bGradient;
}
//************************************************************************
//
// CLCDPopupBackground::SetColor
//
//************************************************************************
void CLCDPopupBackground::SetColor(COLORREF cfColor)
{
m_cfColor = cfColor;
}
//************************************************************************
//
// CLCDPopupBackground::SetRoundedRecteRadius
//
//************************************************************************
void CLCDPopupBackground::SetRoundedRecteRadius(int nRadius)
{
m_nRectRadius = nRadius;
RecalcRoundedRectangle();
}
//************************************************************************
//
// CLCDPopupBackground::RecalcRoundedRectangle
//
//************************************************************************
void CLCDPopupBackground::RecalcRoundedRectangle(void)
{
#if LCDIU_GDIPLUS_ENABLE
if (m_pGraphicsPath)
{
delete m_pGraphicsPath;
m_pGraphicsPath = NULL;
}
m_pGraphicsPath = new GraphicsPath();
int l = 0;
int t = 0;
int w = GetWidth();
int h = GetHeight();
int d = m_nRectRadius << 1;
m_pGraphicsPath->AddArc(l, t, d, d, 180, 90);
m_pGraphicsPath->AddLine(l + m_nRectRadius, t, l + w - m_nRectRadius, t);
m_pGraphicsPath->AddArc(l + w - d, t, d, d, 270, 90);
m_pGraphicsPath->AddLine(l + w, t + m_nRectRadius, l + w, t + h - m_nRectRadius);
m_pGraphicsPath->AddArc(l + w - d, t + h - d, d, d, 0, 90);
m_pGraphicsPath->AddLine(l + w - m_nRectRadius, t + h, l + m_nRectRadius, t + h);
m_pGraphicsPath->AddArc(l, t + h - d, d, d, 90, 90);
m_pGraphicsPath->AddLine(l, t + h - m_nRectRadius, l, t + m_nRectRadius);
m_pGraphicsPath->CloseFigure();
#endif
}
// Define the maximum popup width as 1/2 of the QVGA width
#define MAX_POPUP_WIDTH (LGLCD_QVGA_BMP_WIDTH / 2)
#define POPUP_MARGIN (12)
#define POPUP_FONT_PT (12)
#define POPUP_FONT_WT FW_BOLD
#define POPUP_FONT_FACE _T("Arial")
//************************************************************************
//
// CLCDPopup::CLCDPopup
//
//************************************************************************
CLCDPopup::CLCDPopup(void)
{
m_nMaxPopupWidth = MAX_POPUP_WIDTH;
m_pbType = PB_TEXT;
}
//************************************************************************
//
// CLCDPopup::Initialize
//
//************************************************************************
HRESULT CLCDPopup::Initialize(int nMaxPopupWidth /* = 0 */)
{
if(0 == nMaxPopupWidth)
{
m_nMaxPopupWidth = MAX_POPUP_WIDTH;
}
else
{
m_nMaxPopupWidth = nMaxPopupWidth;
}
// The text gets offset by the margin
m_Background.Initialize();
m_Background.SetOrigin(0, 0);
m_MessageText.SetOrigin(POPUP_MARGIN, POPUP_MARGIN);
m_MessageText.SetFontFaceName(POPUP_FONT_FACE);
m_MessageText.SetFontPointSize(POPUP_FONT_PT);
m_MessageText.SetFontWeight(POPUP_FONT_WT);
m_MessageText.SetWordWrap(TRUE);
m_MessageText.SetSize(LGLCD_QVGA_BMP_WIDTH, LGLCD_QVGA_BMP_HEIGHT);
m_OKText.SetFontFaceName(_T("Arial"));
m_OKText.SetFontPointSize(10);
m_OKText.SetFontWeight(FW_NORMAL);
m_OKText.SetWordWrap(TRUE);
m_OKText.Show(FALSE);
m_CancelText.SetFontFaceName(_T("Arial"));
m_CancelText.SetFontPointSize(10);
m_CancelText.SetFontWeight(FW_NORMAL);
m_CancelText.SetWordWrap(TRUE);
m_CancelText.Show(FALSE);
AddObject(&m_Background);
AddObject(&m_MessageText);
AddObject(&m_OKBitmap);
AddObject(&m_CancelBitmap);
AddObject(&m_OKText);
AddObject(&m_CancelText);
return CLCDBase::Initialize();
}
//************************************************************************
//
// CLCDPopup::SetPopupType
//
//************************************************************************
void CLCDPopup::SetPopupType(PB_TYPE pbType)
{
m_pbType = pbType;
RecalcLayout();
}
//************************************************************************
//
// CLCDPopup::SetText
//
//************************************************************************
void CLCDPopup::SetText(LPCTSTR szMessage, LPCTSTR szOK, LPCTSTR szCancel)
{
if (NULL != szMessage)
{
m_MessageText.SetText(szMessage);
}
if (NULL != szOK)
{
m_OKText.SetText(szOK);
}
if (NULL != szCancel)
{
m_CancelText.SetText(szCancel);
}
RecalcLayout();
}
//************************************************************************
//
// CLCDPopup::SetSize
//
//************************************************************************
void CLCDPopup::SetSize(int nCX, int nCY)
{
CLCDPage::SetSize(nCX, nCY);
}
//************************************************************************
//
// CLCDPopup::RecalcLayout
//
//************************************************************************
void CLCDPopup::RecalcLayout(void)
{
// First get the size of the text
// If the width > MAX_WIDTH, snap it to the max width
int nTextWidthWithMargin = 2 * POPUP_MARGIN;
int nTextHeightWithMargin = 2 * POPUP_MARGIN;
if(0 < _tcslen(m_MessageText.GetText()))
{
m_MessageText.CalculateExtent(FALSE);
nTextWidthWithMargin = m_MessageText.GetVExtent().cx + 2*POPUP_MARGIN;
nTextHeightWithMargin = m_MessageText.GetVExtent().cy + 2*POPUP_MARGIN;
if(nTextWidthWithMargin > m_nMaxPopupWidth)
{
// Resize the text using a max height
m_MessageText.SetSize(m_nMaxPopupWidth, LGLCD_QVGA_BMP_HEIGHT);
m_MessageText.CalculateExtent(FALSE);
nTextWidthWithMargin = m_MessageText.GetVExtent().cx + 2*POPUP_MARGIN;
nTextHeightWithMargin = m_MessageText.GetVExtent().cy + 2*POPUP_MARGIN;
}
m_MessageText.SetSize(m_MessageText.GetVExtent().cx, m_MessageText.GetVExtent().cy);
}
else
{
nTextHeightWithMargin = POPUP_MARGIN;
nTextWidthWithMargin = 0;
m_MessageText.SetSize(0, 0);
}
// Determine the size of the popup including..
// Margin
// Text
// OK Bitmap
// Cancel Bitmap
int nPopupWidth = nTextWidthWithMargin;
int nPopupHeight = nTextHeightWithMargin;
// Bitmap operations
BITMAP bmOK, bmCancel;
memset(&bmOK, 0, sizeof(bmOK));
memset(&bmCancel, 0, sizeof(bmCancel));
if (NULL != m_OKBitmap.GetBitmap())
{
GetObject( m_OKBitmap.GetBitmap(), sizeof(BITMAP), &bmOK);
m_OKBitmap.SetSize(bmOK.bmWidth, bmOK.bmHeight);
}
if (NULL != m_CancelBitmap.GetBitmap())
{
GetObject( m_CancelBitmap.GetBitmap(), sizeof(BITMAP), &bmCancel);
m_CancelBitmap.SetSize(bmCancel.bmWidth, bmCancel.bmHeight);
}
switch(m_pbType)
{
// Main text block only
case PB_TEXT:
m_OKBitmap.Show(FALSE);
m_CancelBitmap.Show(FALSE);
break;
// OK is centered against the main text block
case PB_OK:
if (bmOK.bmWidth)
{
// Just factor in a bitmap
// Add the bitmap w/ margin on the bottom
nPopupHeight += bmOK.bmHeight;
nPopupHeight += POPUP_MARGIN;
// Position the bitmap centered, and vertically after the text+margin
m_OKBitmap.SetOrigin((nPopupWidth-bmOK.bmWidth)/2, nTextHeightWithMargin);
m_OKBitmap.Show(TRUE);
}
break;
// OK, Cancel Buttons are aligned on the same row below the text block (like a dialog)
case PB_OKCANCEL:
if (bmOK.bmWidth && bmCancel.bmWidth)
{
// Add the bitmap w/ margin on the bottom
nPopupHeight += bmOK.bmHeight;
nPopupHeight += POPUP_MARGIN;
// OK is right-aligned with the text
m_OKBitmap.SetOrigin(m_MessageText.GetOrigin().x + m_MessageText.GetSize().cx - bmOK.bmWidth,
nTextHeightWithMargin);
// Cancel is right-aligned with OK (with margin)
m_CancelBitmap.SetOrigin(m_OKBitmap.GetOrigin().x - bmCancel.bmWidth - POPUP_MARGIN,
nTextHeightWithMargin);
m_OKBitmap.Show(TRUE);
m_CancelBitmap.Show(TRUE);
}
break;
// OK, Cancel Buttons are on separate rows centered against their own text blocks
case PB_OKCANCEL_TEXT:
{
int nOKTextWithBitmapHeight = 0;
int nMaxOKTextWidth = 0;
m_OKText.SetOrigin(POPUP_MARGIN, nTextHeightWithMargin - POPUP_MARGIN);
if (bmOK.bmWidth)
{
// OK is left-aligned with the text
m_OKBitmap.SetOrigin(m_MessageText.GetOrigin().x, nTextHeightWithMargin);
// OK text height is left-aligned with OK bmp and right-aligned with text
// OK bmp is vertically centered against the OK text
nMaxOKTextWidth = m_MessageText.GetWidth() - bmOK.bmWidth - POPUP_MARGIN;
if (nMaxOKTextWidth < 0)
{
nMaxOKTextWidth = LGLCD_QVGA_BMP_WIDTH;
}
m_OKText.SetOrigin(m_OKBitmap.GetOrigin().x + bmOK.bmWidth + POPUP_MARGIN, nTextHeightWithMargin);
m_OKText.SetSize(nMaxOKTextWidth, LGLCD_QVGA_BMP_HEIGHT);
m_OKText.CalculateExtent(FALSE);
m_OKText.SetSize(m_OKText.GetVExtent().cx, m_OKText.GetVExtent().cy);
// if no main text, figure out required max popup width
int nCalcPopupWidth = POPUP_MARGIN*3 + bmOK.bmWidth + m_OKText.GetSize().cx;
if (nCalcPopupWidth > nPopupWidth)
{
nPopupWidth = nCalcPopupWidth;
}
// Add the bitmap w/ margin on the bottom
nOKTextWithBitmapHeight = max(bmOK.bmHeight, m_OKText.GetHeight());
nPopupHeight += nOKTextWithBitmapHeight;
nPopupHeight += POPUP_MARGIN;
m_OKText.Show(TRUE);
m_OKBitmap.Show(TRUE);
m_OKBitmap.SetOrigin(m_OKBitmap.GetOrigin().x, m_OKText.GetOrigin().y + (m_OKText.GetHeight() - bmOK.bmHeight)/2);
}
if (bmCancel.bmWidth)
{
// Cancel is left-aligned with the text
m_CancelBitmap.SetOrigin(m_MessageText.GetOrigin().x, m_OKText.GetOrigin().y + nOKTextWithBitmapHeight + POPUP_MARGIN);
int nMaxCancelTextWidth = m_MessageText.GetWidth() - bmCancel.bmWidth - POPUP_MARGIN;
if (nMaxCancelTextWidth < 0)
{
nMaxCancelTextWidth = LGLCD_QVGA_BMP_WIDTH;
}
m_CancelText.SetOrigin(m_CancelBitmap.GetOrigin().x + bmCancel.bmWidth + POPUP_MARGIN, m_CancelBitmap.GetOrigin().y);
m_CancelText.SetSize(nMaxCancelTextWidth, LGLCD_QVGA_BMP_HEIGHT);
m_CancelText.CalculateExtent(FALSE);
m_CancelText.SetSize(m_CancelText.GetVExtent().cx, m_CancelText.GetVExtent().cy);
// if no main text, make the
int nCalcPopupWidth = POPUP_MARGIN*3 + bmOK.bmWidth + m_CancelText.GetSize().cx;
if (nCalcPopupWidth > nPopupWidth)
{
nPopupWidth = nCalcPopupWidth;
}
nPopupHeight += max(bmCancel.bmHeight, m_CancelText.GetHeight());
nPopupHeight += POPUP_MARGIN;
// Vertically center the OK and CANCEL bitmaps against their respective texts
m_CancelText.Show(TRUE);
m_CancelBitmap.Show(TRUE);
m_CancelBitmap.SetOrigin(m_CancelBitmap.GetOrigin().x, m_CancelText.GetOrigin().y + (m_CancelText.GetHeight() - bmCancel.bmHeight)/2);
}
}
break;
}
// Resize ourself
SetSize(nPopupWidth, nPopupHeight);
// Center the popup in the middle of the screen
SetOrigin( (LGLCD_QVGA_BMP_WIDTH - nPopupWidth)/2, (LGLCD_QVGA_BMP_HEIGHT - nPopupHeight)/2);
// Resize the background
m_Background.SetSize(GetWidth(), GetHeight());
}
//************************************************************************
//
// CLCDPopup::SetBitmaps
//
//************************************************************************
void CLCDPopup::SetBitmaps(HBITMAP hbmOK, HBITMAP hbmCancel)
{
m_OKBitmap.SetBitmap(hbmOK);
m_CancelBitmap.SetBitmap(hbmCancel);
RecalcLayout();
}
//************************************************************************
//
// CLCDPopup::SetAlpha
//
//************************************************************************
void CLCDPopup::SetAlpha(BYTE bAlphaStart, BYTE bAlphaEnd)
{
m_Background.SetAlphaLevel(bAlphaStart, bAlphaEnd);
}
//************************************************************************
//
// CLCDPopup::SetGradientMode
//
//************************************************************************
void CLCDPopup::SetGradientMode(BOOL bGradient)
{
m_Background.SetGradientMode(bGradient);
}
//************************************************************************
//
// CLCDPopup::SetColor
//
//************************************************************************
void CLCDPopup::SetColor(COLORREF cfColor)
{
m_Background.SetColor(cfColor);
}
//** end of LCDPopup.cpp *************************************************
↑ V1051 Consider checking for misprints. It's possible that the 'nTextHeightWithMargin' should be checked here.
↑ V805 Decreased performance. It is inefficient to identify an empty string by using 'wcslen(str) > 0' construct. A more efficient way is to check: str[0] != '\0'.
↑ V807 Decreased performance. Consider creating a reference to avoid using the 'm_MessageText.GetVExtent()' expression repeatedly.
↑ V807 Decreased performance. Consider creating a reference to avoid using the 'm_CancelBitmap.GetOrigin()' expression repeatedly.