void UpdateStatusProperties() { if (_mouseTransmissionLossMarker != null) AxisMarkers.Remove(_mouseTransmissionLossMarker); if (AxisSeriesViewModel.IsMouseOver && _shadeFile != null) { MouseRange = string.Format("Range: {0:0.0}m", AxisSeriesViewModel.XAxis.MouseDataLocation); MouseDepth = string.Format("Depth: {0:0.0}m", AxisSeriesViewModel.YAxis.MouseDataLocation); var px = AxisSeriesViewModel.MouseLocation.X / AxisSeriesViewModel.ActualWidth; var py = AxisSeriesViewModel.MouseLocation.Y / AxisSeriesViewModel.ActualHeight; var rangeIndex = Math.Max(0, Math.Min((int)(_shadeFile.ReceiverRanges.Length * px), _shadeFile.ReceiverRanges.Length - 1)); var depthIndex = Math.Max(0, Math.Min((int)(_shadeFile.ReceiverDepths.Length * py), _shadeFile.ReceiverDepths.Length - 1)); MouseTransmissionLossInfo = string.Format("Transmission Loss: {0:0.0}dB", _shadeFile.TransmissionLoss[depthIndex, rangeIndex]); if (float.IsInfinity(_shadeFile.TransmissionLoss[depthIndex, rangeIndex]) || float.IsNaN(_shadeFile.TransmissionLoss[depthIndex, rangeIndex]) || double.IsNaN(AxisSeriesViewModel.YAxis.MouseDataLocation) || (Radial.BottomDepths!= null && (AxisSeriesViewModel.YAxis.MouseDataLocation > Radial.BottomDepths[rangeIndex]))) { MouseTransmissionLossInfo = "Transmission Loss: N/A"; MouseSPLInfo = "Sound Pressure: N/A"; } else { if (FullRange.Contains(_shadeFile.TransmissionLoss[depthIndex, rangeIndex])) { _mouseTransmissionLossMarker = new DataAxisTick(_shadeFile.TransmissionLoss[depthIndex, rangeIndex], string.Format("{0:0}", _shadeFile.TransmissionLoss[depthIndex, rangeIndex]), true, Brushes.Black, Brushes.LightGray, Brushes.White); AxisMarkers.Add(_mouseTransmissionLossMarker); } MouseTransmissionLossInfo = string.Format("Transmission Loss: {0:0.0}dB", _shadeFile.TransmissionLoss[depthIndex, rangeIndex]); MouseSPLInfo = string.Format("Sound Pressure: {0:0.0}dB", SelectedMode.SourceLevel - _shadeFile.TransmissionLoss[depthIndex, rangeIndex]); } } else { MouseDepth = "Depth: N/A"; MouseRange = "Range: N/A"; MouseTransmissionLossInfo = "Transmission Loss: N/A"; MouseSPLInfo = "Sound Pressure: N/A"; if (_mouseTransmissionLossMarker != null) AxisMarkers.Remove(_mouseTransmissionLossMarker); _mouseTransmissionLossMarker = null; } }
Size MeasureNonEnumerated(Size availableSize) { if (Double.IsNaN(availableSize.Width) || Double.IsInfinity(availableSize.Width)) availableSize.Width = SystemParameters.VirtualScreenWidth; if (Double.IsNaN(availableSize.Height) || Double.IsInfinity(availableSize.Height)) availableSize.Height = SystemParameters.VirtualScreenHeight; if (_internalVisibleRange == null || _internalVisibleRange.IsEmpty) return AxisLocation == AxisLocation.Top || AxisLocation == AxisLocation.Bottom ? new Size(availableSize.Width, 22) : new Size(availableSize.Height, 22); // We need to fake out the layout code re: inversion and logarithmic mode so we NEVER set these two parameters to true _axisOptions.AxisTransform = CreateAxisTransform(_internalVisibleRange, availableSize, true, false, false); _axisOptions.Screen = new Rect(availableSize); _axis = _axisLabeler.Generate(_axisOptions, MajorTicksPerInch / _pixelsPerInch); if (_axis == null) return AxisLocation == AxisLocation.Top || AxisLocation == AxisLocation.Bottom ? new Size(availableSize.Width, 22) : new Size(availableSize.Height, 22); if (_showDebugMessages) Debug.WriteLine(string.Format("{0:HH:mm:ss.fff} DataAxis.MeasureNonEnumerated: Axis \"{1}\": _axis.VisibleRange {2} _axis.Labels.First(): {3} _axis.Labels.Last(): {4}", DateTime.Now, AxisLabel, _axis.VisibleRange, _axis.Labels.First().Value, _axis.Labels.Last().Value)); var majorTickLabels = _axis.Labels; if (_showDebugMessages) Debug.WriteLine(string.Format("{0:HH:mm:ss.fff} DataAxis.MeasureNonEnumerated: Axis \"{1}\": _internalVisibleRange {2} _internalVisibleRange.Contains(_axis.VisibleRange): {3}", DateTime.Now, AxisLabel, _internalVisibleRange, _internalVisibleRange.Contains(_axis.VisibleRange))); if (_visibleRange != _axis.VisibleRange) { if (_showDebugMessages) Debug.WriteLine(string.Format("{0:HH:mm:ss.fff} DataAxis.MeasureNonEnumerated: Axis \"{1}\": Updated VisbleRange. Post-update: {2}", DateTime.Now, AxisLabel, _visibleRange)); _visibleRange.Update(_axis.VisibleRange); if (_showDebugMessages) Debug.WriteLine(string.Format("{0:HH:mm:ss.fff} DataAxis.MeasureNonEnumerated: Axis \"{1}\": Updated VisbleRange. Post-update: {2}", DateTime.Now, AxisLabel, _visibleRange)); OnTransformChanged(); } Children.Clear(); AxisTicks.Clear(); foreach (var label in majorTickLabels) { // For logarithmic axes make sure we are only using integral label values if (IsLogarithmic && (Math.Abs(Math.Floor(label.Value) - label.Value) > double.Epsilon)) continue; var labelValue = IsLogarithmic ? Math.Pow(10, label.Value) : label.Value; var majorTick = new DataAxisTick(labelValue, label.Label, true, IsLogarithmic); AxisTicks.Add(majorTick); Children.Add(majorTick.TextBlockBorder); majorTick.TextBlockBorder.Measure(availableSize); } if (AxisMarkers != null) foreach (var marker in AxisMarkers) { Children.Add(marker.TextBlockBorder); marker.TextBlockBorder.Measure(availableSize); } // If the minor tick frequency isn't at least twice the major tick frequency, don't do any minor ticks var minorTicksPerMajorTick = IsLogarithmic ? 10 : (int)(MinorTicksPerInch / MajorTicksPerInch); if (minorTicksPerMajorTick > 1) { if (IsLogarithmic) { // Get the major tick values in descending order var majorTickLogValues = AxisTicks.Select(t => Math.Log10(t.Value)).Reverse().ToList(); // Add minor ticks at whole-number log values if any are needed for (var i = 0; i < majorTickLogValues.Count - 1; i++) for (var j = majorTickLogValues[i] - 1; j > majorTickLogValues[i + 1]; j--) AxisTicks.Add(new DataAxisTick(Math.Pow(10, j), null, false, IsLogarithmic)); // Add minor ticks at the usual places for a log scale (2, 3, 4, 5, 6, 7, 8, 9) for (var baseValue = Math.Floor(_internalVisibleRange.Min); baseValue < Math.Ceiling(_internalVisibleRange.Max); baseValue++) { foreach (var logOffset in LogMinorTicks) { var logValue = baseValue + logOffset; if (_internalVisibleRange.Min <= logValue && logValue <= _internalVisibleRange.Max) AxisTicks.Add(new DataAxisTick(Math.Pow(10, logValue), null, false, IsLogarithmic)); } } } else { var majorTickValueSpacing = majorTickLabels[1].Value - majorTickLabels[0].Value; var stepSize = majorTickValueSpacing / minorTicksPerMajorTick; var majorTickValues = AxisTicks.Select(t => t.Value).ToList(); // Add a phantom major tick to the beginning and end of the list so we can bracket // the major ticks at each end of the range with more minor ticks if they fit within the // visible range of the axis majorTickValues.Insert(0, AxisTicks[0].Value - majorTickValueSpacing); majorTickValues.Add(AxisTicks.Last().Value + majorTickValueSpacing); foreach (var t in majorTickValues) for (var j = 1; j < minorTicksPerMajorTick; j++) { var tickValue = t + (stepSize * j); if (tickValue < _internalVisibleRange.Min || tickValue > _internalVisibleRange.Max) continue; var minorTick = new DataAxisTick(tickValue, null, false, IsLogarithmic); AxisTicks.Add(minorTick); } } } _tickLabelMaxWidth = AxisTicks.Where(t => t.TextBlockBorder != null).Max(t => t.TextBlockBorder.DesiredSize.Width); _tickLabelMaxHeight = AxisTicks.Where(t => t.TextBlockBorder != null).Max(t => t.TextBlockBorder.DesiredSize.Height); if (AxisMarkers != null && AxisMarkers.Count > 0) { _tickLabelMaxWidth = Math.Max(_tickLabelMaxWidth, AxisMarkers.Where(t => t.TextBlockBorder != null).Max(t => t.TextBlockBorder.DesiredSize.Width)); _tickLabelMaxHeight = Math.Max(_tickLabelMaxHeight, AxisMarkers.Where(t => t.TextBlockBorder != null).Max(t => t.TextBlockBorder.DesiredSize.Height)); } var axisLabel = string.IsNullOrEmpty(_axis.AxisTitleExtension) ? AxisLabel : string.Format("{0} ({1})", AxisLabel, _axis.AxisTitleExtension); _axisLabel.Text = axisLabel; _axisLabel.FontSize = _axis.FontSize + 2; Children.Add(_axisLabel); _axisLabel.Measure(availableSize); var desiredSize = new Size(availableSize.Width, availableSize.Height); switch (AxisLocation) { case AxisLocation.Top: case AxisLocation.Bottom: _tickLabelDimension = _tickLabelMaxHeight; _axisLabelDimension = _axisLabel.DesiredSize.Height; desiredSize.Height = MajorTickLength + _tickLabelDimension + _axisLabelDimension; break; case AxisLocation.Left: case AxisLocation.Right: _tickLabelDimension = _tickLabelMaxWidth; _axisLabelDimension = _axisLabel.DesiredSize.Width; desiredSize.Width = MajorTickLength + 2 + _tickLabelDimension + _axisLabelDimension; break; default: throw new ApplicationException("DataAxis: Unknown AxisLocation value."); } // desiredSize = ... computed sum of children's DesiredSize ...; // IMPORTANT: do not allow PositiveInfinity to be returned, that will raise an exception in the caller! // PositiveInfinity might be an availableSize input; this means that the parent does not care about sizing //Debug.WriteLine(string.Format("DataAxis: MeasureNonEnumerated for {0} returning desired width {1} and height {2}", AxisLabel, desiredSize.Width, desiredSize.Height)); return desiredSize; }