Hi,
I've implemented some custom logic after zooming. Some requirements:
- The time that is under the mouse cursor while zooming with Ctrl+scroll, has to remain under the mouse cursor, to give the user the impression that he/she is zooming into that point. In case of CTRL+ (in which I call zoom manually by catching key events) the time in the center of the screen must remain in the center.
- The start time of the gantt must always remain the same after zooming. With 'start time' I mean the most left time on the viewport (scrolloffset 0). The user has to be able to get there without using the time shift left button.
I've implemented the following logic to achieve this (see code block). This worked fine with the 6.5 gantt package (and was being tested for several months now) but behaves weird with the 7.0 package. When zooming out to a certain point, the call to gantt.GanttChart.SetStartTime doesn't work anymore, causing the left part of the view not to be visible anymore.
private void Gantt_BeforeZooming(object sender, BeforeZoomEventArgs e)
{
_DesiredZoomViewWidth = (_DesiredZoomViewWidth.HasValue ? _DesiredZoomViewWidth.Value : gantt.GanttChart.ViewWidth) * (e.NewBaseTimeUnitWidth / gantt.GanttChart.BaseTimeUnitWidth);
//For now, assume that scroll is being performed by mouse if not by key, because there is no other way of checking the source of the zoom
//A zoom called by the control itself will often not pass in the beforezooming event anyway ...
if (_ZoomTrigger != ZoomTrigger.CtrlKey)
_ZoomTrigger = ZoomTrigger.CtrlMouse;
if (_ZoomTrigger == ZoomTrigger.CtrlMouse)
{
var mousePosX = Mouse.GetPosition(gantt.GanttChart.ScrollViewerElement).X;
var time = gantt.GanttChart.ConvertXToTime(mousePosX + gantt.GanttChart.ScrollViewerElement.HorizontalOffset);
_OffsetTimeBeforeZoom = time;
_OffsetTimePixelsToViewportBeforeZoom = mousePosX;
}
else if (_ZoomTrigger == ZoomTrigger.CtrlKey)
{
var centerTimeBeforeZoom = gantt.GanttChart.VisualStartTime.Add(new TimeSpan((gantt.GanttChart.VisualEndTime - gantt.GanttChart.VisualStartTime).Ticks / 2));
_OffsetTimeBeforeZoom = centerTimeBeforeZoom;
_OffsetTimePixelsToViewportBeforeZoom = gantt.GanttChart.ConvertTimeToX(centerTimeBeforeZoom) - gantt.GanttChart.ScrollViewerElement.HorizontalOffset;
}
_ComputedStartTimeBeforeZoom = gantt.GanttChart.ComputedStartTime;
}
private void Gantt_Zoomed(object sender, ZoomedEventArgs args)
{
this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(delegate()
{
if (_ZoomTrigger != ZoomTrigger.System)
{
_ZoomTrigger = ZoomTrigger.System; // Set for next time, because system zoom often doesn't get in the 'BeforeZoom' event ...
if (!_DesiredZoomViewWidth.HasValue) return;
var desiredZoomViewWidth = _DesiredZoomViewWidth.Value;
//Change view width in a way that it's wide enough to contain all items in the scroll area from before the zoom (with a maximum of 12000 pix, unfortunately)
//If the desired width is greater than 12000, the start time of the scrollable area will stay the same but end time is being cut
//This will happen automatically because the start time and ViewWidth is set right on every zoom
gantt.GanttChart.ViewWidth = desiredZoomViewWidth > 12000 ? 12000 : (desiredZoomViewWidth < _MinViewWidth ? _MinViewWidth : desiredZoomViewWidth);
//The start time of the scrollable area stays the same as before the zoom anytime!
gantt.GanttChart.SetStartTime(_ComputedStartTimeBeforeZoom);
//Center the time which was in the middle of the screen before zooming (ctrl +/-)
//OR set same time under the mouse arrow as before the zoom (ctrl scroll)
var timeOffset = this.gantt.GanttChart.ConvertTimeToX(_OffsetTimeBeforeZoom);
if (timeOffset >= 0)
{
// Set amount of pixels relative to the viewport left the same as before the zoom
if (timeOffset <= gantt.GanttChart.ViewWidth)
gantt.GanttChart.ScrollViewerElement.ScrollToHorizontalOffset(-_OffsetTimePixelsToViewportBeforeZoom + timeOffset);
else
gantt.GanttChart.ScrollViewerElement.ScrollToRightEnd();
}
}
}));
}
#endregion
Any clues on this one?
Thanks in advance!
Joachim