Files
Essentials/essentials-framework/Essentials Core/PepperDashEssentialsBase/Ramps and Increments/ActionIncrementer.cs

120 lines
3.8 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Core;
namespace PepperDash.Essentials.Core
{
/// <summary>
/// An incrementer that can use the values of some other object/primitive value to do its thing.
/// It uses an Action to set the value and a Func to get the value from whatever this is
/// attached to.
/// </summary>
public class ActionIncrementer
{
public int ChangeAmount { get; set; }
public int MaxValue { get; set; }
public int MinValue { get; set; }
public uint RepeatDelay { get; set; }
public uint RepeatTime { get; set; }
Action<int> SetAction;
Func<int> GetFunc;
CTimer Timer;
/// <summary>
///
/// </summary>
/// <param name="changeAmount"></param>
/// <param name="minValue"></param>
/// <param name="maxValue"></param>
/// <param name="repeatDelay"></param>
/// <param name="repeatTime"></param>
/// <param name="setAction">Action that will be called when this needs to set the destination value</param>
/// <param name="getFunc">Func that is called to get the current value</param>
public ActionIncrementer(int changeAmount, int minValue, int maxValue, uint repeatDelay, uint repeatTime, Action<int> setAction, Func<int> getFunc)
{
SetAction = setAction;
GetFunc = getFunc;
ChangeAmount = changeAmount;
MaxValue = maxValue;
MinValue = minValue;
RepeatDelay = repeatDelay;
RepeatTime = repeatTime;
}
/// <summary>
/// Starts incrementing cycle
/// </summary>
public void StartUp()
{
if (Timer != null) return;
Go(ChangeAmount);
}
/// <summary>
/// Starts decrementing cycle
/// </summary>
public void StartDown()
{
if (Timer != null) return;
Go(-ChangeAmount);
}
/// <summary>
/// Stops the repeat
/// </summary>
public void Stop()
{
if (Timer != null)
Timer.Stop();
Timer = null;
}
/// <summary>
/// Helper that does the work of setting new level, and starting repeat loop, checking against bounds first.
/// </summary>
/// <param name="change"></param>
void Go(int change)
{
int currentLevel = GetFunc();
// Fire once then pause
int newLevel = currentLevel + change;
bool atLimit = CheckLevel(newLevel, out newLevel);
SetAction(newLevel);
if (atLimit) // Don't go past end
Stop();
else if (Timer == null) // Only enter the timer if it's not already running
Timer = new CTimer(o => { Go(change); }, null, RepeatDelay, RepeatTime);
}
/// <summary>
/// Helper to check a new level against min/max. Returns revised level if new level
/// will go out of bounds
/// </summary>
/// <param name="levelIn">The level to check against bounds</param>
/// <param name="levelOut">Revised level if bounds are exceeded. Min or max</param>
/// <returns>true if new level is at or past bounds</returns>
bool CheckLevel(int levelIn, out int levelOut)
{
bool isAtLimit = false;
if (levelIn > MaxValue)
{
levelOut = MaxValue;
isAtLimit = true;
}
else if (levelIn < MinValue)
{
levelOut = MinValue;
isAtLimit = true;
}
else
levelOut = levelIn;
return isAtLimit;
}
}
}