A view relates to the project through the class com.iver.cit.gvsig.project.documents.ProjectView. The object com.iver.cit.gvsig.project.documents.view.gui.View is created with the method createWindow() and the model is assigned to it. The model is the ProjectView document that has a MapContext associated to the MapControl and another MapContext that corresponds with the layers of MapOverview. The ToC is in reality another way to view the MapContext associated to the MapControl.
View has also a console that is used when a layer in being edited, so the user can key in the editing commands as in a CAD software.
In many extensions the first thing is to obtain the object View and from that to obtain the associated MapControl and MapContext. This is usually the entry point. With the MapContext we have already the list of layers (Flayers), search tool for the layer that we would like to work with, etc. Let?s take a look at an example:
com.iver.andami.ui.mdiManager.IWindow view = PluginServices.getMDIManager().getActiveWindow();
if (!(view instanceof View))
return;
View vista=(View)view;
IProjectView model = vista.getModel();
MapContext mapa = model.getMapContext();
MapControl mapCtrl = vista.getMapControl();
logger.debug("Comand : " + s);
if (s.equals("FULL") ) {
try {
// mapa.beginAtomicEvent();
mapa.getViewPort().setExtent(mapa.getLayers().getFullExtent());
mapa.clearAllCachingImageDrawnLayers();
vista.repaintMap();
// mapa.endAtomicEvent();
} catch (DriverException e) {
NotificationManager.addError("Error getting full extent",
e);
}
}
This portion of code comes from the com.iver.cit.gvsig.ViewControls class. It uses PluginServices.getActiveWindow() to obtain the active window. If that window is of type View, then it gets the MapContext to show a zoom of all the layers:
mapa.getViewPort().setExtent(mapa.getLayers().getFullExtent());
The most interesting classes to review to see examples of this type are:
Within the views it is very interesting to see the relationship between the MapOverview and the MapControl. We will see it next.
A MapOverview is a subclass of the MapControl, with the particularity that is linked to the MapControl within the View document. By default it is on the lower left corner, and it allows for any kind of layer to be loaded onto it and for the management of its legend. It is usually used as a locator, showing some location layers and a rectangle that shows the visible rectangle of the associated MapControl.
The MapOverview is a listener of the MapControl, so that any change in the visualisation of an area makes the MapOverview to update and show the corresponding area shown by the MapControl.
The code responsible of this behaviour is:
public void setModel(MapContext model) {
this.setMapContext(model);
model.setProjection(m_MapAssoc.getMapContext().getProjection());
m_MapAssoc.getMapContext().getViewPort().addViewPortListener(this);
getMapContext().getViewPort().addViewPortListener(this);
}
On having associated the MapOverview model, this is added as a listener to the viewPort of the main MapControl.
public void extentChanged(ExtentEvent evExtent) {
// We get the new extent of the associated FMap, so we draw our
// rectangle to show the drawing area of the other map.
repaint();
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if ((m_MapAssoc.getMapContext().getViewPort().getExtent() != null) &&
(getMapContext().getViewPort().getExtent() != null)) {
if (first) {
first = false;
repaint();
return;
}
image = new BufferedImage(this.getWidth(), this.getHeight(),
BufferedImage.TYPE_INT_ARGB);
ViewPort vp = getMapContext().getViewPort();
Rectangle2D extentView=vp.getAdjustedExtent();
ViewPort vpOrig = m_MapAssoc.getMapContext().getViewPort();
if (extent==null)
extent=vpOrig.getAdjustedExtent();
// We draw the extent of the associated map.
Graphics2D g2 = (Graphics2D) image.getGraphics();
g2.setTransform(vp.getAffineTransform());
g2.setStroke(new BasicStroke((float) vp.getDist1pixel()));
g2.setColor(Color.red);
g2.draw(extent);
g2.setColor(new Color(100,100,100,100));
g2.fill(extent);
// We draw the vertical and horizontal lines.
Point2D pRightUp = vp.toMapPoint(getWidth(), 0);
Line2D.Double linVert = new Line2D.Double(extent.getCenterX(),
extentView.getMinY(), extent.getCenterX(),
pRightUp.getY());
Line2D.Double linHoriz = new Line2D.Double(extentView.getMinX(),
extent.getCenterY(), pRightUp.getX(),
extent.getCenterY());
g2.setColor(Color.darkGray);
g2.draw(linVert);
g2.draw(linHoriz);
g.drawImage(image,0,0,this);
g2.setTransform(new AffineTransform());
extent=null;
}
}
MapOverview implements the ViewPortListener interface:
/**
* <p>Defines the interface for an object that listens to changes in a view port.</p>
*/
public interface ViewPortListener {
/**
* <p>Called when the <i>extent</i> of the view port has changed.</p>
*
* @param e an extend event object
*/
void extentChanged(ExtentEvent e);
/**
* <p>Called when the background color of the view port has changed.</p>
*
* @param e a color event object
*/
void backColorChanged(ColorEvent e);
/**
* <p>Called when the projection of the view port has changed.</p>
*
* @param e a projection event object
*/
void projectionChanged(ProjectionEvent e);
}
So that it can respond to changes of the extent of the main MapControl.
The ToC could be considered as another way to show the user the MapContext. In the ToC we can see the collection of layers that are contained by the MapContext and that are drawn over the View MapControl. The layers located below in the ToC are the first ones to be drawn and those at the top are the last ones to draw.
Other information shown by the ToC:
Most of the time, we will not need to modify the ToC behavior, except to create and/or disable the contextual menu options (those that show up when we right-click with the mouse over a particular layer or group of layers). Because of it, we will look at how the mechanism to create these menu options work first.
Example: Add contextual menu that zoom in the layer over which we click.
Firstly to do is to register an extension point for the contextual menu. This is necessary so all the contextual menus show together.
ExtensionPoints extensionPoints = ExtensionPointsSingleton.getInstance();
extensionPoints.add("View_TocActions","ZoomAlTema",new ZoomAlTemaTocMenuEntry());
The ExtensionPointsSingleton class is a record (inherits of TreeMap) where we can register classes so they can be created by the framework when needed. The idea in this case is to give an entry list of the contextual menu and of the classes that inherits the AbstractContextMenuAction. This abstract class has functions to obtain the layer over which we have clicked (if it is a layer), the MapContext associate to the ToC (useful to refresh the map, for example), to know if have click over a ?leaf? or a ?branch? (isTocItemBranch, isTocItemLeaf) in the ToC tree?
In our case, the class we have created is ZoomAlTemaTocMenuEntry, in the package com.iver.cit.gvsig.project.documents.view.toc.actions.
The code that executes upon selecting this option is:
public void execute(ITocItem item, FLayer[] selectedItems) {
if (selectedItems.length==1) {
try {
if (!selectedItems[0].isAvailable()) return;
getMapContext().zoomToExtent(selectedItems[0].getFullExtent());
} catch (com.iver.cit.gvsig.fmap.DriverException e1) {
e1.printStackTrace();
}
} else {
try {
Rectangle2D maxExtent = setMaxExtent(selectedItems);
getMapContext().zoomToExtent(maxExtent);
} catch (com.iver.cit.gvsig.fmap.DriverException e1) {
e1.printStackTrace();
}
}
}
The method execute() gets as parameters the ToC item over which we had clicked and the list of selected layers. In any case, the method more useful is getMapContext(), since it gives access to the real model of what we are looking at in the view (Layers + ViewPort).
The TOC class (com.iver.cit.gvsig.project.documents.view.toc.gui) is a panel containing the tree of layers and the main component inherits from a JTree => DnDJTree (it is added a support for drag and release, among other things).
The items representing the layers follow a Composite pattern, where the branches represent the layers and the groups of layers and the leaves represent the symbols with their corresponding descriptions. Visually they are an icon + a label.