mirror of
https://github.com/chibicitiberiu/rainmeter-studio.git
synced 2024-02-24 04:33:31 +00:00
Added new options IfCondition/IfTrueAction/IfFalseAction for all Measures.
Multiple conditions/actions are also possible (eg. IfCondition2/IfTrueAction2)
This commit is contained in:
parent
e65af4d890
commit
87edcd0ce4
261
Library/IfActions.cpp
Normal file
261
Library/IfActions.cpp
Normal file
@ -0,0 +1,261 @@
|
||||
/*
|
||||
Copyright (C) 2013 Brian Ferguson
|
||||
|
||||
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "Measure.h"
|
||||
#include "IfActions.h"
|
||||
#include "Rainmeter.h"
|
||||
#include "../Common/MathParser.h"
|
||||
|
||||
IfActions::IfActions(MeterWindow* meterWindow, Measure* measure) :
|
||||
m_AboveValue(0.0f),
|
||||
m_BelowValue(0.0f),
|
||||
m_EqualValue(0),
|
||||
m_AboveAction(),
|
||||
m_BelowAction(),
|
||||
m_EqualAction(),
|
||||
m_AboveCommitted(false),
|
||||
m_BelowCommitted(false),
|
||||
m_EqualCommitted(false),
|
||||
m_Conditions(),
|
||||
m_HasConditions(false),
|
||||
m_HasDynamicVariables(false),
|
||||
m_MeterWindow(meterWindow),
|
||||
m_Measure(measure)
|
||||
{
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
m_BelowAction = parser.ReadString(section, L"IfBelowAction", L"", false);
|
||||
m_BelowValue = parser.ReadFloat(section, L"IfBelowValue", 0.0f);
|
||||
|
||||
m_EqualAction = parser.ReadString(section, L"IfEqualAction", L"", false);
|
||||
m_EqualValue = (int64_t)parser.ReadFloat(section, L"IfEqualValue", 0.0f);
|
||||
|
||||
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 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;
|
||||
int i = 1;
|
||||
|
||||
do
|
||||
{
|
||||
if (m_Conditions.size() > (i - 1))
|
||||
{
|
||||
m_Conditions[i - 1].Set(condition, tAction, fAction);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Conditions.emplace_back(condition, tAction, fAction, hasSelf);
|
||||
}
|
||||
|
||||
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);
|
||||
key = L"IfFalseAction" + std::to_wstring(i);
|
||||
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"");
|
||||
|
||||
}
|
||||
while (!condition.empty() && (!tAction.empty() || !fAction.empty()));
|
||||
}
|
||||
}
|
||||
|
||||
void IfActions::DoIfActions(double& value)
|
||||
{
|
||||
if (!m_EqualAction.empty())
|
||||
{
|
||||
if ((int64_t)value == m_EqualValue)
|
||||
{
|
||||
if (!m_EqualCommitted)
|
||||
{
|
||||
m_EqualCommitted = true; // To avoid infinite loop from !Update
|
||||
GetRainmeter().ExecuteCommand(m_EqualAction.c_str(), m_MeterWindow);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_EqualCommitted = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_AboveAction.empty())
|
||||
{
|
||||
if (value > m_AboveValue)
|
||||
{
|
||||
if (!m_AboveCommitted)
|
||||
{
|
||||
m_AboveCommitted = true; // To avoid infinite loop from !Update
|
||||
GetRainmeter().ExecuteCommand(m_AboveAction.c_str(), m_MeterWindow);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_AboveCommitted = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_BelowAction.empty())
|
||||
{
|
||||
if (value < m_BelowValue)
|
||||
{
|
||||
if (!m_BelowCommitted)
|
||||
{
|
||||
m_BelowCommitted = true; // To avoid infinite loop from !Update
|
||||
GetRainmeter().ExecuteCommand(m_BelowAction.c_str(), m_MeterWindow);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_BelowCommitted = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_HasConditions)
|
||||
{
|
||||
int i = 0;
|
||||
for (auto& item : m_Conditions)
|
||||
{
|
||||
++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)
|
||||
{
|
||||
if (!item.parseError)
|
||||
{
|
||||
if (i == 1)
|
||||
{
|
||||
LogErrorF(m_Measure, L"%s: IfCondition=%s", errMsg, item.condition.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
LogErrorF(m_Measure, L"%s: IfCondition%i=%s", errMsg, i, item.condition.c_str());
|
||||
}
|
||||
item.parseError = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
item.parseError = false;
|
||||
|
||||
if (result == 1.0f) // "True"
|
||||
{
|
||||
GetRainmeter().ExecuteCommand(item.tAction.c_str(), m_MeterWindow);
|
||||
}
|
||||
else if (result == 0.0f) // "False"
|
||||
{
|
||||
GetRainmeter().ExecuteCommand(item.fAction.c_str(), m_MeterWindow);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IfActions::SetState(double value)
|
||||
{
|
||||
// Set IfAction committed state to false if condition is not met with value = 0
|
||||
if (m_EqualValue != 0)
|
||||
{
|
||||
m_EqualCommitted = false;
|
||||
}
|
||||
|
||||
if (m_AboveValue <= 0.0)
|
||||
{
|
||||
m_AboveCommitted = false;
|
||||
}
|
||||
|
||||
if (m_BelowValue >= 0.0)
|
||||
{
|
||||
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[1], pos);
|
||||
condition.replace(pos, 1, eBracket.substr(1, 1));
|
||||
++pos;
|
||||
replaced = true;
|
||||
}
|
||||
|
||||
return replaced;
|
||||
}
|
92
Library/IfActions.h
Normal file
92
Library/IfActions.h
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
Copyright (C) 2013 Brian Ferguson
|
||||
|
||||
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __IFACTIONS_H__
|
||||
#define __IFACTIONS_H__
|
||||
|
||||
#include <windows.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class ConfigParser;
|
||||
class Measure;
|
||||
class MeterWindow;
|
||||
|
||||
class IfCondition
|
||||
{
|
||||
public:
|
||||
IfCondition(std::wstring value, std::wstring trueAction, std::wstring falseAction = L"", bool hasSelf = false) :
|
||||
condition(),
|
||||
tAction(),
|
||||
fAction(),
|
||||
containsSelf(hasSelf),
|
||||
parseError(false)
|
||||
{
|
||||
Set(value, trueAction, falseAction);
|
||||
}
|
||||
|
||||
inline void Set(std::wstring value, std::wstring trueAction, std::wstring falseAction)
|
||||
{
|
||||
this->condition = value;
|
||||
this->tAction = trueAction;
|
||||
this->fAction = falseAction;
|
||||
}
|
||||
|
||||
std::wstring condition; // IfCondition
|
||||
std::wstring tAction; // IfTrueAction
|
||||
std::wstring fAction; // IfFalseAction
|
||||
bool parseError;
|
||||
bool containsSelf;
|
||||
};
|
||||
|
||||
class IfActions
|
||||
{
|
||||
public:
|
||||
IfActions(MeterWindow* meterWindow, Measure* measure);
|
||||
~IfActions();
|
||||
|
||||
void ReadOptions(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;
|
||||
|
||||
std::wstring m_AboveAction;
|
||||
std::wstring m_BelowAction;
|
||||
std::wstring m_EqualAction;
|
||||
|
||||
bool m_AboveCommitted;
|
||||
bool m_BelowCommitted;
|
||||
bool m_EqualCommitted;
|
||||
|
||||
std::vector<IfCondition> m_Conditions;
|
||||
bool m_HasConditions;
|
||||
|
||||
bool m_HasDynamicVariables;
|
||||
|
||||
ConfigParser* m_Parser;
|
||||
MeterWindow* m_MeterWindow;
|
||||
Measure* m_Measure;
|
||||
};
|
||||
#endif
|
@ -67,6 +67,7 @@
|
||||
<ClCompile Include="Group.cpp">
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="IfActions.cpp" />
|
||||
<ClCompile Include="Litestep.cpp">
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
@ -287,6 +288,7 @@
|
||||
<ClInclude Include="DialogAbout.h" />
|
||||
<ClInclude Include="Error.h" />
|
||||
<ClInclude Include="Group.h" />
|
||||
<ClInclude Include="IfActions.h" />
|
||||
<ClInclude Include="Litestep.h" />
|
||||
<ClInclude Include="DialogManage.h" />
|
||||
<ClInclude Include="Logger.h" />
|
||||
|
@ -393,6 +393,9 @@
|
||||
<ClCompile Include="ContextMenu.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="IfActions.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="ConfigParser.h">
|
||||
@ -671,6 +674,9 @@
|
||||
<ClInclude Include="ContextMenu.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="IfActions.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="Library.rc">
|
||||
|
@ -77,12 +77,7 @@ Measure::Measure(MeterWindow* meterWindow, const WCHAR* name) : Section(meterWin
|
||||
m_MedianPos(),
|
||||
m_AveragePos(),
|
||||
m_AverageSize(),
|
||||
m_IfEqualValue(),
|
||||
m_IfAboveValue(),
|
||||
m_IfBelowValue(),
|
||||
m_IfEqualCommitted(false),
|
||||
m_IfAboveCommitted(false),
|
||||
m_IfBelowCommitted(false),
|
||||
m_IfActions(meterWindow, this),
|
||||
m_Disabled(false),
|
||||
m_Paused(false),
|
||||
m_Initialized(false),
|
||||
@ -134,16 +129,7 @@ void Measure::ReadOptions(ConfigParser& parser, const WCHAR* section)
|
||||
m_MinValue = parser.ReadFloat(section, L"MinValue", m_MinValue);
|
||||
m_MaxValue = parser.ReadFloat(section, L"MaxValue", m_MaxValue);
|
||||
|
||||
// The ifabove/ifbelow define actions that are ran when the value goes above/below the given number.
|
||||
|
||||
m_IfAboveValue = parser.ReadFloat(section, L"IfAboveValue", 0.0);
|
||||
m_IfAboveAction = parser.ReadString(section, L"IfAboveAction", L"", false);
|
||||
|
||||
m_IfBelowValue = parser.ReadFloat(section, L"IfBelowValue", 0.0);
|
||||
m_IfBelowAction = parser.ReadString(section, L"IfBelowAction", L"", false);
|
||||
|
||||
m_IfEqualValue = (int64_t)parser.ReadFloat(section, L"IfEqualValue", 0.0);
|
||||
m_IfEqualAction = parser.ReadString(section, L"IfEqualAction", L"", false);
|
||||
m_IfActions.ReadOptions(parser, section);
|
||||
|
||||
m_OnChangeAction = parser.ReadString(section, L"OnChangeAction", L"", false);
|
||||
|
||||
@ -513,53 +499,7 @@ bool Measure::Update()
|
||||
|
||||
if (m_MeterWindow)
|
||||
{
|
||||
if (!m_IfEqualAction.empty())
|
||||
{
|
||||
if ((int64_t)m_Value == m_IfEqualValue)
|
||||
{
|
||||
if (!m_IfEqualCommitted)
|
||||
{
|
||||
m_IfEqualCommitted = true; // To avoid infinite loop from !Update
|
||||
GetRainmeter().ExecuteCommand(m_IfEqualAction.c_str(), m_MeterWindow);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_IfEqualCommitted = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_IfAboveAction.empty())
|
||||
{
|
||||
if (m_Value > m_IfAboveValue)
|
||||
{
|
||||
if (!m_IfAboveCommitted)
|
||||
{
|
||||
m_IfAboveCommitted = true; // To avoid infinite loop from !Update
|
||||
GetRainmeter().ExecuteCommand(m_IfAboveAction.c_str(), m_MeterWindow);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_IfAboveCommitted = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_IfBelowAction.empty())
|
||||
{
|
||||
if (m_Value < m_IfBelowValue)
|
||||
{
|
||||
if (!m_IfBelowCommitted)
|
||||
{
|
||||
m_IfBelowCommitted = true; // To avoid infinite loop from !Update
|
||||
GetRainmeter().ExecuteCommand(m_IfBelowAction.c_str(), m_MeterWindow);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_IfBelowCommitted = false;
|
||||
}
|
||||
}
|
||||
m_IfActions.DoIfActions(m_Value);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -569,21 +509,7 @@ bool Measure::Update()
|
||||
// Disabled measures have 0 as value
|
||||
m_Value = 0.0;
|
||||
|
||||
// Set IfAction committed state to false if condition is not met with value = 0
|
||||
if (m_IfEqualValue != 0)
|
||||
{
|
||||
m_IfEqualCommitted = false;
|
||||
}
|
||||
|
||||
if (m_IfAboveValue <= 0.0)
|
||||
{
|
||||
m_IfAboveCommitted = false;
|
||||
}
|
||||
|
||||
if (m_IfBelowValue >= 0.0)
|
||||
{
|
||||
m_IfBelowCommitted = false;
|
||||
}
|
||||
m_IfActions.SetState(m_Value);
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -879,3 +805,25 @@ void Measure::Command(const std::wstring& command)
|
||||
{
|
||||
LogWarningF(this, L"!CommandMeasure: Not supported");
|
||||
}
|
||||
|
||||
/*
|
||||
** Returns the number value of a measure, used by IfCondition's.
|
||||
**
|
||||
*/
|
||||
bool Measure::GetCurrentMeasureValue(const WCHAR* str, int len, double* value, void* context)
|
||||
{
|
||||
auto measure = (Measure*)context;
|
||||
const std::vector<Measure*>& measures = measure->m_MeterWindow->GetMeasures();
|
||||
|
||||
for (const auto& iter : measures)
|
||||
{
|
||||
if (iter->GetOriginalName().length() == len &&
|
||||
_wcsnicmp(str, iter->GetName(), len) == 0)
|
||||
{
|
||||
*value = iter->GetValue();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <windows.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include "IfActions.h"
|
||||
#include "Litestep.h"
|
||||
#include "Section.h"
|
||||
|
||||
@ -89,6 +90,7 @@ public:
|
||||
void DoChangeAction(bool execute = true);
|
||||
|
||||
static Measure* Create(const WCHAR* measure, MeterWindow* meterWindow, const WCHAR* name);
|
||||
static bool GetCurrentMeasureValue(const WCHAR* str, int len, double* value, void* context);
|
||||
|
||||
protected:
|
||||
Measure(MeterWindow* meterWindow, const WCHAR* name);
|
||||
@ -117,15 +119,7 @@ protected:
|
||||
UINT m_AveragePos;
|
||||
UINT m_AverageSize;
|
||||
|
||||
int64_t m_IfEqualValue; // The limit for the IfEqual action
|
||||
double m_IfAboveValue; // The limit for the IfAbove action
|
||||
double m_IfBelowValue; // The limit for the IfBelow action
|
||||
std::wstring m_IfEqualAction; // The IfEqual action
|
||||
std::wstring m_IfAboveAction; // The IfAbove action
|
||||
std::wstring m_IfBelowAction; // The IfBelow action
|
||||
bool m_IfEqualCommitted; // True when the IfEqual action is executed
|
||||
bool m_IfAboveCommitted; // True when the IfAbove action is executed
|
||||
bool m_IfBelowCommitted; // True when the IfBelow action is executed
|
||||
IfActions m_IfActions;
|
||||
bool m_Disabled; // Status of the measure
|
||||
bool m_Paused;
|
||||
bool m_Initialized;
|
||||
|
Loading…
Reference in New Issue
Block a user