Package org.geotools.swing

Source Code of org.geotools.swing.JMapFrame

/*
*    GeoTools - The Open Source Java GIS Toolkit
*    http://geotools.org
*
*    (C) 2009-2011, Open Source Geospatial Foundation (OSGeo)
*
*    This library is free software; you can redistribute it and/or
*    modify it under the terms of the GNU Lesser General Public
*    License as published by the Free Software Foundation;
*    version 2.1 of the License.
*
*    This library is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
*    Lesser General Public License for more details.
*/
package org.geotools.swing;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.Set;

import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSplitPane;
import javax.swing.JToolBar;
import javax.swing.SwingUtilities;

import net.miginfocom.swing.MigLayout;

import org.geotools.map.MapContent;
import org.geotools.swing.action.InfoAction;
import org.geotools.swing.action.NoToolAction;
import org.geotools.swing.action.PanAction;
import org.geotools.swing.action.ResetAction;
import org.geotools.swing.action.ZoomInAction;
import org.geotools.swing.action.ZoomOutAction;
import org.geotools.swing.control.JMapStatusBar;

/**
* A Swing frame containing a map display pane and (optionally) a toolbar,
* status bar and map layer table.
* <p>
* Simplest use is with the static {@link #showMap(MapContent)} method:
* <pre>{@code \u0000
* MapContent content = new MapContent();
* content.setTitle("My beautiful map");
*
* // add some layers to the MapContent...
*
* JMapFrame.showMap(content);
* }</pre>
*
* @see MapLayerTable
* @see StatusBar
*
* @author Michael Bedward
* @since 2.6
*
* @source $URL$
* @version $Id$
*/
public class JMapFrame extends JFrame {
   
    /*
     * The following toolbar button names are primarily for unit testing
     * but could also be useful for applications wanting to control appearance
     * and behaviour at run-time.
     */
   
    /** Name assigned to toolbar button for feature info queries. */
    public static final String TOOLBAR_INFO_BUTTON_NAME = "ToolbarInfoButton";
    /** Name assigned to toolbar button for map panning. */
    public static final String TOOLBAR_PAN_BUTTON_NAME = "ToolbarPanButton";
    /** Name assigned to toolbar button for default pointer. */
    public static final String TOOLBAR_POINTER_BUTTON_NAME = "ToolbarPointerButton";
    /** Name assigned to toolbar button for map reset. */
    public static final String TOOLBAR_RESET_BUTTON_NAME = "ToolbarResetButton";
    /** Name assigned to toolbar button for map zoom in. */
    public static final String TOOLBAR_ZOOMIN_BUTTON_NAME = "ToolbarZoomInButton";
    /** Name assigned to toolbar button for map zoom out. */
    public static final String TOOLBAR_ZOOMOUT_BUTTON_NAME = "ToolbarZoomOutButton";

    /**
     * Constants for available toolbar buttons used with the
     * {@link #enableTool} method.
     */
    public enum Tool {
        /**
         * Simple mouse cursor, used to unselect previous cursor tool.
         */
        POINTER,

        /**
         * The feature info cursor tool
         */
        INFO,

        /**
         * The panning cursor tool.
         */
        PAN,

        /**
         * The reset map extent cursor tool.
         */
        RESET,

        /**
         * The zoom display cursor tools.
         */
        ZOOM;
    }

    private boolean showToolBar;
    private Set<Tool> toolSet;

    /*
     * UI elements
     */
    private JMapPane mapPane;
    private MapLayerTable mapLayerTable;
    private JToolBar toolBar;

    private boolean showStatusBar;
    private boolean showLayerTable;
    private boolean uiSet;

    /**
     * Creates a new map frame with a toolbar, map pane and status
     * bar; sets the supplied {@code MapContent}; and displays the frame.
     * If {@linkplain MapContent#getTitle()} returns a non-empty string,
     * this is used as the frame's title.
     * <p>
     * This method can be called safely from any thread.
     *
     * @param content the map content
     */
    public static void showMap(final MapContent content) {
        if (SwingUtilities.isEventDispatchThread()) {
            doShowMap(content);
        } else {
            SwingUtilities.invokeLater(new Runnable() {

                @Override
                public void run() {
                    doShowMap(content);
                }
            });
        }
    }
   
    private static void doShowMap(MapContent content) {
        final JMapFrame frame = new JMapFrame(content);
        frame.enableStatusBar(true);
        frame.enableToolBar(true);
        frame.initComponents();
        frame.setSize(800, 600);
        frame.setVisible(true);
    }

    /**
     * Default constructor. Creates a {@code JMapFrame} with
     * no map content or renderer set
     */
    public JMapFrame() {
        this(null);
    }

    /**
     * Constructs a new {@code JMapFrame} object with specified map content.
     *
     * @param content the map content
     */
    public JMapFrame(MapContent content) {
        super(content == null ? "" : content.getTitle());
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        showLayerTable = false;
        showStatusBar = false;
        showToolBar = false;
        toolSet = EnumSet.noneOf(Tool.class);

        // the map pane is the one element that is always displayed
        mapPane = new JMapPane(content);
        mapPane.setBackground(Color.WHITE);
        mapPane.setBorder(BorderFactory.createLineBorder(Color.BLACK));
       
        // give keyboard focus to the map pane
        addWindowFocusListener(new WindowAdapter() {
            @Override
            public void windowGainedFocus(WindowEvent e) {
                mapPane.requestFocusInWindow();
            }
        });
       
        mapPane.addFocusListener(new FocusAdapter() {

            @Override
            public void focusGained(FocusEvent e) {
                mapPane.setBorder(BorderFactory.createLineBorder(Color.BLACK));
            }

            @Override
            public void focusLost(FocusEvent e) {
                mapPane.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY));
            }
        });
       
        mapPane.addMouseListener(new MouseAdapter() {

            @Override
            public void mousePressed(MouseEvent e) {
                mapPane.requestFocusInWindow();
            }
        });
    }

    /**
     * Sets whether to display the default toolbar (default is false).
     * Calling this with state == true is equivalent to
     * calling {@link #enableTool} with all {@link JMapFrame.Tool}
     * constants.
     *
     * @param enabled whether the toolbar is required
     */
    public void enableToolBar(boolean enabled) {
        if (enabled) {
            toolSet = EnumSet.allOf(Tool.class);
        } else {
            toolSet.clear();
        }
        showToolBar = enabled;
    }

    /**
     * This method is an alternative to {@link #enableToolBar(boolean)}.
     * It requests that a tool bar be created with specific tools, identified
     * by {@link JMapFrame.Tool} constants.
     *
     * <code><pre>
     * myMapFrame.enableTool(Tool.PAN, Tool.ZOOM);
     * </pre></code>
     *
     * Calling this method with no arguments or {@code null} is equivalent
     * to {@code enableToolBar(false)}.
     *
     * @param tool tools to display on the toolbar
     */
    public void enableTool(Tool ...tool) {
        if (tool == null || tool.length == 0) {
            enableToolBar(false);
        } else {
            toolSet = EnumSet.copyOf(Arrays.asList(tool));
            showToolBar = true;
        }
    }

    /**
     * Set whether a status bar will be displayed to display cursor position
     * and map bounds.
     *
     * @param enabled whether the status bar is required.
     */
    public void enableStatusBar(boolean enabled) {
        showStatusBar = enabled;
    }

    /**
     * Set whether a map layer table will be displayed to show the list
     * of layers in the map content and set their order, visibility and
     * selected status.
     *
     * @param enabled whether the map layer table is required.
     */
    public void enableLayerTable(boolean enabled) {
        showLayerTable = enabled;
    }

    /**
     * Calls {@link #initComponents()} if it has not already been called explicitly
     * to construct the frame's components before showing the frame.
     *
     * @param state true to show the frame; false to hide.
     */
    @Override
    public void setVisible(boolean state) {
        if (state && !uiSet) {
            initComponents();
        }

        super.setVisible(state);
    }

    /**
     * Creates and lays out the frame's components that have been
     * specified with the enable methods (e.g. {@link #enableToolBar(boolean)} ).
     * If not called explicitly by the client this method will be invoked by
     * {@link #setVisible(boolean) } when the frame is first shown.
     */
    public void initComponents() {
        if (uiSet) {
            // @todo log a warning ?
            return;
        }

        /*
         * We use the MigLayout manager to make it easy to manually code
         * our UI design
         */
        StringBuilder sb = new StringBuilder();
        if (!toolSet.isEmpty()) {
            sb.append("[]"); // fixed size
        }
        sb.append("[grow]"); // map pane and optionally layer table fill space
        if (showStatusBar) {
            sb.append("[min!]"); // status bar height
        }

        JPanel panel = new JPanel(new MigLayout(
                "wrap 1, insets 0", // layout constrains: 1 component per row, no insets

                "[grow]", // column constraints: col grows when frame is resized

                sb.toString() ));

        /*
         * A toolbar with buttons for zooming in, zooming out,
         * panning, and resetting the map to its full extent.
         * The cursor tool buttons (zooming and panning) are put
         * in a ButtonGroup.
         *
         * Note the use of the XXXAction objects which makes constructing
         * the tool bar buttons very simple.
         */
        if (showToolBar) {
            toolBar = new JToolBar();
            toolBar.setOrientation(JToolBar.HORIZONTAL);
            toolBar.setFloatable(false);

            JButton btn;
            ButtonGroup cursorToolGrp = new ButtonGroup();
           
            if (toolSet.contains(Tool.POINTER)) {
                btn = new JButton(new NoToolAction(mapPane));
                btn.setName(TOOLBAR_POINTER_BUTTON_NAME);
                toolBar.add(btn);
                cursorToolGrp.add(btn);
            }

            if (toolSet.contains(Tool.ZOOM)) {
                btn = new JButton(new ZoomInAction(mapPane));
                btn.setName(TOOLBAR_ZOOMIN_BUTTON_NAME);
                toolBar.add(btn);
                cursorToolGrp.add(btn);

                btn = new JButton(new ZoomOutAction(mapPane));
                btn.setName(TOOLBAR_ZOOMOUT_BUTTON_NAME);
                toolBar.add(btn);
                cursorToolGrp.add(btn);

                toolBar.addSeparator();
            }

            if (toolSet.contains(Tool.PAN)) {
                btn = new JButton(new PanAction(mapPane));
                btn.setName(TOOLBAR_PAN_BUTTON_NAME);
                toolBar.add(btn);
                cursorToolGrp.add(btn);

                toolBar.addSeparator();
            }

            if (toolSet.contains(Tool.INFO)) {
                btn = new JButton(new InfoAction(mapPane));
                btn.setName(TOOLBAR_INFO_BUTTON_NAME);
                toolBar.add(btn);

                toolBar.addSeparator();
            }

            if (toolSet.contains(Tool.RESET)) {
                btn = new JButton(new ResetAction(mapPane));
                btn.setName(TOOLBAR_RESET_BUTTON_NAME);
                toolBar.add(btn);
            }

            panel.add(toolBar, "grow");
        }

        if (showLayerTable) {
            mapLayerTable = new MapLayerTable(mapPane);

            /*
             * We put the map layer panel and the map pane into a JSplitPane
             * so that the user can adjust their relative sizes as needed
             * during a session. The call to setPreferredSize for the layer
             * panel has the effect of setting the initial position of the
             * JSplitPane divider
             */
            mapLayerTable.setPreferredSize(new Dimension(200, -1));
            JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
                    false,
                    mapLayerTable,
                    mapPane);
            panel.add(splitPane, "grow");

        } else {
            /*
             * No layer table, just the map pane
             */
            panel.add(mapPane, "grow");
        }

        if (showStatusBar) {
            panel.add(JMapStatusBar.createDefaultStatusBar(mapPane), "grow");
        }

        this.getContentPane().add(panel);
        uiSet = true;
    }

    /**
     * Get the map content associated with this frame.
     * Returns {@code null} if no map content has been set explicitly with the
     * constructor or {@link #setMapContent}.
     *
     * @return the current {@code MapContent} object
     */
    public MapContent getMapContent() {
        return mapPane.getMapContent();
    }

    /**
     * Set the MapContent object used by this frame.
     *
     * @param content the map content
     * @throws IllegalArgumentException if content is null
     */
    public void setMapContent(MapContent content) {
        if (content == null) {
            throw new IllegalArgumentException("map content must not be null");
        }

        mapPane.setMapContent(content);
    }

    /**
     * Provides access to the instance of {@code JMapPane} being used
     * by this frame.
     *
     * @return the {@code JMapPane} object
     */
    public JMapPane getMapPane() {
        return mapPane;
    }

    /**
     * Provides access to the toolbar being used by this frame.
     * If {@link #initComponents} has not been called yet
     * this method will invoke it.
     *
     * @return the toolbar or null if the toolbar was not enabled
     */
    public JToolBar getToolBar() {
        if (!uiSet) initComponents();
        return toolBar;
    }
}
TOP

Related Classes of org.geotools.swing.JMapFrame

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.