IfActions: Read condition options after measure value is changed to properly support section variables

This commit is contained in:
Birunthan Mohanathas 2013-11-05 20:43:04 +02:00
parent cf86d365ad
commit b62fca59d0
5 changed files with 32 additions and 90 deletions

View File

@ -34,7 +34,6 @@ IfActions::IfActions(MeterWindow* meterWindow, Measure* measure) :
m_EqualCommitted(false), m_EqualCommitted(false),
m_Conditions(), m_Conditions(),
m_HasConditions(false), m_HasConditions(false),
m_HasDynamicVariables(false),
m_MeterWindow(meterWindow), m_MeterWindow(meterWindow),
m_Measure(measure) m_Measure(measure)
{ {
@ -46,9 +45,6 @@ IfActions::~IfActions()
void IfActions::ReadOptions(ConfigParser& parser, const WCHAR* section) void IfActions::ReadOptions(ConfigParser& parser, const WCHAR* section)
{ {
m_Parser = &parser;
m_HasDynamicVariables = m_Measure->HasDynamicVariables();
m_AboveAction = parser.ReadString(section, L"IfAboveAction", L"", false); m_AboveAction = parser.ReadString(section, L"IfAboveAction", L"", false);
m_AboveValue = parser.ReadFloat(section, L"IfAboveValue", 0.0f); m_AboveValue = parser.ReadFloat(section, L"IfAboveValue", 0.0f);
@ -57,25 +53,14 @@ void IfActions::ReadOptions(ConfigParser& parser, const WCHAR* section)
m_EqualAction = parser.ReadString(section, L"IfEqualAction", L"", false); m_EqualAction = parser.ReadString(section, L"IfEqualAction", L"", false);
m_EqualValue = (int64_t)parser.ReadFloat(section, L"IfEqualValue", 0.0f); m_EqualValue = (int64_t)parser.ReadFloat(section, L"IfEqualValue", 0.0f);
}
void IfActions::ReadConditionOptions(ConfigParser& parser, const WCHAR* section)
{
m_HasConditions = false; m_HasConditions = false;
bool hasSelf = false; std::wstring condition = parser.ReadString(section, L"IfCondition", L"");
std::wstring condition;
if (m_HasDynamicVariables)
{
condition = parser.GetValue(section, L"IfCondition", L"");
if (!condition.empty() && ReplaceSelf(condition, section, L"[]", L"{}"))
{
parser.SetValue(section, L"IfCondition", condition);
hasSelf = true;
}
}
condition = parser.ReadString(section, L"IfCondition", L"");
std::wstring tAction = parser.ReadString(section, L"IfTrueAction", L"", false); std::wstring tAction = parser.ReadString(section, L"IfTrueAction", L"", false);
std::wstring fAction = parser.ReadString(section, L"IfFalseAction", L"", false); std::wstring fAction = parser.ReadString(section, L"IfFalseAction", L"", false);
if (!condition.empty() && (!tAction.empty() || !fAction.empty())) if (!condition.empty() && (!tAction.empty() || !fAction.empty()))
{ {
m_HasConditions = true; m_HasConditions = true;
@ -89,11 +74,9 @@ void IfActions::ReadOptions(ConfigParser& parser, const WCHAR* section)
} }
else else
{ {
m_Conditions.emplace_back(condition, tAction, fAction, hasSelf); m_Conditions.emplace_back(condition, tAction, fAction);
} }
hasSelf = false;
// Check for IfCondition2/IfTrueAction2/IfFalseAction2 ... etc. // Check for IfCondition2/IfTrueAction2/IfFalseAction2 ... etc.
std::wstring key = L"IfTrueAction" + std::to_wstring(++i); std::wstring key = L"IfTrueAction" + std::to_wstring(++i);
tAction = parser.ReadString(section, key.c_str(), L"", false); tAction = parser.ReadString(section, key.c_str(), L"", false);
@ -101,15 +84,6 @@ void IfActions::ReadOptions(ConfigParser& parser, const WCHAR* section)
fAction = parser.ReadString(section, key.c_str(), L"", false); fAction = parser.ReadString(section, key.c_str(), L"", false);
key = L"IfCondition" + std::to_wstring(i); key = L"IfCondition" + std::to_wstring(i);
if (m_HasDynamicVariables)
{
condition = parser.GetValue(section, key, L"");
if (!condition.empty() && ReplaceSelf(condition, section, L"[]", L"{}"))
{
parser.SetValue(section, key, condition);
hasSelf = true;
}
}
condition = parser.ReadString(section, key.c_str(), L""); condition = parser.ReadString(section, key.c_str(), L"");
} }
@ -175,13 +149,6 @@ void IfActions::DoIfActions(double& value)
++i; ++i;
if (!item.condition.empty() && (!item.tAction.empty() || !item.fAction.empty())) if (!item.condition.empty() && (!item.tAction.empty() || !item.fAction.empty()))
{ {
//Replace measures (need it here in case the if actions reference themselves)
if (m_HasDynamicVariables && item.containsSelf)
{
ReplaceSelf(item.condition, m_Measure->GetName(), L"{}", L"[]");
m_Parser->ReplaceMeasures(item.condition);
}
double result = 0.0f; double result = 0.0f;
const WCHAR* errMsg = MathParser::Parse(item.condition.c_str(), &result, m_Measure->GetCurrentMeasureValue, m_Measure); const WCHAR* errMsg = MathParser::Parse(item.condition.c_str(), &result, m_Measure->GetCurrentMeasureValue, m_Measure);
if (errMsg != nullptr) if (errMsg != nullptr)
@ -235,36 +202,3 @@ void IfActions::SetState(double value)
m_BelowCommitted = false; m_BelowCommitted = false;
} }
} }
/*
** Replaces a [MeasureName] with {MeasureName} and vice-versa.
** This is needed to support IfConditions referencing themselves.
*/
bool IfActions::ReplaceSelf(std::wstring& condition, const WCHAR* section,
const std::wstring sBracket, const std::wstring eBracket)
{
bool replaced = false;
std::wstring measureName = sBracket;
measureName.replace(1, 1, section);
size_t pos = 0;
while ((pos = condition.find(measureName, pos)) != std::wstring::npos)
{
condition.replace(pos, 1, eBracket.substr(0, 1));
pos = condition.find(sBracket.substr(1, 1), pos);
if (pos != std::wstring::npos)
{
condition.replace(pos, 1, eBracket.substr(1, 1));
++pos;
replaced = true;
}
else
{
replaced = false; // No closing bracket found
break;
}
}
return replaced;
}

View File

@ -30,11 +30,10 @@ class MeterWindow;
class IfCondition class IfCondition
{ {
public: public:
IfCondition(std::wstring value, std::wstring trueAction, std::wstring falseAction, bool hasSelf = false) : IfCondition(std::wstring value, std::wstring trueAction, std::wstring falseAction) :
condition(), condition(),
tAction(), tAction(),
fAction(), fAction(),
containsSelf(hasSelf),
parseError(false) parseError(false)
{ {
Set(value, trueAction, falseAction); Set(value, trueAction, falseAction);
@ -51,7 +50,6 @@ public:
std::wstring tAction; // IfTrueAction std::wstring tAction; // IfTrueAction
std::wstring fAction; // IfFalseAction std::wstring fAction; // IfFalseAction
bool parseError; bool parseError;
bool containsSelf;
}; };
class IfActions class IfActions
@ -61,13 +59,11 @@ public:
~IfActions(); ~IfActions();
void ReadOptions(ConfigParser& parser, const WCHAR* section); void ReadOptions(ConfigParser& parser, const WCHAR* section);
void ReadConditionOptions(ConfigParser& parser, const WCHAR* section);
void DoIfActions(double& value); void DoIfActions(double& value);
void SetState(double value = 0.0f); void SetState(double value = 0.0f);
private: private:
bool ReplaceSelf(std::wstring& condition, const WCHAR* section,
const std::wstring sBracket, const std::wstring eBracket);
double m_AboveValue; double m_AboveValue;
double m_BelowValue; double m_BelowValue;
int64_t m_EqualValue; int64_t m_EqualValue;
@ -83,9 +79,6 @@ private:
std::vector<IfCondition> m_Conditions; std::vector<IfCondition> m_Conditions;
bool m_HasConditions; bool m_HasConditions;
bool m_HasDynamicVariables;
ConfigParser* m_Parser;
MeterWindow* m_MeterWindow; MeterWindow* m_MeterWindow;
Measure* m_Measure; Measure* m_Measure;
}; };

View File

@ -131,6 +131,13 @@ void Measure::ReadOptions(ConfigParser& parser, const WCHAR* section)
m_IfActions.ReadOptions(parser, section); m_IfActions.ReadOptions(parser, section);
// The first time around, we read the conditions here. Subsequent rereads will be done in
// Update() if needed.
if (!m_Initialized)
{
m_IfActions.ReadConditionOptions(parser, section);
}
m_OnChangeAction = parser.ReadString(section, L"OnChangeAction", L"", false); m_OnChangeAction = parser.ReadString(section, L"OnChangeAction", L"", false);
m_AverageSize = parser.ReadUInt(section, L"AverageSize", 0); m_AverageSize = parser.ReadUInt(section, L"AverageSize", 0);
@ -437,8 +444,13 @@ std::wstring Measure::ExtractWord(std::wstring& buffer)
return ret; return ret;
} }
bool Measure::Update() bool Measure::Update(bool rereadOptions)
{ {
if (rereadOptions)
{
ReadOptions(m_MeterWindow->GetParser());
}
// Don't do anything if paused // Don't do anything if paused
if (m_Paused) return false; if (m_Paused) return false;
@ -497,6 +509,13 @@ bool Measure::Update()
m_ValueAssigned = true; m_ValueAssigned = true;
// For the conditional options to work with the current measure value when using
// [MeasureName], we need to read the options after m_Value has been changed.
if (rereadOptions)
{
m_IfActions.ReadConditionOptions(m_MeterWindow->GetParser(), GetName());
}
if (m_MeterWindow) if (m_MeterWindow)
{ {
m_IfActions.DoIfActions(m_Value); m_IfActions.DoIfActions(m_Value);

View File

@ -61,7 +61,7 @@ public:
void ReadOptions(ConfigParser& parser) { ReadOptions(parser, GetName()); } void ReadOptions(ConfigParser& parser) { ReadOptions(parser, GetName()); }
virtual void Initialize(); virtual void Initialize();
bool Update(); bool Update(bool rereadOptions = false);
void Disable(); void Disable();
void Enable(); void Enable();

View File

@ -2675,13 +2675,9 @@ bool MeterWindow::UpdateMeasure(Measure* measure, bool force)
int updateDivider = measure->GetUpdateDivider(); int updateDivider = measure->GetUpdateDivider();
if (updateDivider >= 0 || force) if (updateDivider >= 0 || force)
{ {
if (measure->HasDynamicVariables() && const bool rereadOptions =
(measure->GetUpdateCounter() + 1) >= updateDivider) measure->HasDynamicVariables() && (measure->GetUpdateCounter() + 1) >= updateDivider;
{ bUpdate = measure->Update(rereadOptions);
measure->ReadOptions(m_Parser);
}
bUpdate = measure->Update();
} }
return bUpdate; return bUpdate;