protected void CalculateAndAddToHistory()
        {
            var selectedOperator = _operatorMapping.Single(o => o.Key == CurrentCalculation.Operator).Value;

            try
            {
                var result = Calculator.Calculate(CurrentCalculation.FirstNumber, CurrentCalculation.SecondNumber, selectedOperator);
                CurrentCalculation.Result             = result;
                CurrentCalculation.CalculationProcess =
                    $"{CurrentCalculation.FirstNumber} {CurrentCalculation.Operator} {CurrentCalculation.SecondNumber} = {CurrentCalculation.Result}";
            }
            catch (DivideByZeroException exception)
            {
                AddError(exception);
            }
            catch (ArgumentOutOfRangeException exception)
            {
                AddError(exception);
            }

            CalculationItems.Add(CurrentCalculation);

            CurrentCalculation = new Calculation
            {
                Operator      = _operatorMapping.Keys.First(),
                CalculationID = CalculationID++
            };

            StateHasChanged();
        }
        public void SetLevelOrder(IList <CalculationItem> order)
        {
            if (order == null)
            {
                foreach (var item in CalculationItems)
                {
                    item.MetadataObject.Ordinal = -1;
                }
            }
            else
            {
                if (order.Count != CalculationItems.Count)
                {
                    throw new ArgumentException("Cannot order a hierarchy by a list that does not contain exactly the same levels as the hierarchy iteself.");
                }

                for (var i = 0; i < CalculationItems.Count; i++)
                {
                    if (!CalculationItems.Contains(order[i]))
                    {
                        throw new ArgumentException("Cannot order a hierarchy by levels in another hierarchy.");
                    }
                    order[i].MetadataObject.Ordinal = i;
                }
            }

            Handler.Tree.OnStructureChanged(this);
        }
        public void CompactLevelOrdinals()
        {
            var ordinal = 0;

            foreach (var l in CalculationItems.OrderBy(l => l.Ordinal))
            {
                l.MetadataObject.Ordinal = ordinal;
                ordinal++;
            }
        }
        public CalculationItem AddCalculationItem(string name = null, string expression = null)
        {
            var item = CalculationItem.CreateNew(CalculationGroup, string.IsNullOrEmpty(name) ? "New Calculation" : name);

            if (expression != null)
            {
                item.Expression = expression;
            }
            if (CalculationItems.Any(i => i.Ordinal != -1))
            {
                item.Ordinal = CalculationItems.Max(i => i.Ordinal) + 1;
            }
            return(item);
        }
        public void FixItemOrder(CalculationItem item, int newOrdinal)
        {
            if (_reordering)
            {
                return;
            }

            var before = CalculationItems.OrderBy(l => l.Ordinal).ToList();

            var ordinal = 0;

            foreach (var l in CalculationItems.OrderBy(l => (l == item ? newOrdinal : l.Ordinal) * 2 - (l == item ? 1 : 0)))
            {
                l.MetadataObject.Ordinal = newOrdinal == -1 ? -1 : ordinal;
                ordinal++;
            }

            var after = CalculationItems.OrderBy(l => l.Ordinal).ToList();

            Handler.UndoManager.Add(new UndoCalculationItemsOrderAction(this, before, newOrdinal == -1 ? null : after));

            _reordering = false;
            Handler.Tree.OnStructureChanged(this);
        }