Adds new [Meter:] and [Measure:] functionality

This commit is contained in:
Brian 2012-08-01 13:52:50 -04:00 committed by jsmorley
parent 746bd059fd
commit 06f625c91c
3 changed files with 246 additions and 36 deletions

View File

@ -23,6 +23,7 @@
#include "Rainmeter.h"
#include "System.h"
#include "Measure.h"
#include "Meter.h"
#include "resource.h"
extern CRainmeter* Rainmeter;
@ -80,6 +81,8 @@ void CConfigParser::Initialize(const std::wstring& filename, CMeterWindow* meter
m_FoundSections.clear();
m_ListVariables.clear();
m_SectionInsertPos = m_Sections.end();
m_MeterWindow = meterWindow;
}
void CConfigParser::SetBuiltInVariables(const std::wstring& filename, const std::wstring* resourcePath, CMeterWindow* meterWindow)
@ -188,6 +191,188 @@ bool CConfigParser::GetVariable(const std::wstring& strVariable, std::wstring& s
return false;
}
/*
** Meter/Measure psuedo-variables. [MeasureName:] returns numeric value of measure.
** ie. [MeterName:X], [MeasureName:], [MeasureName:%, 2], [MeasureName:3]
*/
bool CConfigParser::GetSectionVariables(const std::wstring& strVariable, std::wstring& strValue)
{
WCHAR buffer[MAX_LINE_LENGTH];
std::vector<std::wstring> strToken = Tokenize(strVariable, L":");
if (strToken.size() == 1 && !m_Measures.empty())
{
// [MeasureName:] returns number value
CMeasure* measure = m_MeterWindow->GetMeasure(strToken[0]);
if (measure)
{
_snwprintf_s(buffer, _TRUNCATE, L"%lli", (LONGLONG)measure->GetValue());
strValue = buffer;
return true;
}
}
else if (strToken.size() == 2)
{
std::wstring args = strToken[1];
// strip off leading and trailing spaces
size_t startPos = args.find_first_not_of(L" \t");
size_t endPos = args.find_last_not_of(L" \t");
if (std::wstring::npos != startPos || std::wstring::npos != endPos)
args = args.substr(startPos, endPos - startPos + 1);
// Check meters first
// Format: [MeterName:X]
CMeter* meter = m_MeterWindow->GetMeter(strToken[0]);
if (meter)
{
WCHAR buffer[MAX_LINE_LENGTH];
if (_wcsicmp(args.c_str(), L"X") == 0)
{
_itow_s(meter->GetX(), buffer, 10);
}
else if (_wcsicmp(args.c_str(), L"Y") == 0)
{
_itow_s(meter->GetY(), buffer, 10);
}
else if (_wcsicmp(args.c_str(), L"W") == 0)
{
_itow_s(meter->GetW(), buffer, 10);
}
else if (_wcsicmp(args.c_str(), L"H") == 0)
{
_itow_s(meter->GetH(), buffer, 10);
}
else
{
return false;
}
strValue = buffer;
return true;
}
// Check measures
// Format: [MeasureName:/1000,2] [MeasureName:%,2] [MeasureName:10]
CMeasure* measure = m_MeterWindow->GetMeasure(strToken[0]);
if (measure)
{
double scale = 1.0;
int numOfDecimals = -1;
bool foundDecimal = false;
bool percentual = false;
WCHAR format[32];
std::vector<std::wstring> measureOptions = Tokenize(args, L",");
if (_wcsicmp(measureOptions[0].c_str(), L"%") == 0) // Percentual
{
percentual = true;
}
else if (_wcsicmp(measureOptions[0].substr(0,1).c_str(), L"/") == 0) // Scale
{
std::wstring tempScale = measureOptions[0].substr(1, measureOptions[0].length() - 1);
// strip off leading and trailing spaces
size_t startPos = tempScale.find_first_not_of(L" \t");
size_t endPos = tempScale.find_last_not_of(L" \t");
if ((std::wstring::npos != startPos) || (std::wstring::npos != endPos))
{
tempScale = tempScale.substr(startPos, endPos - startPos + 1);
}
scale = _wtoi(tempScale.c_str());
// _wtoi returns 0 if there is an error.
if (scale == 0 && tempScale != L"0")
scale = 1.0;
}
else // NumOfDecimals
{
std::wstring tempStr = measureOptions[0];
// strip off leading and trailing spaces
size_t startPos = tempStr.find_first_not_of(L" \t");
size_t endPos = tempStr.find_last_not_of(L" \t");
if ((std::wstring::npos != startPos) || (std::wstring::npos != endPos))
{
tempStr = tempStr.substr(startPos, endPos - startPos + 1);
}
numOfDecimals = _wtoi(tempStr.c_str());
// _wtoi returns 0 if there is an error.
if ((numOfDecimals == 0 && tempStr != L"0") || numOfDecimals < -1)
numOfDecimals = -1;
foundDecimal = true;
}
// NumOfDecimals (for Percentual and Scale)
if (measureOptions.size() == 2 && !foundDecimal)
{
std::wstring tempStr = measureOptions[1];
// strip off leading and trailing spaces
size_t startPos = tempStr.find_first_not_of(L" \t");
size_t endPos = tempStr.find_last_not_of(L" \t");
if ((std::wstring::npos != startPos) || (std::wstring::npos != endPos))
{
tempStr = tempStr.substr(startPos, endPos - startPos + 1);
}
numOfDecimals = _wtoi(tempStr.c_str());
// _wtoi returns 0 if there is an error.
if ((numOfDecimals == 0 && tempStr != L"0") || numOfDecimals < -1)
numOfDecimals = -1;
}
if (percentual)
{
double val = 100.0 * measure->GetRelativeValue();
if (numOfDecimals <= 0)
{
_itow_s((int)val, buffer, 10);
}
else
{
_snwprintf_s(format, _TRUNCATE, L"%%.%if", numOfDecimals);
_snwprintf_s(buffer, _TRUNCATE, format, val);
}
}
else
{
double val = measure->GetValue() / scale;
if (numOfDecimals == 0)
{
val += (val >= 0) ? 0.5 : -0.5;
_snwprintf_s(buffer, _TRUNCATE, L"%lli", (LONGLONG)val);
}
else if (numOfDecimals < 0)
{
int len = _snwprintf_s(buffer, _TRUNCATE, L"%.15f", val);
measure->RemoveTrailingZero(buffer, len);
}
else
{
_snwprintf_s(format, _TRUNCATE, L"%%.%if", numOfDecimals);
_snwprintf_s(buffer, _TRUNCATE, format, val);
}
}
strValue = buffer;
return true;
}
}
return false;
}
void CConfigParser::ResetMonitorVariables(CMeterWindow* meterWindow)
{
// Set the SCREENAREA/WORKAREA variables
@ -498,40 +683,47 @@ bool CConfigParser::ReplaceMeasures(std::wstring& result)
{
bool replaced = false;
// Check for measures ([Measure])
if (!m_Measures.empty())
{
size_t start = 0, end, next;
bool loop = true;
size_t start = 0, end, next;
bool loop = true;
do
do
{
start = result.find(L'[', start);
if (start != std::wstring::npos)
{
start = result.find(L'[', start);
if (start != std::wstring::npos)
size_t si = start + 1;
end = result.find(L']', si);
if (end != std::wstring::npos)
{
size_t si = start + 1;
end = result.find(L']', si);
if (end != std::wstring::npos)
next = result.find(L'[', si);
if (next == std::wstring::npos || end < next)
{
next = result.find(L'[', si);
if (next == std::wstring::npos || end < next)
size_t ei = end - 1;
if (si != ei && result[si] == L'*' && result[ei] == L'*')
{
size_t ei = end - 1;
if (si != ei && result[si] == L'*' && result[ei] == L'*')
result.erase(ei, 1);
result.erase(si, 1);
start = ei;
}
else
{
std::wstring var = result.substr(si, end - si);
CMeasure* measure = GetMeasure(var);
if (measure)
{
result.erase(ei, 1);
result.erase(si, 1);
start = ei;
const std::wstring& value = measure->GetStringValue(AUTOSCALE_OFF, 1, -1, false);
// Measure found, replace it with the value
result.replace(start, end - start + 1, value);
start += value.length();
replaced = true;
}
else
{
std::wstring var = result.substr(si, end - si);
CMeasure* measure = GetMeasure(var);
if (measure)
std::wstring value;
if (GetSectionVariables(var, value))
{
const std::wstring& value = measure->GetStringValue(AUTOSCALE_OFF, 1, -1, false);
// Measure found, replace it with the value
result.replace(start, end - start + 1, value);
start += value.length();
@ -543,14 +735,10 @@ bool CConfigParser::ReplaceMeasures(std::wstring& result)
}
}
}
else
{
start = next;
}
}
else
{
loop = false;
start = next;
}
}
else
@ -558,8 +746,12 @@ bool CConfigParser::ReplaceMeasures(std::wstring& result)
loop = false;
}
}
while (loop);
else
{
loop = false;
}
}
while (loop);
return replaced;
}

View File

@ -33,6 +33,7 @@
class CRainmeter;
class CMeterWindow;
class CMeasure;
class CMeter;
class CConfigParser
{
@ -109,6 +110,8 @@ private:
void SetAutoSelectedMonitorVariables(CMeterWindow* meterWindow);
bool GetSectionVariables(const std::wstring& strVariable, std::wstring& strValue);
static void SetVariable(std::unordered_map<std::wstring, std::wstring>& variables, const std::wstring& strVariable, const std::wstring& strValue);
static void SetVariable(std::unordered_map<std::wstring, std::wstring>& variables, const WCHAR* strVariable, const WCHAR* strValue);
@ -140,6 +143,8 @@ private:
std::unordered_map<std::wstring, std::wstring> m_BuiltInVariables;
std::unordered_map<std::wstring, std::wstring> m_Variables;
CMeterWindow* m_MeterWindow;
static std::unordered_map<std::wstring, std::wstring> c_MonitorVariables;
};

View File

@ -42,8 +42,8 @@ extern CRainmeter* Rainmeter;
CMeter::CMeter(CMeterWindow* meterWindow, const WCHAR* name) : m_MeterWindow(meterWindow), m_Name(name),
m_X(),
m_Y(),
m_W(),
m_H(),
m_W(0),
m_H(0),
m_Hidden(false),
m_WDefined(false),
m_HDefined(false),
@ -291,11 +291,24 @@ void CMeter::ReadOptions(CConfigParser& parser, const WCHAR* section)
m_RelativeY = POSITION_ABSOLUTE;
}
m_W = parser.ReadInt(section, L"W", 1);
m_WDefined = parser.GetLastValueDefined();
bool oldWDefined = m_WDefined;
bool oldHDefined = m_HDefined;
m_H = parser.ReadInt(section, L"H", 1);
m_W = parser.ReadInt(section, L"W", m_W);
m_WDefined = parser.GetLastValueDefined();
if (!m_WDefined && oldWDefined)
{
m_W = 0;
parser.SetValue(section, L"W", L"0");
}
m_H = parser.ReadInt(section, L"H", m_H);
m_HDefined = parser.GetLastValueDefined();
if (!m_HDefined && oldHDefined)
{
m_H = 0;
parser.SetValue(section, L"H", L"0");
}
bool oldHidden = m_Hidden;
m_Hidden = 0!=parser.ReadInt(section, L"Hidden", 0);