2009-02-10 18:37:48 +00:00
|
|
|
/*
|
|
|
|
Copyright (C) 2001 Kimmo Pekkola
|
|
|
|
|
|
|
|
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
|
2009-10-07 16:45:14 +00:00
|
|
|
#include "StdAfx.h"
|
2009-02-10 18:37:48 +00:00
|
|
|
#include "MeterString.h"
|
|
|
|
#include "Rainmeter.h"
|
|
|
|
#include "Measure.h"
|
|
|
|
#include "Error.h"
|
|
|
|
|
|
|
|
using namespace Gdiplus;
|
|
|
|
|
2009-10-07 16:45:14 +00:00
|
|
|
std::map<std::wstring, Gdiplus::FontFamily*> CMeterString::c_FontFamilies;
|
|
|
|
std::map<std::wstring, Gdiplus::Font*> CMeterString::c_Fonts;
|
|
|
|
|
2010-11-05 03:25:21 +00:00
|
|
|
void StringToUpper(std::wstring& str)
|
|
|
|
{
|
|
|
|
//change each element of the string to upper case
|
|
|
|
std::transform(str.begin(), str.end(), str.begin(), ::towupper);
|
|
|
|
}
|
|
|
|
|
|
|
|
void StringToLower(std::wstring& str)
|
|
|
|
{
|
|
|
|
//change each element of the string to lower case
|
|
|
|
std::transform(str.begin(), str.end(), str.begin(), ::towlower);
|
|
|
|
}
|
|
|
|
|
|
|
|
void StringToProper(std::wstring& str)
|
|
|
|
{
|
|
|
|
//change each element of the string to lower case
|
|
|
|
if (!str.empty())
|
|
|
|
{
|
|
|
|
str[0] = towupper(str[0]);
|
|
|
|
|
|
|
|
for (size_t i = 1; i < str.length(); ++i)
|
|
|
|
{
|
|
|
|
if (str[i-1] == L' ')
|
|
|
|
{
|
|
|
|
str[i] = towupper(str[i]);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
str[i] = towlower(str[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-03-18 19:48:14 +00:00
|
|
|
|
2009-02-10 18:37:48 +00:00
|
|
|
/*
|
|
|
|
** CMeterString
|
|
|
|
**
|
|
|
|
** The constructor
|
|
|
|
**
|
|
|
|
*/
|
2010-11-11 20:24:59 +00:00
|
|
|
CMeterString::CMeterString(CMeterWindow* meterWindow) : CMeter(meterWindow),
|
|
|
|
m_Color(Color::White),
|
|
|
|
m_EffectColor(Color::Black)
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
2009-07-29 12:54:05 +00:00
|
|
|
m_Effect = EFFECT_NONE;
|
2009-02-10 18:37:48 +00:00
|
|
|
m_AutoScale = true;
|
|
|
|
m_Align = ALIGN_LEFT;
|
|
|
|
m_Font = NULL;
|
|
|
|
m_FontFamily = NULL;
|
|
|
|
m_Style = NORMAL;
|
|
|
|
m_FontSize = 10;
|
|
|
|
m_Scale = 1.0;
|
|
|
|
m_NoDecimals = true;
|
|
|
|
m_Percentual = true;
|
|
|
|
m_ClipString = false;
|
|
|
|
m_NumOfDecimals = -1;
|
|
|
|
m_DimensionsDefined = false;
|
|
|
|
m_Angle = 0.0;
|
2010-03-18 19:48:14 +00:00
|
|
|
m_textCase = TEXTCASE_NONE;
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
** ~CMeterString
|
|
|
|
**
|
|
|
|
** The destructor
|
|
|
|
**
|
|
|
|
*/
|
|
|
|
CMeterString::~CMeterString()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
** GetX
|
|
|
|
**
|
|
|
|
** Returns the X-coordinate of the meter
|
|
|
|
**
|
|
|
|
*/
|
|
|
|
int CMeterString::GetX(bool abs)
|
|
|
|
{
|
|
|
|
int x = CMeter::GetX();
|
|
|
|
|
|
|
|
if (!abs)
|
|
|
|
{
|
|
|
|
switch(m_Align)
|
|
|
|
{
|
|
|
|
case ALIGN_CENTER:
|
|
|
|
x = x - (m_W / 2);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ALIGN_RIGHT:
|
|
|
|
x -= m_W;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ALIGN_LEFT:
|
|
|
|
// This is already correct
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
** Initialize
|
|
|
|
**
|
|
|
|
** Create the font that is used to draw the text.
|
|
|
|
**
|
|
|
|
*/
|
|
|
|
void CMeterString::Initialize()
|
|
|
|
{
|
|
|
|
CMeter::Initialize();
|
|
|
|
|
2009-10-07 16:45:14 +00:00
|
|
|
// Check if the font family is in the cache and use it
|
2010-03-30 22:37:05 +00:00
|
|
|
std::map<std::wstring, Gdiplus::FontFamily*>::const_iterator iter = c_FontFamilies.find(m_FontFace);
|
2009-10-07 16:45:14 +00:00
|
|
|
if (iter != c_FontFamilies.end())
|
|
|
|
{
|
|
|
|
m_FontFamily = (*iter).second;
|
|
|
|
}
|
|
|
|
else
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
2009-10-07 16:45:14 +00:00
|
|
|
m_FontFamily = new FontFamily(m_FontFace.c_str());
|
|
|
|
Status status = m_FontFamily->GetLastStatus();
|
2009-09-03 00:33:46 +00:00
|
|
|
|
2009-10-07 16:45:14 +00:00
|
|
|
// It couldn't find the font family
|
|
|
|
// Therefore we look in the privatefontcollection of this meters MeterWindow
|
2009-09-03 00:33:46 +00:00
|
|
|
if(Ok != status)
|
2009-10-07 16:45:14 +00:00
|
|
|
{
|
2009-09-03 00:33:46 +00:00
|
|
|
delete m_FontFamily;
|
2009-10-07 16:45:14 +00:00
|
|
|
m_FontFamily = new FontFamily(m_FontFace.c_str(), m_MeterWindow->GetPrivateFontCollection());
|
|
|
|
status = m_FontFamily->GetLastStatus();
|
|
|
|
|
|
|
|
// It couldn't find the font family: Log it.
|
|
|
|
if(Ok != status)
|
|
|
|
{
|
|
|
|
std::wstring error = L"Error: Couldn't load font family: ";
|
|
|
|
error += m_FontFace;
|
2010-10-31 20:13:32 +00:00
|
|
|
LSLog(LOG_DEBUG, APPNAME, error.c_str());
|
2009-10-07 16:45:14 +00:00
|
|
|
|
|
|
|
delete m_FontFamily;
|
|
|
|
m_FontFamily = NULL;
|
|
|
|
}
|
|
|
|
|
2009-09-03 00:33:46 +00:00
|
|
|
}
|
2009-10-07 16:45:14 +00:00
|
|
|
|
2010-02-04 07:16:22 +00:00
|
|
|
if(m_FontFamily)
|
|
|
|
{
|
|
|
|
c_FontFamilies[m_FontFace] = m_FontFamily;
|
|
|
|
}
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
FontStyle style = FontStyleRegular;
|
|
|
|
|
|
|
|
switch(m_Style)
|
|
|
|
{
|
|
|
|
case ITALIC:
|
|
|
|
style = FontStyleItalic;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case BOLD:
|
|
|
|
style = FontStyleBold;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case BOLDITALIC:
|
|
|
|
style = FontStyleBoldItalic;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Adjust the font size with screen DPI
|
2010-11-22 19:52:10 +00:00
|
|
|
HDC dc = GetDC(0);
|
2009-02-10 18:37:48 +00:00
|
|
|
int dpi = GetDeviceCaps(dc, LOGPIXELSX);
|
2010-11-22 19:52:10 +00:00
|
|
|
ReleaseDC(0, dc);
|
2009-02-10 18:37:48 +00:00
|
|
|
|
2009-02-14 10:11:28 +00:00
|
|
|
REAL size = (REAL)m_FontSize * (96.0f / (REAL)dpi);
|
2009-02-10 18:37:48 +00:00
|
|
|
|
2009-10-11 13:03:20 +00:00
|
|
|
std::wstring properties = FontPropertiesToString(m_FontFamily, size, style);
|
2010-03-30 22:37:05 +00:00
|
|
|
std::map<std::wstring, Gdiplus::Font*>::const_iterator iter2 = c_Fonts.find(properties);
|
2009-10-07 16:45:14 +00:00
|
|
|
if (iter2 != c_Fonts.end())
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
2009-10-07 16:45:14 +00:00
|
|
|
m_Font = (*iter2).second;
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-10-07 16:45:14 +00:00
|
|
|
if (m_FontFamily)
|
|
|
|
{
|
|
|
|
m_Font = new Gdiplus::Font(m_FontFamily, size, style);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_Font = new Gdiplus::Font(FontFamily::GenericSansSerif(), size, style);
|
|
|
|
}
|
2009-02-10 18:37:48 +00:00
|
|
|
|
2009-10-11 13:03:20 +00:00
|
|
|
Status status = m_Font->GetLastStatus();
|
2010-02-04 07:16:22 +00:00
|
|
|
if (Ok == status)
|
2009-10-11 13:03:20 +00:00
|
|
|
{
|
2010-02-04 07:16:22 +00:00
|
|
|
c_Fonts[properties] = m_Font;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
delete m_Font;
|
|
|
|
m_Font = NULL;
|
|
|
|
|
2010-02-08 14:12:47 +00:00
|
|
|
if (m_FontSize != 0)
|
2010-02-04 07:16:22 +00:00
|
|
|
{
|
2010-11-25 15:34:49 +00:00
|
|
|
std::wstring error = L"Unable to create font: ";
|
|
|
|
error += m_FontFace;
|
|
|
|
throw CError(error, __LINE__, __FILE__);
|
2010-02-04 07:16:22 +00:00
|
|
|
}
|
2009-10-11 13:03:20 +00:00
|
|
|
}
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
** ReadConfig
|
|
|
|
**
|
|
|
|
** Read the meter-specific configs from the ini-file.
|
|
|
|
**
|
|
|
|
*/
|
|
|
|
void CMeterString::ReadConfig(const WCHAR* section)
|
|
|
|
{
|
2010-09-13 20:06:52 +00:00
|
|
|
WCHAR tmpName[64];
|
2009-02-10 18:37:48 +00:00
|
|
|
|
2009-08-27 17:05:10 +00:00
|
|
|
// Store the current font values so we know if the font needs to be updated
|
|
|
|
std::wstring oldFontFace = m_FontFace;
|
|
|
|
int oldFontSize = m_FontSize;
|
|
|
|
TEXTSTYLE oldStyle = m_Style;
|
|
|
|
|
2009-02-10 18:37:48 +00:00
|
|
|
// Read common configs
|
|
|
|
CMeter::ReadConfig(section);
|
|
|
|
|
|
|
|
CConfigParser& parser = m_MeterWindow->GetParser();
|
|
|
|
|
2009-10-07 16:45:14 +00:00
|
|
|
m_MeasureNames.clear();
|
|
|
|
|
2009-02-10 18:37:48 +00:00
|
|
|
// Check for extra measures
|
2010-11-16 20:12:27 +00:00
|
|
|
if (!m_MeasureName.empty())
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
2010-11-16 20:12:27 +00:00
|
|
|
int i = 2;
|
|
|
|
bool loop = true;
|
|
|
|
do
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
2010-11-16 20:12:27 +00:00
|
|
|
swprintf(tmpName, L"MeasureName%i", i);
|
|
|
|
std::wstring measure = parser.ReadString(section, tmpName, L"");
|
|
|
|
if (!measure.empty())
|
|
|
|
{
|
|
|
|
m_MeasureNames.push_back(measure);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
loop = false;
|
|
|
|
}
|
|
|
|
++i;
|
|
|
|
} while(loop);
|
|
|
|
}
|
2009-02-10 18:37:48 +00:00
|
|
|
|
2009-09-04 16:37:51 +00:00
|
|
|
m_Color = parser.ReadColor(section, L"FontColor", Color::Black);
|
|
|
|
m_EffectColor = parser.ReadColor(section, L"FontEffectColor", Color::Black);
|
2009-02-10 18:37:48 +00:00
|
|
|
|
2009-09-04 16:37:51 +00:00
|
|
|
m_Prefix = parser.ReadString(section, L"Prefix", L"");
|
|
|
|
m_Postfix = parser.ReadString(section, L"Postfix", L"");
|
|
|
|
m_Text = parser.ReadString(section, L"Text", L"");
|
2009-02-10 18:37:48 +00:00
|
|
|
|
2009-09-04 16:37:51 +00:00
|
|
|
m_Percentual = 0!=parser.ReadInt(section, L"Percentual", 0);
|
|
|
|
m_AutoScale = 0!=parser.ReadInt(section, L"AutoScale", 0);
|
|
|
|
m_ClipString = 0!=parser.ReadInt(section, L"ClipString", 0);
|
2009-02-10 18:37:48 +00:00
|
|
|
|
2010-02-04 07:16:22 +00:00
|
|
|
m_FontSize = (int)parser.ReadFormula(section, L"FontSize", 10);
|
2010-02-08 14:12:47 +00:00
|
|
|
|
|
|
|
if (m_FontSize < 0)
|
|
|
|
{
|
|
|
|
m_FontSize = 10;
|
|
|
|
}
|
|
|
|
|
2009-09-04 16:37:51 +00:00
|
|
|
m_NumOfDecimals = parser.ReadInt(section, L"NumOfDecimals", -1);
|
2009-02-10 18:37:48 +00:00
|
|
|
|
2009-09-04 16:37:51 +00:00
|
|
|
m_Angle = (Gdiplus::REAL)parser.ReadFloat(section, L"Angle", 0.0);
|
2009-02-10 18:37:48 +00:00
|
|
|
|
2010-11-11 20:24:59 +00:00
|
|
|
std::wstring scale = parser.ReadString(section, L"Scale", L"1");
|
2009-02-10 18:37:48 +00:00
|
|
|
|
2010-09-15 12:52:40 +00:00
|
|
|
if (scale.find(L'.') == std::wstring::npos)
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
|
|
|
m_NoDecimals = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_NoDecimals = false;
|
|
|
|
}
|
|
|
|
m_Scale = wcstod(scale.c_str(), NULL);
|
|
|
|
|
2009-09-04 16:37:51 +00:00
|
|
|
m_FontFace = parser.ReadString(section, L"FontFace", L"Arial");
|
2009-02-10 18:37:48 +00:00
|
|
|
|
2010-11-11 20:24:59 +00:00
|
|
|
std::wstring align = parser.ReadString(section, L"StringAlign", L"LEFT");
|
2009-02-10 18:37:48 +00:00
|
|
|
|
|
|
|
if(_wcsicmp(align.c_str(), L"LEFT") == 0)
|
|
|
|
{
|
|
|
|
m_Align = ALIGN_LEFT;
|
|
|
|
}
|
|
|
|
else if(_wcsicmp(align.c_str(), L"RIGHT") == 0)
|
|
|
|
{
|
|
|
|
m_Align = ALIGN_RIGHT;
|
|
|
|
}
|
|
|
|
else if(_wcsicmp(align.c_str(), L"CENTER") == 0)
|
|
|
|
{
|
|
|
|
m_Align = ALIGN_CENTER;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-11-25 15:34:49 +00:00
|
|
|
std::wstring error = L"StringAlign=";
|
|
|
|
error += align;
|
|
|
|
error += L" is not valid in meter [";
|
|
|
|
error += m_Name;
|
|
|
|
error += L"].";
|
|
|
|
throw CError(error, __LINE__, __FILE__);
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
|
|
|
|
2010-11-11 20:24:59 +00:00
|
|
|
std::wstring stringCase = parser.ReadString(section, L"StringCase", L"NONE");
|
2010-03-18 19:48:14 +00:00
|
|
|
|
|
|
|
if(_wcsicmp(stringCase.c_str(), L"NONE") == 0)
|
|
|
|
{
|
|
|
|
m_textCase = TEXTCASE_NONE;
|
|
|
|
}
|
|
|
|
else if(_wcsicmp(stringCase.c_str(), L"UPPER") == 0)
|
|
|
|
{
|
|
|
|
m_textCase = TEXTCASE_UPPER;
|
|
|
|
}
|
|
|
|
else if(_wcsicmp(stringCase.c_str(), L"LOWER") == 0)
|
|
|
|
{
|
|
|
|
m_textCase = TEXTCASE_LOWER;
|
|
|
|
}
|
|
|
|
else if(_wcsicmp(stringCase.c_str(), L"PROPER") == 0)
|
|
|
|
{
|
|
|
|
m_textCase = TEXTCASE_PROPER;
|
|
|
|
}
|
2010-09-21 16:45:29 +00:00
|
|
|
else
|
|
|
|
{
|
2010-11-25 15:34:49 +00:00
|
|
|
std::wstring error = L"StringCase=";
|
|
|
|
error += stringCase;
|
|
|
|
error += L" is not valid in meter [";
|
|
|
|
error += m_Name;
|
|
|
|
error += L"].";
|
|
|
|
throw CError(error, __LINE__, __FILE__);
|
2010-09-21 16:45:29 +00:00
|
|
|
}
|
2010-03-18 19:48:14 +00:00
|
|
|
|
2010-11-11 20:24:59 +00:00
|
|
|
std::wstring style = parser.ReadString(section, L"StringStyle", L"NORMAL");
|
2009-09-04 16:37:51 +00:00
|
|
|
|
2009-02-10 18:37:48 +00:00
|
|
|
if(_wcsicmp(style.c_str(), L"NORMAL") == 0)
|
|
|
|
{
|
|
|
|
m_Style = NORMAL;
|
|
|
|
}
|
|
|
|
else if(_wcsicmp(style.c_str(), L"BOLD") == 0)
|
|
|
|
{
|
|
|
|
m_Style = BOLD;
|
|
|
|
}
|
|
|
|
else if(_wcsicmp(style.c_str(), L"ITALIC") == 0)
|
|
|
|
{
|
|
|
|
m_Style = ITALIC;
|
|
|
|
}
|
|
|
|
else if(_wcsicmp(style.c_str(), L"BOLDITALIC") == 0)
|
|
|
|
{
|
|
|
|
m_Style = BOLDITALIC;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-11-25 15:34:49 +00:00
|
|
|
std::wstring error = L"StringStyle=";
|
|
|
|
error += style;
|
|
|
|
error += L" is not valid in meter [";
|
|
|
|
error += m_Name;
|
|
|
|
error += L"].";
|
|
|
|
throw CError(error, __LINE__, __FILE__);
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
|
|
|
|
2010-11-11 20:24:59 +00:00
|
|
|
std::wstring effect = parser.ReadString(section, L"StringEffect", L"NONE");
|
2009-09-04 16:37:51 +00:00
|
|
|
|
2009-07-29 12:54:05 +00:00
|
|
|
if(_wcsicmp(effect.c_str(), L"NONE") == 0)
|
|
|
|
{
|
|
|
|
m_Effect = EFFECT_NONE;
|
|
|
|
}
|
|
|
|
else if(_wcsicmp(effect.c_str(), L"SHADOW") == 0)
|
|
|
|
{
|
|
|
|
m_Effect = EFFECT_SHADOW;
|
|
|
|
}
|
|
|
|
else if(_wcsicmp(effect.c_str(), L"BORDER") == 0)
|
|
|
|
{
|
|
|
|
m_Effect = EFFECT_BORDER;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-11-25 15:34:49 +00:00
|
|
|
std::wstring error = L"StringEffect=";
|
|
|
|
error += effect;
|
|
|
|
error += L" is not valid in meter [";
|
|
|
|
error += m_Name;
|
|
|
|
error += L"].";
|
|
|
|
throw CError(error, __LINE__, __FILE__);
|
2009-07-29 12:54:05 +00:00
|
|
|
}
|
|
|
|
|
2010-02-09 06:53:34 +00:00
|
|
|
if (-1 != (int)parser.ReadFormula(section, L"W", -1) && -1 != (int)parser.ReadFormula(section, L"H", -1))
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
|
|
|
m_DimensionsDefined = true;
|
|
|
|
}
|
2009-08-27 17:05:10 +00:00
|
|
|
|
|
|
|
if (m_Initialized &&
|
|
|
|
(oldFontFace != m_FontFace ||
|
|
|
|
oldFontSize != m_FontSize ||
|
|
|
|
oldStyle != m_Style))
|
|
|
|
{
|
|
|
|
Initialize(); // Recreate the font
|
|
|
|
}
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
** Update
|
|
|
|
**
|
|
|
|
** Updates the value(s) from the measures.
|
|
|
|
**
|
|
|
|
*/
|
|
|
|
bool CMeterString::Update()
|
|
|
|
{
|
2010-02-08 14:12:47 +00:00
|
|
|
if (CMeter::Update())
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
|
|
|
std::vector<std::wstring> stringValues;
|
|
|
|
|
2010-09-15 12:52:40 +00:00
|
|
|
int decimals = (m_NumOfDecimals != -1) ? m_NumOfDecimals : (m_NoDecimals && (m_Percentual || !m_AutoScale)) ? 0 : 1;
|
2009-02-10 18:37:48 +00:00
|
|
|
|
|
|
|
if (m_Measure) stringValues.push_back(m_Measure->GetStringValue(m_AutoScale, m_Scale, decimals, m_Percentual));
|
|
|
|
|
|
|
|
// Get the values for the other measures
|
2010-03-30 22:37:05 +00:00
|
|
|
for (size_t i = 0; i < m_Measures.size(); ++i)
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
|
|
|
stringValues.push_back(m_Measures[i]->GetStringValue(m_AutoScale, m_Scale, decimals, m_Percentual));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create the text
|
|
|
|
m_String = m_Prefix;
|
|
|
|
if (m_Text.empty())
|
|
|
|
{
|
|
|
|
if (stringValues.size() > 0)
|
|
|
|
{
|
|
|
|
m_String += stringValues[0];
|
|
|
|
}
|
|
|
|
}
|
2010-11-19 07:33:58 +00:00
|
|
|
else if (!stringValues.empty())
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
|
|
|
std::wstring tmpText = m_Text;
|
2010-11-19 07:33:58 +00:00
|
|
|
ReplaceMeasures(stringValues, tmpText);
|
2009-02-10 18:37:48 +00:00
|
|
|
m_String += tmpText;
|
|
|
|
}
|
2010-11-19 07:33:58 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
m_String += m_Text;
|
|
|
|
}
|
2010-11-05 03:25:21 +00:00
|
|
|
if (!m_Postfix.empty()) m_String += m_Postfix;
|
2009-02-10 18:37:48 +00:00
|
|
|
|
2010-03-18 19:48:14 +00:00
|
|
|
switch(m_textCase)
|
|
|
|
{
|
|
|
|
case TEXTCASE_UPPER:
|
2010-11-05 03:25:21 +00:00
|
|
|
StringToUpper(m_String);
|
2010-03-18 19:48:14 +00:00
|
|
|
break;
|
|
|
|
case TEXTCASE_LOWER:
|
2010-11-05 03:25:21 +00:00
|
|
|
StringToLower(m_String);
|
2010-03-18 19:48:14 +00:00
|
|
|
break;
|
|
|
|
case TEXTCASE_PROPER:
|
2010-11-05 03:25:21 +00:00
|
|
|
StringToProper(m_String);
|
2010-03-18 19:48:14 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2009-02-10 18:37:48 +00:00
|
|
|
if (!m_DimensionsDefined)
|
|
|
|
{
|
|
|
|
// Calculate the text size
|
|
|
|
RectF rect;
|
2009-07-27 11:48:57 +00:00
|
|
|
Graphics graphics(m_MeterWindow->GetDoubleBuffer());
|
2010-02-08 14:12:47 +00:00
|
|
|
if (DrawString(graphics, &rect))
|
|
|
|
{
|
|
|
|
m_W = (int)rect.Width;
|
|
|
|
m_H = (int)rect.Height;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_W = 1;
|
|
|
|
m_H = 1;
|
|
|
|
}
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
** Draw
|
|
|
|
**
|
|
|
|
** Draws the meter on the double buffer
|
|
|
|
**
|
|
|
|
*/
|
2009-07-27 11:48:57 +00:00
|
|
|
bool CMeterString::Draw(Graphics& graphics)
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
2010-02-08 14:12:47 +00:00
|
|
|
if(!CMeter::Draw(graphics)) return false;
|
2009-02-10 18:37:48 +00:00
|
|
|
|
2009-07-27 11:48:57 +00:00
|
|
|
return DrawString(graphics, NULL);
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
** DrawString
|
|
|
|
**
|
|
|
|
** Draws the string or calculates it's size
|
|
|
|
**
|
|
|
|
*/
|
2009-07-27 11:48:57 +00:00
|
|
|
bool CMeterString::DrawString(Graphics& graphics, RectF* rect)
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
2010-02-08 14:12:47 +00:00
|
|
|
if (m_Font == NULL) return false;
|
|
|
|
|
2009-02-10 18:37:48 +00:00
|
|
|
StringFormat stringFormat;
|
|
|
|
|
|
|
|
if (m_AntiAlias)
|
|
|
|
{
|
|
|
|
graphics.SetTextRenderingHint(TextRenderingHintAntiAlias);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
graphics.SetTextRenderingHint(TextRenderingHintSingleBitPerPixelGridFit);
|
|
|
|
}
|
|
|
|
|
|
|
|
switch(m_Align)
|
|
|
|
{
|
|
|
|
case ALIGN_CENTER:
|
|
|
|
stringFormat.SetAlignment(StringAlignmentCenter);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ALIGN_RIGHT:
|
|
|
|
stringFormat.SetAlignment(StringAlignmentFar);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ALIGN_LEFT:
|
|
|
|
stringFormat.SetAlignment(StringAlignmentNear);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2010-11-05 03:25:21 +00:00
|
|
|
if (m_ClipString)
|
|
|
|
{
|
|
|
|
stringFormat.SetTrimming(StringTrimmingEllipsisCharacter);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
stringFormat.SetTrimming(StringTrimmingNone);
|
|
|
|
stringFormat.SetFormatFlags(StringFormatFlagsNoClip | StringFormatFlagsNoWrap);
|
|
|
|
}
|
|
|
|
|
|
|
|
CharacterRange range(0, (int)m_String.length());
|
|
|
|
stringFormat.SetMeasurableCharacterRanges(1, &range);
|
|
|
|
|
2009-02-14 10:11:28 +00:00
|
|
|
REAL x = (REAL)GetX();
|
|
|
|
REAL y = (REAL)GetY();
|
2009-02-10 18:37:48 +00:00
|
|
|
|
|
|
|
if (rect)
|
|
|
|
{
|
|
|
|
PointF pos(x, y);
|
2010-11-05 03:25:21 +00:00
|
|
|
graphics.MeasureString(m_String.c_str(), (int)m_String.length(), m_Font, pos, &stringFormat, rect);
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
RectF rc((REAL)x, (REAL)y, (REAL)m_W, (REAL)m_H);
|
|
|
|
|
2010-11-05 03:25:21 +00:00
|
|
|
if (m_Angle != 0.0f)
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
2010-11-05 03:25:21 +00:00
|
|
|
REAL angle = m_Angle * 180.0f / 3.14159265f; // Convert to degrees
|
|
|
|
graphics.TranslateTransform((Gdiplus::REAL)CMeter::GetX(), y);
|
|
|
|
graphics.RotateTransform(angle);
|
|
|
|
graphics.TranslateTransform(-(Gdiplus::REAL)CMeter::GetX(), -y);
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
|
|
|
|
2010-11-11 20:24:59 +00:00
|
|
|
if (m_Effect == EFFECT_SHADOW)
|
2009-07-29 12:54:05 +00:00
|
|
|
{
|
2010-11-11 20:24:59 +00:00
|
|
|
SolidBrush solidBrush(m_EffectColor);
|
|
|
|
RectF rcEffect(rc);
|
|
|
|
rcEffect.Offset(1, 1);
|
|
|
|
graphics.DrawString(m_String.c_str(), (int)m_String.length(), m_Font, rcEffect, &stringFormat, &solidBrush);
|
|
|
|
}
|
|
|
|
else if (m_Effect == EFFECT_BORDER)
|
|
|
|
{
|
|
|
|
SolidBrush solidBrush(m_EffectColor);
|
|
|
|
RectF rcEffect(rc);
|
|
|
|
rcEffect.Offset(0, 1);
|
|
|
|
graphics.DrawString(m_String.c_str(), (int)m_String.length(), m_Font, rcEffect, &stringFormat, &solidBrush);
|
|
|
|
rcEffect.Offset(1, -1);
|
|
|
|
graphics.DrawString(m_String.c_str(), (int)m_String.length(), m_Font, rcEffect, &stringFormat, &solidBrush);
|
|
|
|
rcEffect.Offset(-1, -1);
|
|
|
|
graphics.DrawString(m_String.c_str(), (int)m_String.length(), m_Font, rcEffect, &stringFormat, &solidBrush);
|
|
|
|
rcEffect.Offset(-1, 1);
|
|
|
|
graphics.DrawString(m_String.c_str(), (int)m_String.length(), m_Font, rcEffect, &stringFormat, &solidBrush);
|
2009-07-29 12:54:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SolidBrush solidBrush(m_Color);
|
2010-11-05 03:25:21 +00:00
|
|
|
graphics.DrawString(m_String.c_str(), (int)m_String.length(), m_Font, rc, &stringFormat, &solidBrush);
|
2009-07-27 11:48:57 +00:00
|
|
|
|
2010-11-05 03:25:21 +00:00
|
|
|
if (m_Angle != 0.0f)
|
|
|
|
{
|
|
|
|
graphics.ResetTransform();
|
|
|
|
}
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
** BindMeasure
|
|
|
|
**
|
|
|
|
** Overridden method. The string meters need not to be bound on anything
|
|
|
|
**
|
|
|
|
*/
|
2010-11-19 07:33:58 +00:00
|
|
|
void CMeterString::BindMeasure(const std::list<CMeasure*>& measures)
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
|
|
|
if (m_MeasureName.empty()) return; // Allow NULL measure binding
|
|
|
|
|
|
|
|
CMeter::BindMeasure(measures);
|
|
|
|
|
2010-03-30 22:37:05 +00:00
|
|
|
std::vector<std::wstring>::const_iterator j = m_MeasureNames.begin();
|
|
|
|
for (; j != m_MeasureNames.end(); ++j)
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
|
|
|
// Go through the list and check it there is a secondary measures for us
|
2010-03-30 22:37:05 +00:00
|
|
|
std::list<CMeasure*>::const_iterator i = measures.begin();
|
|
|
|
for( ; i != measures.end(); ++i)
|
2009-02-10 18:37:48 +00:00
|
|
|
{
|
|
|
|
if(_wcsicmp((*i)->GetName(), (*j).c_str()) == 0)
|
|
|
|
{
|
|
|
|
m_Measures.push_back(*i);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (i == measures.end())
|
|
|
|
{
|
2010-11-25 15:34:49 +00:00
|
|
|
std::wstring error = L"The meter [";
|
|
|
|
error += m_Name;
|
|
|
|
error += L"] cannot be bound with [";
|
|
|
|
error += (*j);
|
|
|
|
error += L"]!";
|
|
|
|
throw CError(error, __LINE__, __FILE__);
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
|
|
|
}
|
2010-09-10 17:29:30 +00:00
|
|
|
CMeter::SetAllMeasures(m_Measures);
|
2009-02-10 18:37:48 +00:00
|
|
|
}
|
2009-10-07 16:45:14 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
** FreeFontCache
|
|
|
|
**
|
|
|
|
** Static function which frees the font cache.
|
|
|
|
**
|
|
|
|
*/
|
|
|
|
void CMeterString::FreeFontCache()
|
|
|
|
{
|
|
|
|
std::map<std::wstring, Gdiplus::FontFamily*>::iterator iter = c_FontFamilies.begin();
|
2010-03-30 22:37:05 +00:00
|
|
|
for ( ; iter != c_FontFamilies.end(); ++iter)
|
2009-10-07 16:45:14 +00:00
|
|
|
{
|
|
|
|
delete (*iter).second;
|
|
|
|
}
|
|
|
|
c_FontFamilies.clear();
|
|
|
|
|
|
|
|
std::map<std::wstring, Gdiplus::Font*>::iterator iter2 = c_Fonts.begin();
|
2010-03-30 22:37:05 +00:00
|
|
|
for ( ; iter2 != c_Fonts.end(); ++iter2)
|
2009-10-07 16:45:14 +00:00
|
|
|
{
|
|
|
|
delete (*iter2).second;
|
|
|
|
}
|
|
|
|
c_Fonts.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
** FontPropertiesToString
|
|
|
|
**
|
|
|
|
** Static helper to convert font properties to a string so it can be used as a key for the cache map.
|
|
|
|
**
|
|
|
|
*/
|
2009-10-11 13:03:20 +00:00
|
|
|
std::wstring CMeterString::FontPropertiesToString(FontFamily* fontFamily, REAL size, FontStyle style)
|
2009-10-07 16:45:14 +00:00
|
|
|
{
|
|
|
|
std::wstringstream stream;
|
|
|
|
stream << size << L"-" << (int)style;
|
2009-10-11 13:03:20 +00:00
|
|
|
|
|
|
|
if (fontFamily)
|
|
|
|
{
|
|
|
|
WCHAR familyName[LF_FACESIZE];
|
|
|
|
if (Ok == fontFamily->GetFamilyName(familyName))
|
|
|
|
{
|
|
|
|
return std::wstring(familyName) + L"-" + stream.str();
|
|
|
|
}
|
|
|
|
}
|
2009-10-07 16:45:14 +00:00
|
|
|
return stream.str();
|
|
|
|
}
|
|
|
|
|
2010-03-20 19:40:30 +00:00
|
|
|
/*
|
|
|
|
** EnumerateInstalledFontFamilies
|
|
|
|
**
|
|
|
|
** Static helper to log all installed font families.
|
|
|
|
**
|
|
|
|
*/
|
|
|
|
void CMeterString::EnumerateInstalledFontFamilies()
|
|
|
|
{
|
|
|
|
INT fontCount;
|
|
|
|
InstalledFontCollection fontCollection;
|
|
|
|
|
|
|
|
if (Ok == fontCollection.GetLastStatus())
|
|
|
|
{
|
|
|
|
fontCount = fontCollection.GetFamilyCount();
|
|
|
|
if (fontCount > 0)
|
|
|
|
{
|
|
|
|
INT fontFound;
|
|
|
|
|
|
|
|
FontFamily* fontFamilies = new FontFamily[fontCount];
|
|
|
|
|
|
|
|
if (Ok == fontCollection.GetFamilies(fontCount, fontFamilies, &fontFound))
|
|
|
|
{
|
|
|
|
std::wstring fonts;
|
2010-03-30 22:37:05 +00:00
|
|
|
for (INT i = 0; i < fontCount; ++i)
|
2010-03-20 19:40:30 +00:00
|
|
|
{
|
|
|
|
WCHAR familyName[LF_FACESIZE];
|
|
|
|
if (Ok == fontFamilies[i].GetFamilyName(familyName))
|
|
|
|
{
|
|
|
|
fonts += familyName;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fonts += L"***";
|
|
|
|
}
|
|
|
|
fonts += L", ";
|
|
|
|
}
|
2010-10-31 20:13:32 +00:00
|
|
|
LSLog(LOG_DEBUG, APPNAME, fonts.c_str());
|
2010-03-20 19:40:30 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-10-31 20:13:32 +00:00
|
|
|
LSLog(LOG_DEBUG, APPNAME, L"Failed to enumerate installed font families: GetFamilies() failed.");
|
2010-03-20 19:40:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
delete [] fontFamilies;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-10-31 20:13:32 +00:00
|
|
|
LSLog(LOG_DEBUG, APPNAME, L"There are no installed font families!");
|
2010-03-20 19:40:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-10-31 20:13:32 +00:00
|
|
|
LSLog(LOG_DEBUG, APPNAME, L"Failed to enumerate installed font families: InstalledFontCollection() failed.");
|
2010-03-20 19:40:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-03-18 19:48:14 +00:00
|
|
|
// EOF
|