ChartDirector 7.1 (C++ Edition)

Zooming and Scrolling Framework (MFC)


NOTE: This section describes Zooming and Scrolling Framework for MFC only. For Qt, please refer to Zooming and Scrolling Framework (Qt).

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.

MethodDescription
ViewPortManager.getViewPortLeftGets the position of the left side of the view port.
ViewPortManager.setViewPortLeftSets the position of the left side of the view port.
ViewPortManager.getViewPortTopGets the position of the top side of the view port.
ViewPortManager.setViewPortTopSets the position of the top side of the view port.
ViewPortManager.getViewPortWidthGets the width of the view port.
ViewPortManager.setViewPortWidthSets the width of the view port.
ViewPortManager.getViewPortHeightGets the height of the view port.
ViewPortManager.setViewPortHeightSets the height of the view port.

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:

MethodDescription
ViewPortManager.setFullRangeDefines the full range of a view port data scale.
ViewPortManager.updateFullRangeHUpdates a horizontal the full range and adjust the view port accordingly.
ViewPortManager.updateFullRangeVUpdates a vertical the full range and adjust the view port accordingly.
ViewPortManager.getValueAtViewPortConverts a view port coordinate to a value of the specified data scale.
ViewPortManager.getViewPortAtValueConverts a value of the specified data scale to a view port coordinate.
ViewPortManager.syncLinearAxisWithViewPortSynchronizes a linear Axis with the part of the data scale in view port.
ViewPortManager.syncLogAxisWithViewPortSynchronizes a logarithmic Axis with the part of the data scale in view port.
ViewPortManager.syncDateAxisWithViewPortSynchronizes a date/time Axis with the part of the data scale in view port.

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

Sample CodeDescription
Simple Zooming and Scrolling (MFC)This example demonstrates a simple zoomable and scrollable chart with tooltips, using mouse click and drag to control zooming and scrolling.
Zooming and Scrolling with Track Line (1) (MFC)In addition to using mouse click and drag, this example demonstrates using a scroll bar for scrolling and mouse wheel for zooming. It also includes a track cursor that updates the legend dynamically to display the data values as the mouse cursor moves over the chart.
Zooming and Scrolling with Track Line (2) (MFC)This example extends Zooming and Scrolling with Track Line (1) (MFC) by adding date picker controls to select and display the date range. It also includes checkboxes to hide and show data series.
Zoom/Scroll with PDF Report (MFC)This example extends Zooming and Scrolling with Track Line (1) (MFC) to demonstrate creating a PDF report with multiple charts covering the entire data range.
Mega Chart Zoom/Scroll (MFC)This example demonstrates a zoomable and scrollable chart with huge datasets containing 3 x 10M data points.
Zooming and Scrolling with Viewport Control (MFC)The example extends the Zooming and Scrolling with Track Line (1) (MFC) example by replacing the scrollbar with a CViewPortControl. There is also a save button to save the chart in PNG, JPG, GIF, BMP, SVG or PDF formats.
XY Zooming and Scrolling (MFC)This example demonstrates zooming and scrolling in both horizontal and vertical directions. In addition to using mouse click and drag, this example demonstrates using a slider and a CViewPortControl to control zooming and scrolling. This example also includes a crosshair track cursor with dynamic labels on the x-axis and y-axis showing the mouse cursor position, and an image map for data point tooltips.