ChartDirector 7.1 (C++ Edition)
Zooming and Scrolling Framework (MFC)
Introduction
The ChartDirector Zooming and Scrolling Framework is a framework for "logical zooming" of charts. "Logical zooming" means the chart is plotted with more details as it is zoomed in, but the chart objects do not necessary become bigger. The font size, line width, symbol size, etc, may remain the same. The chart may change type or use different data when it is zoomed in. For example, for a finance chart, it may start as a daily candlestick chart when the time range is long, and becomes a realtime intraday line chart when zoomed to one day.
The main elements of the ChartDirector Zooming and Scrolling Framework include a click and drag user interface to control zooming and scrolling, and a set of methods to manage axis scales. To implement a zoomable and scrollable chart, the charting code would need to be written to create the required chart type based on the axis scales.
The View Port
In the ChartDirector Zooming and Scrolling framework, the view port is used to determine which part of the data range should be plotted.
The view port can be imagined as a rectangular window over the entire XY data range. For example, suppose the full data range is 10 years in the horizontal direction. A view port width of 0.1 means only 10% of the horizontal data range should be plotted. In other words, the chart is zoomed in so that only 1 year of data is visible. The view port left side will determine exactly which year of data that is visible.
The view port position and size can be get and set using the following methods. The full data range is always assumed to be 0 to 1. So the view port position and size should be between 0 to 1.
The Zoom and Scroll User Interface
The
CChartViewer control allows using mouse actions on the chart to control zooming and scrolling. Several mouse usage modes are supported, including drag to scroll, drag to select a region to zoom into, click to zoom in, click to zoom out. They can be selected using
CChartViewer.setMouseUsage. The CChartViewer also supports using mouse wheel to control zooming, configurable using
CChartViewer.setMouseWheelZoomRatio. The zooming and scrolling direction can be horizontal only, vertical only, or both, configurable using
CChartViewer.setZoomDirection and
CChartViewer.setScrollDirection.
When the user performs zooming or scrolling operations,
CChartViewer will update the view port to reflect the new visible region. It will then emit the
CVN_ViewPortChanged message. The message handler can then redraw the chart.
The CViewPortControl
In addition to using mouse actions directly on the chart being zoomed or scrolled, ChartDirector also provides a
CViewPortControl to let the user visualize and manipulate the view port managed by the
CChartViewer.
In typical usage, the CViewPortControl displays an "overall chart" that shows the full data range, configured using
CViewPortControl.setChart, and connects to the CChartViewer using
CViewPortControl.setViewer. The CViewPortControl can then include a rectangle on the overall chart to represent the view port. The user can drag the rectangle to move the view port, which corresponds to scrolling. The user can also drag the rectangle border to resize the view port, which corresponds to zooming. In additional, the user can drag a new rectangular region as the new view port or click on a point on the overall chart to center the view port at that point. These user interactions can be configured with the methods of the
CViewPortControl.
Zoom and Scroll with External Controls
In some applications, it may be desirable to have other ways to control zooming and scrolling. For example, in finance charts, there are often buttons that allow the user to jump to certain predefined period (eg. the last 30, 90, 180 or 360 days), which are essentially a type of zooming and scrolling. Sometimes people would like to use scroll bars to control scrolling, or to use "date picker controls" to directly select the data range to display.
To perform zooming and scrolling using external controls, the controls can update the view port and then emit CVN_ViewPortChanged messages by using
CChartViewer.updateViewPort. For example, if a scroll bar is used for scrolling, in message handler of the scroll bar, it may update the view port to reflect the current scroll bar position, and then call
CChartViewer.updateViewPort.
The CVN_ViewPortChanged Message
The
CVN_ViewPortChanged message occurs when the view port is changed. In the simplest case, the message handler just needs to call the charting code to redraw the chart to reflect the changed view port.
If external controls are used, they may need to be updated to reflect the view port. For example, suppose the user can drag the chart or drag a scroll bar to scroll the chart. If the user drags the chart, the scroll bar would need to be updated too to reflect the new view port position.
In zooming and scrolling, the view port messages can be "intermediate messages". For example, in "drag to scroll", as the user drags the mouse, the view port will be updated rapidly and generate a lot of CVN_ViewPortChanged messages. These messages are "intermediate messages" because the view port is still changing. When the user finishes dragging and releases the mouse, ChartDirector will emit a CVN_ViewPortChanged message. Only this "final message" corresponds to a stable view port.
To efficiently handle intermediate messages, in the CVN_ViewPortChanged message handler,
CChartViewer.needUpdateChart and
CChartViewer.needUpdateImageMap may be used to determine if the chart and/or image map needs to be updated. For intermediate messages, ChartDirector will indicate only the chart needs update. For the final message, ChartDirector will indicate that the image map needs update. It may indicate the chart needs update if the view port has changed between the last intermediate event and the final message.
If external controls are used to control zooming and scrolling and the chart requires image map, it is suggested the external controls set the needUpdateChart and needUpdateImageMap flags properly when calling
CChartViewer.updateViewPort. However, for some controls, it may be impossible to distinguish between intermediate and final messages. One way to handle this case is to delay updating the image map until the mouse moves over the chart. It is because the image map is for configuring hot spots on the chart, so it is not needed until the mouse is over the chart.
Managing Axis Scale
The view port always assumes the full data range to be 0 to 1. In practice, a chart can have multiple x-axes and y-axes, using a combination of date/time, linear and logarithmic scales.
To facilitate conversion between the view port and the axis scale, ChartDirector includes a number of methods as follows:
In typical usage,
ViewPortManager.setFullRange is used to define the full data ranges for the axes in the chart.
ViewPortManager.getValueAtViewPort and
ViewPortManager.getViewPortAtValue can then be used to map between data values and view port positions.
ViewPortManager.syncLinearAxisWithViewPort,
ViewPortManager.syncLogAxisWithViewPort and
ViewPortManager.syncDateAxisWithViewPort can be used to synchronize the axis scale with the view port position.
If
ViewPortManager.syncLinearAxisWithViewPort,
ViewPortManager.syncLogAxisWithViewPort or
ViewPortManager.syncDateAxisWithViewPort is called without first defining the full data range, ChartDirector will automatically configure the axis scale based on the data in the chart, and assume it to be the full data range. This is useful if the full data range is not known but must be inferred from the data.
For realtime charts, new data can be added and old data can be removed. That means the full range can change. In this case, the
ViewPortManager.updateFullRangeH and
ViewPortManager.updateFullRangeV can be used to update the full range and adjust the view port to fit into the updated full range.
Zooming and Scrolling Examples
© 2023 Advanced Software Engineering Limited. All rights reserved.