using System; using System.Collections.Generic; using System.Linq; using System.Text; using Crestron.SimplSharp; using PepperDash.Core; namespace PepperDash.Essentials.Core { /// /// 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. /// 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 SetAction; Func GetFunc; CTimer Timer; /// /// /// /// /// /// /// /// /// Action that will be called when this needs to set the destination value /// Func that is called to get the current value public ActionIncrementer(int changeAmount, int minValue, int maxValue, uint repeatDelay, uint repeatTime, Action setAction, Func getFunc) { SetAction = setAction; GetFunc = getFunc; ChangeAmount = changeAmount; MaxValue = maxValue; MinValue = minValue; RepeatDelay = repeatDelay; RepeatTime = repeatTime; } /// /// Starts incrementing cycle /// public void StartUp() { if (Timer != null) return; Go(ChangeAmount); } /// /// Starts decrementing cycle /// public void StartDown() { if (Timer != null) return; Go(-ChangeAmount); } /// /// Stops the repeat /// public void Stop() { if (Timer != null) Timer.Stop(); Timer = null; } /// /// Helper that does the work of setting new level, and starting repeat loop, checking against bounds first. /// /// 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); } /// /// Helper to check a new level against min/max. Returns revised level if new level /// will go out of bounds /// /// The level to check against bounds /// Revised level if bounds are exceeded. Min or max /// true if new level is at or past bounds 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; } } }