Mercurial > repos > IBDev-IBBoard.WarFoundry.GUI.WinForms
view UI/EquipmentAmountControl.cs @ 165:2c17714ad71b
Fixes #295: Index out of bounds when changing unit size and clicking in equipment list
* Remove forced refresh of equipment on unit size change
* Revert r620 and remove code for unlistening and relistening
author | IBBoard <dev@ibboard.co.uk> |
---|---|
date | Wed, 14 Jul 2010 20:02:20 +0000 |
parents | e00332dc1618 |
children |
line wrap: on
line source
using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Text; using System.Windows.Forms; using log4net; using IBBoard.CustomMath; using IBBoard.Lang; using IBBoard.Limits; using IBBoard.Windows.Forms; using IBBoard.Windows.Forms.I18N; using IBBoard.Windows.Forms.Util; using IBBoard.WarFoundry.API; using IBBoard.WarFoundry.API.Objects; using IBBoard.WarFoundry.API.Util; namespace IBBoard.WarFoundry.GUI.WinForms.UI { public partial class EquipmentAmountControl : UserControl { private ILog log = LogManager.GetLogger(typeof(EquipmentAmountControl)); private Unit unit; private UnitEquipmentItem equip; public event EventHandler ValueChanged; public EquipmentAmountControl() { InitializeComponent(); ControlTranslator.TranslateControl(this); } public void SetUnit(Unit equipUnit) { unit = equipUnit; log.Debug("Set unit to: " + (unit == null ? "null" : unit.Name)); } public void SetUnitEquipmentItem(UnitEquipmentItem unitEquipment) { equip = unitEquipment; log.Debug("Set equipment to: " + (equip == null ? "null" : equip.Name)); SetWidgetValues(); } private void OnValueChanged() { if (ValueChanged != null) { ValueChanged(this, new EventArgs()); } } private void SetWidgetValues() { if (equip != null) { IgnoreWidgets(); Enabled = true; log.Debug("Equipment update"); bool equipIsRatioLimit = UnitEquipmentUtil.IsEquipmentRatioLimited(unit, equip); log.Debug("Equipment is ratio? " + (equipIsRatioLimit ? "yes" : "no")); double maxPercent = RoundPercentage(UnitEquipmentUtil.GetMaxEquipmentPercentage(unit, equip)); maxPercent = Math.Max(0, maxPercent); log.Debug("Equipment max percentage: " + maxPercent); double minPercent = RoundPercentage(UnitEquipmentUtil.GetMinEquipmentPercentage(unit, equip)); minPercent = Math.Max(0, minPercent); log.Debug("Equipment min percentage: " + minPercent); int maxNumber = UnitEquipmentUtil.GetMaxEquipmentCount(unit, equip); maxNumber = Math.Max(0, maxNumber); log.Debug("Equipment max count: " + maxNumber); int minNumber = UnitEquipmentUtil.GetMinEquipmentCount(unit, equip); minNumber = Math.Max(0, minNumber); log.Debug("Equipment min count: " + minNumber); SetUpDownControlMinMaxes(minPercent, maxPercent, minNumber, maxNumber); if (equipIsRatioLimit) { SetEquipmentAmountsFromPercentage(minPercent); } else { SetEquipmentAmountsFromNumber(minNumber); } rbEquipAll.Enabled = equipIsRatioLimit && maxPercent == 100; rbEquipAll.Checked = equipIsRatioLimit && minPercent == 100; log.Debug("rbEquipAll: " + (rbEquipAll.Enabled ? "enabled":"disabled") + " " + (rbEquipAll.Checked ? "checked" : "unchecked")); percentage.Enabled = equipIsRatioLimit && minPercent != 100; rbPercentage.Enabled = percentage.Enabled; rbPercentage.Checked = equipIsRatioLimit && !rbEquipAll.Checked; log.Debug("rbPercentage: " + (rbPercentage.Enabled ? "enabled" : "disabled") + " " + (rbPercentage.Checked ? "checked" : "unchecked")); numeric.Enabled = !equipIsRatioLimit || minPercent != 100; rbNumeric.Enabled = numeric.Enabled; rbNumeric.Checked = !equipIsRatioLimit; log.Debug("rbNumeric: " + (rbNumeric.Enabled ? "enabled" : "disabled") + " " + (rbNumeric.Checked ? "checked" : "unchecked")); SetUnitEquipmentItemAmount(); ListenToWidgets(); } else { log.Debug("Null equipment - no widget update"); Enabled = false; } } private void IgnoreWidgets() { percentage.ValueChanged -= percentage_ValueChanged; numeric.ValueChanged -= numeric_ValueChanged; rbEquipAll.CheckedChanged -= rbEquipAll_CheckedChanged; rbNumeric.CheckedChanged -= radioCheckedChanged; rbPercentage.CheckedChanged -= radioCheckedChanged; } private void ListenToWidgets() { percentage.ValueChanged += percentage_ValueChanged; numeric.ValueChanged += numeric_ValueChanged; rbEquipAll.CheckedChanged += rbEquipAll_CheckedChanged; rbNumeric.CheckedChanged += radioCheckedChanged; rbPercentage.CheckedChanged += radioCheckedChanged; } private void SetUpDownControlMinMaxes(double minPercent, double maxPercent, int minNumber, int maxNumber) { SetUpDownControlMinMax(percentage, minPercent, maxPercent); SetUpDownControlMinMax(numeric, (decimal) minNumber, (decimal) maxNumber); } private void SetUpDownControlMinMax(NumericUpDown upDownControl, double min, double max) { SetUpDownControlMinMax(upDownControl, (decimal)min, (decimal)max); } private void SetUpDownControlMinMax(NumericUpDown upDownControl, decimal min, decimal max) { log.Debug("Set "+upDownControl.Name+" min and max to: "+min+", "+max); upDownControl.Minimum = min; upDownControl.Maximum = max; } private void rbEquipAll_CheckedChanged(object sender, EventArgs e) { bool equipAll = rbEquipAll.Checked; numeric.Enabled = !equipAll; percentage.Enabled = !equipAll; if (equipAll) { numeric.Value = unit.Size; percentage.Value = 100; } radioCheckedChanged(sender, e); } private void percentage_ValueChanged(object sender, EventArgs e) { PerformPercentageValueChanged(); } private void PerformPercentageValueChanged() { log.Debug("Percentage value changed"); SetNumericValueFromPercentage(); rbEquipAll.Checked = (percentage.Value == 100 && !rbNumeric.Checked); OnValueChanged(); } private void SetNumericValueFromPercentage() { numeric.ValueChanged -= numeric_ValueChanged; numeric.Value = CalculateNumericValueFromPercentage(percentage.Value); numeric.ValueChanged += numeric_ValueChanged; } private decimal CalculateNumericValueFromPercentage(decimal percent) { decimal calcedAmount = (decimal) IBBoard.CustomMath.IBBMath.Round((double)(unit.Size * (percent / 100)), equip.RoundNumberUp); log.Debug("Numeric value calculated from percentage: "+percent+"% -> "+calcedAmount); return Math.Min(Math.Max(calcedAmount, numeric.Minimum), numeric.Maximum); } private void numeric_ValueChanged(object sender, EventArgs e) { log.Debug("Numeric value changed"); SetPercentageValueFromNumeric(); OnValueChanged(); } private void SetPercentageValueFromNumeric() { int number = (int)numeric.Value; percentage.ValueChanged -= percentage_ValueChanged; percentage.Value = CalcualtePercentageValueFromNumber(number); percentage.ValueChanged += percentage_ValueChanged; } private decimal CalcualtePercentageValueFromNumber(int number) { decimal calcedAmount = (decimal) RoundPercentage(IBBoard.CustomMath.IBBMath.Percentage(number, unit.Size)); log.Debug("Numeric value calculated from percentage: " + number + " -> " + calcedAmount+"%"); return Math.Min(Math.Max(calcedAmount, percentage.Minimum), percentage.Maximum); } private double RoundPercentage(double percent) { return Math.Round(percent, 1); } public double EquipmentAmount { get { double val = 0; if (rbNumeric.Checked) { val = (double) numeric.Value; } else if (rbPercentage.Checked) { val = (double) percentage.Value; } else if (rbEquipAll.Checked) { val = 100; } else { val = 0; } return val; } } public bool IsRatioEquipmentAmount { get { return !rbNumeric.Checked; } } private void SetUnitEquipmentItemAmount() { double equipAmountNum = UnitEquipmentUtil.GetEquipmentAmount(unit, equip); if (equipAmountNum > 0) { bool isRatio = UnitEquipmentUtil.GetEquipmentAmountIsRatio(unit, equip); if (isRatio) { SetEquipmentAmountsFromPercentage(equipAmountNum); if (equipAmountNum == 100) { rbEquipAll.Checked = true; } else { rbPercentage.Checked = true; } } else { int equipAmount = (int) equipAmountNum; SetEquipmentAmountsFromNumber(equipAmount); rbNumeric.Checked = true; } } } private void SetEquipmentAmountsFromPercentage(double equipAmount) { log.Debug("Set equipment amount from percentage: " + equipAmount); decimal decEquipAmount = (decimal) equipAmount; if (decEquipAmount > percentage.Maximum) { string percentageTooLarge = Translation.GetTranslation("equipPercentageTooLarge", "the current percentage ({0}%) was larger than the maximum for the equipment item ({1}%) - the maximum value will be used instead", equipAmount, percentage.Maximum); string percentageTooLargeTitle = Translation.GetTranslation("equipPercentageTooLargeTitle", "equipment percentage too large"); MessageBox.Show(ParentForm, percentageTooLarge, percentageTooLargeTitle); decEquipAmount = percentage.Maximum; log.Debug("Limited equipment amount to " + decEquipAmount); OnValueChanged(); } else if (decEquipAmount < percentage.Minimum) { string percentageTooSmall = Translation.GetTranslation("equipPercentageTooSmall", "the current percentage ({0}%) was smaller than the minimum for the equipment item ({1}%) - the minimum value will be used instead", equipAmount, percentage.Minimum); string percentageTooSmallTitle = Translation.GetTranslation("equipPercentageTooSmallTitle", "equipment percentage too small"); MessageBox.Show(ParentForm, percentageTooSmall, percentageTooSmallTitle); decEquipAmount = percentage.Minimum; log.Debug("Limited equipment amount to " + decEquipAmount); OnValueChanged(); } numeric.Value = CalculateNumericValueFromPercentage(decEquipAmount); percentage.Value = decEquipAmount; } private void SetEquipmentAmountsFromNumber(int equipAmount) { log.Debug("Set equipment percentage from amount: " + equipAmount); if (equipAmount > numeric.Maximum) { string amountTooLarge = Translation.GetTranslation("equipNumberTooLarge", "the current amount ({0}) was larger than the maximum for the equipment item ({1}) - the maximum value will be used instead", equipAmount, numeric.Maximum); string amountTooLargeTitle = Translation.GetTranslation("equipNumberTooLargeTitle", "equipment amount too large"); MessageBox.Show(ParentForm, amountTooLarge, amountTooLargeTitle); equipAmount = (int)numeric.Maximum; log.Debug("Limited equipment amount to " + equipAmount); OnValueChanged(); } else if (equipAmount < numeric.Minimum) { string amountTooSmall = Translation.GetTranslation("equipNumberTooSmall", "the current amount ({0}) was smaller than the minimum for the equipment item ({1}) - the minimum value will be used instead", equipAmount, numeric.Minimum); string amountTooSmallTitle = Translation.GetTranslation("equipNumberTooSmallTitle", "equipment amount too small"); MessageBox.Show(ParentForm, amountTooSmall, amountTooSmallTitle); equipAmount = (int) numeric.Minimum; log.Debug("Limited equipment amount to " + equipAmount); OnValueChanged(); } percentage.Value = CalcualtePercentageValueFromNumber(equipAmount); numeric.Value = equipAmount; } private void radioCheckedChanged(object sender, EventArgs e) { OnValueChanged(); } protected override bool ProcessDialogKey(Keys keyData) { bool processed = false; if (keyData == Keys.Enter) { if (numeric.Focused) { processed = ForceUpDownControlUpdate(numeric); } else if (percentage.Focused) { processed = ForceUpDownControlUpdate(percentage); } } if (!processed) { processed = base.ProcessDialogKey(keyData); } return processed; } private bool ForceUpDownControlUpdate(NumericUpDown control) { ControlValueChangedChecker checker = new ControlValueChangedChecker(); control.ValueChanged += checker.ValueChanged; decimal val = control.Value; control.ValueChanged -= checker.ValueChanged; return checker.valueChanged; } } }