From b62fca59d0caf5c92dcdc4af02c7426fef33105b Mon Sep 17 00:00:00 2001 From: Birunthan Mohanathas Date: Tue, 5 Nov 2013 20:43:04 +0200 Subject: [PATCH] IfActions: Read condition options after measure value is changed to properly support section variables --- Library/IfActions.cpp | 78 ++++------------------------------------- Library/IfActions.h | 11 ++---- Library/Measure.cpp | 21 ++++++++++- Library/Measure.h | 2 +- Library/MeterWindow.cpp | 10 ++---- 5 files changed, 32 insertions(+), 90 deletions(-) diff --git a/Library/IfActions.cpp b/Library/IfActions.cpp index 3a864f9b..6941a0f9 100644 --- a/Library/IfActions.cpp +++ b/Library/IfActions.cpp @@ -34,7 +34,6 @@ IfActions::IfActions(MeterWindow* meterWindow, Measure* measure) : m_EqualCommitted(false), m_Conditions(), m_HasConditions(false), - m_HasDynamicVariables(false), m_MeterWindow(meterWindow), m_Measure(measure) { @@ -46,9 +45,6 @@ IfActions::~IfActions() 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_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_EqualValue = (int64_t)parser.ReadFloat(section, L"IfEqualValue", 0.0f); - +} + +void IfActions::ReadConditionOptions(ConfigParser& parser, const WCHAR* section) +{ m_HasConditions = false; - bool hasSelf = false; - 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 condition = parser.ReadString(section, L"IfCondition", L""); std::wstring tAction = parser.ReadString(section, L"IfTrueAction", L"", false); std::wstring fAction = parser.ReadString(section, L"IfFalseAction", L"", false); - if (!condition.empty() && (!tAction.empty() || !fAction.empty())) { m_HasConditions = true; @@ -89,11 +74,9 @@ void IfActions::ReadOptions(ConfigParser& parser, const WCHAR* section) } else { - m_Conditions.emplace_back(condition, tAction, fAction, hasSelf); + m_Conditions.emplace_back(condition, tAction, fAction); } - hasSelf = false; - // Check for IfCondition2/IfTrueAction2/IfFalseAction2 ... etc. std::wstring key = L"IfTrueAction" + std::to_wstring(++i); 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); 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""); } @@ -175,13 +149,6 @@ void IfActions::DoIfActions(double& value) ++i; 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; const WCHAR* errMsg = MathParser::Parse(item.condition.c_str(), &result, m_Measure->GetCurrentMeasureValue, m_Measure); if (errMsg != nullptr) @@ -235,36 +202,3 @@ void IfActions::SetState(double value) 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; -} diff --git a/Library/IfActions.h b/Library/IfActions.h index 915a938d..7fb18a0a 100644 --- a/Library/IfActions.h +++ b/Library/IfActions.h @@ -30,11 +30,10 @@ class MeterWindow; class IfCondition { 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(), tAction(), fAction(), - containsSelf(hasSelf), parseError(false) { Set(value, trueAction, falseAction); @@ -51,7 +50,6 @@ public: std::wstring tAction; // IfTrueAction std::wstring fAction; // IfFalseAction bool parseError; - bool containsSelf; }; class IfActions @@ -61,13 +59,11 @@ public: ~IfActions(); void ReadOptions(ConfigParser& parser, const WCHAR* section); + void ReadConditionOptions(ConfigParser& parser, const WCHAR* section); void DoIfActions(double& value); void SetState(double value = 0.0f); private: - bool ReplaceSelf(std::wstring& condition, const WCHAR* section, - const std::wstring sBracket, const std::wstring eBracket); - double m_AboveValue; double m_BelowValue; int64_t m_EqualValue; @@ -83,9 +79,6 @@ private: std::vector m_Conditions; bool m_HasConditions; - bool m_HasDynamicVariables; - - ConfigParser* m_Parser; MeterWindow* m_MeterWindow; Measure* m_Measure; }; diff --git a/Library/Measure.cpp b/Library/Measure.cpp index 1f9cf1fe..1aeee8b5 100644 --- a/Library/Measure.cpp +++ b/Library/Measure.cpp @@ -131,6 +131,13 @@ void Measure::ReadOptions(ConfigParser& parser, const WCHAR* 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_AverageSize = parser.ReadUInt(section, L"AverageSize", 0); @@ -437,8 +444,13 @@ std::wstring Measure::ExtractWord(std::wstring& buffer) return ret; } -bool Measure::Update() +bool Measure::Update(bool rereadOptions) { + if (rereadOptions) + { + ReadOptions(m_MeterWindow->GetParser()); + } + // Don't do anything if paused if (m_Paused) return false; @@ -497,6 +509,13 @@ bool Measure::Update() 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) { m_IfActions.DoIfActions(m_Value); diff --git a/Library/Measure.h b/Library/Measure.h index b4acf766..86aff4c5 100644 --- a/Library/Measure.h +++ b/Library/Measure.h @@ -61,7 +61,7 @@ public: void ReadOptions(ConfigParser& parser) { ReadOptions(parser, GetName()); } virtual void Initialize(); - bool Update(); + bool Update(bool rereadOptions = false); void Disable(); void Enable(); diff --git a/Library/MeterWindow.cpp b/Library/MeterWindow.cpp index 0bdf4a67..834c511b 100644 --- a/Library/MeterWindow.cpp +++ b/Library/MeterWindow.cpp @@ -2675,13 +2675,9 @@ bool MeterWindow::UpdateMeasure(Measure* measure, bool force) int updateDivider = measure->GetUpdateDivider(); if (updateDivider >= 0 || force) { - if (measure->HasDynamicVariables() && - (measure->GetUpdateCounter() + 1) >= updateDivider) - { - measure->ReadOptions(m_Parser); - } - - bUpdate = measure->Update(); + const bool rereadOptions = + measure->HasDynamicVariables() && (measure->GetUpdateCounter() + 1) >= updateDivider; + bUpdate = measure->Update(rereadOptions); } return bUpdate;