Rogue Wave banner
Previous fileTop of DocumentContentsIndex pageNext file
Objective Views User's Guide
Rogue Wave web site:  Home Page  |  Main Documentation Page

7.3 The CODViewport Class

The viewport contains all the logic you need to render your graphical model to the screen. It handles the drawing and printing of the model, as well as the scrolling, zooming, and panning. The viewport's main function is to update sections of the screen when the model changes. When the model changes, it informs all of its observers of the change ensuring that every viewport associated with that model receives the update message. The viewport needs only to override the creation of the controller.

7.3.1 Grid

By default, each viewport is overlaid with a grid to which the components snap. You can show or hide the grid and turn on or turn off the snap feature. You can also change the color of the grid so that it is visible against the background color of the canvas.

By default, the grid rows and columns are 1/8 inch apart. You can also change the distance. The grids in each viewport are independent of each other. Consequently, if you change the spacing or color of the grid in one viewport, the grids in other viewports will not be affected.

7.3.2 Angle Snap

Angle Snap is related to the "snap to grid" feature. When you turn on angle snap, the rotation of components is restricted to 15 degree increments.

7.3.3 Page Boundaries

Another visual aspect of the viewport is the page boundaries. The viewport checks the page settings in the model to determine how the canvas will span the paper. These boundaries are drawn over the canvas to show you how the canvas will look when you print it. You can turn off this display if you like.

7.3.4 Zoom Limits

The end-user of your application can zoom in and out on the canvas. There are limits set to this zoom factor that you can change. The default is a minimum of 5% and a maximum of 1500%.

7.3.5 Selection Handle Size

Another visual detail that you should consider is how your components appear when they are selected. The selection handles are maintained by the viewport. You can set how large they are. You can also override the methods that draw the handles to change their appearance.

7.3.6 Component Tracking

Tracking the manipulation of components is another responsibility of the viewport. When an end-user moves, rotates or scales a component, tracking places an outline around the component. The purpose of this outline is to convey how the component would look if you dropped it in its current position. The controller accomplishes tracking by interpreting the end-user's actions and then asking the viewport to draw the "ghosting" of the component.

7.3.7 Updating

The viewport observes a model. When an aspect of the model changes, it notifies all of its observers. The viewport has an OnUpdate() method that receives these notifications. Then, it determines which sections of the viewport were effected by the change and redraws them.

7.3.8 Scrolling

The CODScrollViewport class extends the CODViewport class by adding scrolling capabilities. This class uses the MvcScrollWrapper_T template class to subclass the viewport and add scrollbars.

7.3.9 Off-Screen Buffering

The CODBufferedViewport class extends the CODViewport class by adding off-screen buffering. Off-screen buffering eliminates screen flicker and improves performance by rendering the image in memory before drawing on the screen. The screen updates are reduced to a single BitBlt() or paint operation.

7.3.10 Logical Units

Logical units are abstract units stored as integers. Logical units have no real-world equivalent until they are applied to a coordinate mapping. A coordinate mapping consists of a mapping mode, window extents, and viewport extents. (See documentation for CDC::SetMapMode() in the MFC Class Library Reference for more information on mapping modes).

The coordinate mapping defines how logical units are mapped onto device units. The device resolution determines the real-world size of device units on the output device. Combining the coordinate mapping and device resolution determines the size of a logical unit on the output device. For mapping modes other than MM_ANISOTROPIC, MM_ISOTROPIC, and MM_TEXT the mapping mode alone is enough to determine the size of a logical unit on the output device. For example, MM_HIMETRIC mode specifies 1 logical unit to be 0.01 mm on the output device. The number of pixels that 1 logical unit maps to in MM_HIMETRIC mode varies based on the device resolution. For MM_ANISOTROPIC, MM_ISOTROPIC, and MM_TEXT mapping modes, the window extents and viewport extents define a ratio that maps logical units to device units. The default coordinate mapping for Objective Diagram is MM_ANISOTROPIC with the extents set at a 1:1 ratio, which is equivalent to MM_TEXT.

Given the default coordinate mapping (MM_ANISOTROPIC with 1:1 extent ratios) and a device resolution of 96 dpi, 1 logical unit is 1/96 = 0.0104167 inches.

You can experiment with mapping modes and extents using the coordinate mapping page in the diagram measurement property sheet (CODMeasurePropSheet). The size of a logical unit is displayed on the property page.

7.3.11 Coordinate Mapping

The coordinate mapping defines how logical units are mapped onto device units. A coordinate mapping consists of a mapping mode, window extents, and viewport extents. (See documentation for CDC::SetMapMode() in the MFC Class Library Reference for more information on mapping modes). The coordinate mapping can be set interactively through the Coordinate Mapping page in the Measurement property sheet. It can also be set programmatically in your CODViewport derived class. The methods for setting the coordinate mapping in the viewport are SetMapMode(), SetExtents(), and SetLogExtents(). CODViewport inherits these methods from MvcLogicalPart.

Here are the GDI equivalents of these MvcLogicalPart methods.

The default coordinate mapping is set in CODViewport::OnInitialUpdate() to the following values.

This is equivalent to MM_TEXT, where 1 logical unit equals 1 device unit (i.e. pixel). If the screen resolution is 96 dpi, then 1 logical unit will equal 0.0104167 inches on the screen.

7.3.12 Inverting the Y Axis

In order to preserve backward compatibility, in Objective Views the default direction of the Y-axis is positive Y down. Several of the Windows mapping modes such as MM_LOMETRIC, MM_HIMETRIC, MM_LOENGLISH, and MM_HIENGLISH set the orientation of the Y-axis so that it matches a Cartesian coordinate system (positive Y is up and negative Y is down). Objective Views supports both possible configurations of the Y-axis.

There are a few things that must be done in order to invert the Y-axis and use Cartesian coordinates in your Objective Views application. First, determine what your virtual bounds will be. The virtual bounds are determined by the bounds of your CODModel-derived class. One way to set the virtual bounds is to assign the origin and size of the model in the Initialize() method, as shown in Example 1.

Example 1: The CODModel Initialize method - Assigning origin and size

Note that the size along the Y-axis is specified as -2000. The size is always added to the origin, so 2000 + (-4000) yields -2000. Therefore, the range on the Y-axis is 2000 to -2000. The logical bounds can also be set as shown in Example 2.

Example 2: The CODModel Initialize() method - Setting logical bounds

Both methods of setting the virtual bounds are equally valid and produce the same result.

It is very important to note that the bounds of components are always assumed to be normalized rectangles. This means that the top of the rectangle is always less than the bottom. In other words, RECT.top < RECT.bottom regardless of the direction of the Y-axis. This is necessary because numerous Windows API functions assume normalized rectangles (such as hit testing functions). This assumption applies to any code that manipulates logical rectangles.

Next, set the direction of the Y axis to YAXIS_UP in the viewport. This can be done in the OnInitializeUpdate() method as in Example 3.

Example 3: The CODModel OnInitializeUpdate() method


In order to preserve backward compatibility, the default direction of the Y-axis is positive Y down. That is why you need to explicitly set the Y-axis direction up.

There is a method in the viewport to draw the X and Y axes called DrawAxes(). You can override DrawRect() or DrawGrid() in your CODViewport-derived class and add a call to DrawAxes() in order to see the coordinate axes.

7.3.13 Drawing Scale

The drawing scale feature allows you to specify what a given size on the output device represents. It influences how measurements are presented to the user. If you use the drawing scale to indicate that 1 inch = 1 foot, then all measurements are scaled by a factor of 12. If your mapping mode is MM_LOENGLISH (1 logical unit = 0.01 inch), then 1 logical unit would be presented to the user as 0.01 * 12 = 0.12 inches. This does not literally scale the object or zoom in. The drawing scale only determines how measurements are taken.

The default drawing scale is 1:1, so that real-world measurements in the user's domain match real-world measurements on the output device.

7.3.14 Print and Print View

Objective Views provides the print methods PreparePrinting() and EndPrinting() that can be used to override the standard MFC methods OnPreparePrinting() and OnEndPrinting(). These extended methods provide a variety of ways to print the view displayed on a canvas. The options are:

The above features are demonstrated in the Showcase sample, located at <installdir>\Samples\Views\Showcase.

The general requirements for using these features are illustrated below, using the first of new listed features as the example:



Previous fileTop of DocumentContentsNo linkNext file

Copyright © Rogue Wave Software, Inc. All Rights Reserved.

The Rogue Wave name and logo, and Stingray, are registered trademarks of Rogue Wave Software. All other trademarks are the property of their respective owners.
Provide feedback to Rogue Wave about its documentation.