Java tutorial
/* * Copyright (C) 2010, Emergya (http://www.emergya.es) * * @author <a href="mailto:jlrodriguez@emergya.es">Juan Lus Rodrguez</a> * @author <a href="mailto:marias@emergya.es">Mara Arias</a> * @author <a href="mailto:fario@emergya.es">Flix del Ro Beningno</a> * * This file is part of GoFleet * * This software is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This software 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * As a special exception, if you link this library with other files to * produce an executable, this library does not by itself cause the * resulting executable to be covered by the GNU General Public License. * This exception does not however invalidate any other reasons why the * executable file might be covered by the GNU General Public License. */ /* * 01/07/2009 */ package es.emergya.ui.gis; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Point; import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; import java.awt.event.ComponentListener; import java.awt.event.MouseEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.ConcurrentModificationException; import java.util.LinkedList; import java.util.List; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.JButton; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JToggleButton; import javax.swing.SwingWorker; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.gofleet.context.GoWired; import org.gofleet.internacionalization.I18n; import org.openstreetmap.gui.jmapviewer.JobDispatcher; import org.openstreetmap.gui.jmapviewer.OsmMercator; import org.openstreetmap.josm.Main; import org.openstreetmap.josm.data.coor.EastNorth; import org.openstreetmap.josm.data.coor.LatLon; import org.openstreetmap.josm.data.gpx.WayPoint; import org.openstreetmap.josm.data.osm.DataSet; import org.openstreetmap.josm.gui.MainMenu; import org.openstreetmap.josm.gui.MapMover; import org.openstreetmap.josm.gui.MapView; import org.openstreetmap.josm.gui.layer.Layer; import org.openstreetmap.josm.gui.layer.OsmDataLayer; import org.openstreetmap.josm.gui.layer.markerlayer.Marker; import org.openstreetmap.josm.gui.layer.markerlayer.MarkerLayer; import org.openstreetmap.josm.gui.preferences.ToolbarPreferences; import es.emergya.actions.Authentication; import es.emergya.actions.UsuarioAdmin; import es.emergya.bbdd.bean.HistoricoGPS; import es.emergya.bbdd.bean.Incidencia; import es.emergya.bbdd.bean.Recurso; import es.emergya.bbdd.bean.Usuario; import es.emergya.cliente.constants.LogicConstants; import es.emergya.consultas.IncidenciaConsultas; import es.emergya.consultas.RecursoConsultas; import es.emergya.consultas.UsuarioConsultas; import es.emergya.ui.gis.layers.MapViewerLayer; import es.emergya.ui.gis.markers.CustomMarker; import es.emergya.ui.gis.markers.CustomMarker.Type; import es.emergya.ui.gis.paintingThreads.Updatable; import es.emergya.ui.plugins.LayerSelectionDialog; import es.emergya.ui.plugins.ZoomPerformed; /** * Extends the functionality of {@link MapView} Allowing access to some private * or protected methods, limiting the zoom scale to osm zoom factor equivalents * and enabling rotation operation * * @author fario */ public class CustomMapView extends MapView implements RotatableView, MapMoveListener, ZoomPerformed, Contextful, ICustomMapView { // Constantes de utilidad private static final double PI2 = Math.PI * 2; private static final double PI_MEDIO = Math.PI / 2; /** Distancia (EastNorthing) minimo a partir del cual se seguira un marcador */ private static final double FOLLOW_THRESSHOLD = Double.parseDouble(LogicConstants.get("FOLLOW_THRESSHOLD")); // in // eastnorthing // units private static final Log log = LogFactory.getLog(CustomMapView.class); public double fps = 2; // solo util para la obu private static final long serialVersionUID = 734833313834536432L; /** factor de zoom de mapnik */ protected int zoomFactor; /** limites de zoom la capa raster base */ protected int minZoom = LogicConstants.getInt("MIN_TILE_ZOOM"), maxZoom = LogicConstants.getInt("MAX_TILE_ZOOM"); // por defecto, // luego se les // da // valores /** Giro actual */ protected double angle; protected double sin, cos = 1; // es util tenerlos a mano, Math.sin/cos son // lentos /** * Este marcador estara siempre en el centro del mapa y si se mueve el mapa * lo seguira */ protected Marker follow; /** * Hacer zoom a una distancia apropiada para que * {@link CustomMapView#follow} se vea */ protected boolean autoZoom = true; /** Girar en la direccion en la que {@link CustomMapView#follow} se mueve */ protected boolean autoTurn = true; /** Suavizar el giro si autoTurn esta activado */ protected boolean smoothTurn = true; /** Ultima posicion de {@link CustomMapView#follow} */ private EastNorth lastFollowPos; // se usa para ver en que direccion se // mueve /** Ultima direccion en la que se movia {@link CustomMapView#follow} */ private double lastFollowAngle = 0; // se usa para hacer smoothTurn /** La distancia que se movio {@link CustomMapView#follow} la ultima vez */ private double lastDistance = 0; // se usa para hacer autoZoom protected Updater positionUpdater; protected JPanel layerControlPanel; // controles para mostrar/ocultar capas protected LayerSelectionDialog layerDialog; // protected JPanel controlPanel; // Diversos controles // protected ZoomControlPanel zoom; // controles para hacer zoom // contiene los botones de layerControlPanel, para poder ocultarlos o // mostrarlos protected JPanel zoom; protected List<JToggleButton> layerControls; protected ActionListener layerControlListener = new LayerControl(); // lista de callbacks para movimiento y zoom (se necesitan para implementar // los listeners protected List<MapMoveListener.MapMovedCallback> movedCallbacks = new ArrayList<MapMovedCallback>(); protected List<ZoomPerformed.ZoomCallback> zoomedCallbacks = new ArrayList<ZoomCallback>(); protected JPopupMenu contextMenu; // metodos de utilidad de josm /** * Use this to register shortcuts to */ public final JPanel contentPane = new JPanel(new BorderLayout()); /** * The MOTD Layer. */ // private GettingStarted gettingStarted = new GettingStarted(); /** * The main menu bar at top of screen. */ public final MainMenu menu; /* * (non-Javadoc) * * @see es.emergya.ui.gis.ICustomMapView#getMenu() */ @Override public MainMenu getMenu() { return menu; } /* * (non-Javadoc) * * @see es.emergya.ui.gis.ICustomMapView#getContentPane() */ @Override public JPanel getContentPane() { return contentPane; } /* * (non-Javadoc) * * @see es.emergya.ui.gis.ICustomMapView#getPanel() */ @Override public JPanel getPanel() { return panel; } /* * (non-Javadoc) * * @see es.emergya.ui.gis.ICustomMapView#setPanel(javax.swing.JPanel) */ @Override public void setPanel(JPanel panel) { this.panel = panel; } public JPanel panel = new JPanel(new BorderLayout()); /** * The toolbar preference control to register new actions. */ public ToolbarPreferences toolbar; @GoWired public I18n i18n; /** * @return the i18n */ public I18n getI18n() { return i18n; } /** * @param i18n the i18n to set */ public void setI18n(I18n i18n) { this.i18n = i18n; } public CustomMapView() { super(); menu = new MainMenu(); contentPane.add(panel, BorderLayout.CENTER); // iniciar los controles mostrar/ocultar capas layerControls = new LinkedList<JToggleButton>(); JToggleButton botonMostrarOcultarBotones = new JToggleButton(getI18n().getString("map.layers.hideButtons"), LogicConstants.getIcon("capas_button_mostrar"), false); botonMostrarOcultarBotones.setSelected(true); botonMostrarOcultarBotones.setActionCommand("#hide"); // b.setVerticalTextPosition(SwingConstants.BOTTOM); // b.setHorizontalTextPosition(SwingConstants.CENTER); botonMostrarOcultarBotones.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { JToggleButton b = (JToggleButton) e.getSource(); if (e.getActionCommand().equals("#hide")) { layerControlPanel.removeAll(); layerControlPanel.add(Box.createHorizontalStrut(10)); layerControlPanel.add(b); b.setActionCommand("#show"); b.setText(getI18n().getString("map.layers.showButtons")); } else { layerControlPanel.removeAll(); layerControlPanel.add(Box.createHorizontalStrut(10)); for (JToggleButton bt : layerControls) { layerControlPanel.add(bt); layerControlPanel.add(Box.createHorizontalGlue()); } b.setActionCommand("#hide"); b.setText(getI18n().getString("map.layers.hideButtons")); } layerControlPanel.updateUI(); } }); layerControls.add(botonMostrarOcultarBotones); final JToggleButton botonTodoasLasCapas = new JToggleButton(getI18n().getString("map.layers.allLayers"), LogicConstants.getIcon("capas_button_mostrar"), false); layerDialog = new LayerSelectionDialog(this); layerDialog.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { botonTodoasLasCapas.setSelected(false); } }); botonTodoasLasCapas.setSelected(false); botonTodoasLasCapas.setActionCommand("#all"); // all.setVerticalTextPosition(SwingConstants.BOTTOM); // all.setHorizontalTextPosition(SwingConstants.CENTER); botonTodoasLasCapas.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { layerDialog.setLocationRelativeTo((Component) e.getSource()); layerDialog.setVisible(!layerDialog.isShowing()); } }); layerControls.add(botonTodoasLasCapas); layerControlPanel = new JPanel(); layerControlPanel.setLayout(new BoxLayout(layerControlPanel, BoxLayout.X_AXIS)); Main.main.menu = this.menu; toolbar = new ToolbarPreferences(); toolbar.refreshToolbarControl(); // toolbar.control.updateUI(); // contentPane.add(toolbar.control, BorderLayout.NORTH); contentPane.updateUI(); panel.updateUI(); } /* * (non-Javadoc) * * @see * es.emergya.ui.gis.ICustomMapView#addLayer(org.openstreetmap.josm.gui. * layer.Layer, boolean) */ @Override public void addLayer(Layer layer, boolean showOnButtonList) { addLayer(layer, showOnButtonList, 0); } /* * (non-Javadoc) * * @see * es.emergya.ui.gis.ICustomMapView#addLayer(org.openstreetmap.josm.gui. * layer.Layer, boolean, int) */ @Override public void addLayer(Layer layer, boolean showOnButtonList, int pos) { if (layer instanceof MapViewerLayer) { minZoom = Math.max(((MapViewerLayer) layer).getMinZoomLevel(), getMinZoom()); maxZoom = Math.min(((MapViewerLayer) layer).getMaxZoomLevel(), getMaxZoom()); if (zoomFactor > maxZoom || zoomFactor < minZoom) { zoomFactor = (maxZoom + minZoom) / 2; } zoomTo(center, zoom2Scale(zoomFactor)); } if (showOnButtonList) { JToggleButton b = new JToggleButton(layer.name, LogicConstants.getIcon("capas_button_" + layer.name.toLowerCase()), layer.visible); // b.setVerticalTextPosition(SwingConstants.BOTTOM); // b.setHorizontalTextPosition(SwingConstants.CENTER); b.setActionCommand(layer.name); b.addActionListener(layerControlListener); layerControls.add(b); layerControlPanel.removeAll(); layerControlPanel.add(Box.createHorizontalStrut(10)); for (JToggleButton bt : layerControls) { layerControlPanel.add(bt); layerControlPanel.add(Box.createHorizontalGlue()); } layerControlPanel.updateUI(); } super.addLayer(layer, pos); } /* * (non-Javadoc) * * @see * es.emergya.ui.gis.ICustomMapView#addLayer(org.openstreetmap.josm.gui. * layer.Layer, boolean, java.lang.String) */ @Override public void addLayer(Layer layer, boolean showOnButtonList, String icon) { if (layer instanceof MapViewerLayer) { minZoom = Math.max(((MapViewerLayer) layer).getMinZoomLevel(), getMinZoom()); maxZoom = Math.min(((MapViewerLayer) layer).getMaxZoomLevel(), getMaxZoom()); if (zoomFactor > maxZoom || zoomFactor < minZoom) { zoomFactor = (maxZoom + minZoom) / 2; } zoomTo(center, zoom2Scale(zoomFactor)); } if (showOnButtonList) { JToggleButton b = new JToggleButton(layer.name, LogicConstants.getIcon(icon), layer.visible); // b.setVerticalTextPosition(SwingConstants.BOTTOM); // b.setHorizontalTextPosition(SwingConstants.CENTER); b.setActionCommand(layer.name); b.addActionListener(layerControlListener); layerControls.add(b); layerControlPanel.removeAll(); layerControlPanel.add(Box.createHorizontalStrut(10)); for (JToggleButton bt : layerControls) { layerControlPanel.add(bt); layerControlPanel.add(Box.createHorizontalGlue()); } layerControlPanel.updateUI(); } super.addLayer(layer); } /* * (non-Javadoc) * * @see * es.emergya.ui.gis.ICustomMapView#addLayer(org.openstreetmap.josm.gui. * layer.Layer) */ @Override public void addLayer(Layer layer) { addLayer(layer, true); } /* * (non-Javadoc) * * @see * es.emergya.ui.gis.ICustomMapView#setActiveLayer(org.openstreetmap.josm * .gui.layer.Layer) */ @Override public void setActiveLayer(Layer layer) { // modificado para que no pete if (!getAllLayers().contains(layer)) { throw new IllegalArgumentException("Layer must be in layerlist"); } if (layer instanceof OsmDataLayer) { editLayer = (OsmDataLayer) layer; Main.ds = editLayer.data; } else { Main.ds.setSelected(); } DataSet.fireSelectionChanged(Main.ds.getSelected()); Layer old = getActiveLayer(); setActiveLayerReflect(layer); if (old != layer) { for (Layer.LayerChangeListener l : Layer.listeners) { l.activeLayerChange(old, layer); } } repaint(); } /* * (non-Javadoc) * * @see es.emergya.ui.gis.ICustomMapView#zoomToEditLayerBoundingBox() */ @Override public boolean zoomToEditLayerBoundingBox() { return false; } /** * Tries to bypass private field declaration for activeLayer field * * @param layer */ private void setActiveLayerReflect(Layer layer) { activeLayer = layer; } /* * (non-Javadoc) * * @see * es.emergya.ui.gis.ICustomMapView#zoomTo(org.openstreetmap.josm.data.coor * .EastNorth, double) */ @Override public void zoomTo(EastNorth newCenter, double scale) { int factor = zoomFactor; if (this.scale > scale) { if (zoomFactor == getMaxZoom()) { return; } factor = Math.min(zoomFactor + 1, getMaxZoom()); } else if (this.scale < scale) { if (zoomFactor == getMinZoom()) { return; } factor = Math.max(zoomFactor - 1, getMinZoom()); } zoomToFactor(newCenter, factor); } /* * (non-Javadoc) * * @see es.emergya.ui.gis.ICustomMapView#setAutoZoom(boolean) */ @Override public void setAutoZoom(boolean autoZoom) { this.autoZoom = autoZoom; } /* * (non-Javadoc) * * @see es.emergya.ui.gis.ICustomMapView#setAutoTurn(boolean) */ @Override public void setAutoTurn(boolean autoTurn) { this.autoTurn = autoTurn; } /* * (non-Javadoc) * * @see es.emergya.ui.gis.ICustomMapView#setSmoothTurn(boolean) */ @Override public void setSmoothTurn(boolean smoothTurn) { this.smoothTurn = smoothTurn; } /* * (non-Javadoc) * * @see * es.emergya.ui.gis.ICustomMapView#setContextMenu(javax.swing.JPopupMenu) */ @Override public void setContextMenu(JPopupMenu contextMenu) { this.contextMenu = contextMenu; } /* * (non-Javadoc) * * @see es.emergya.ui.gis.ICustomMapView#showMenu(java.awt.Component, int, * int) */ @Override public void showMenu(Component parent, int x, int y) { if (this.contextMenu != null) { // si hay contextmenu this.contextMenu.show(parent, x, y); } } /* * (non-Javadoc) * * @see es.emergya.ui.gis.ICustomMapView#zoomPerformed() */ @Override public void zoomPerformed() { JobDispatcher.getInstance().cancelOutstandingJobs(); updateMarkers(); for (ZoomCallback zc : zoomedCallbacks) { zc.action(); } } /* * (non-Javadoc) * * @see es.emergya.ui.gis.ICustomMapView#addCallback(es.emergya.ui.plugins. * ZoomPerformed.ZoomCallback) */ @Override public void addCallback(ZoomCallback zcb) { if (!zoomedCallbacks.contains(zcb)) { zoomedCallbacks.add(zcb); } } // @Override // public void clearCallbacks() { zoomedCallbacks.clear(); } /* * (non-Javadoc) * * @see * es.emergya.ui.gis.ICustomMapView#removeCallback(es.emergya.ui.plugins * .ZoomPerformed.ZoomCallback) */ @Override public boolean removeCallback(ZoomCallback zcb) { return zoomedCallbacks.remove(zcb); } /* * (non-Javadoc) * * @see * es.emergya.ui.gis.ICustomMapView#zoomToFactor(org.openstreetmap.josm. * data.coor.EastNorth, int) */ @Override public void zoomToFactor(EastNorth newCenter, int zoomFactor) { if (zoomFactor < getMinZoom() || zoomFactor > getMaxZoom()) { return; } this.zoomFactor = zoomFactor; super.zoomTo(newCenter, zoom2Scale(zoomFactor)); } /* * (non-Javadoc) * * @see * es.emergya.ui.gis.ICustomMapView#zoomToFactor(org.openstreetmap.josm. * data.coor.EastNorth, int, double) */ @Override public void zoomToFactor(EastNorth newCenter, int zoomFactor, double angle) { this.angle = normalizeAngle(angle); this.sin = Math.sin(angle); this.cos = Math.cos(angle); this.zoomToFactor(newCenter, zoomFactor); } /* * (non-Javadoc) * * @see * es.emergya.ui.gis.ICustomMapView#zoomTo(org.openstreetmap.josm.data.coor * .EastNorth, double, double) */ @Override public void zoomTo(EastNorth newCenter, double scale, double angle) { this.angle = normalizeAngle(angle); this.sin = Math.sin(angle); this.cos = Math.cos(angle); this.zoomTo(newCenter, scale); } /** * @param angle * @return el equivalente a angle entre 0 y 2*PI */ private double normalizeAngle(double angle) { while (angle > PI2) { angle -= PI2; } while (angle < -PI2) { angle += PI2; } return angle; } /* * (non-Javadoc) * * @see es.emergya.ui.gis.ICustomMapView#paint(java.awt.Graphics) */ @Override public void paint(Graphics g) { Main.mapView = this; if (follow != null) { follow(); } try { super.paint(g); // Esto ya llama a paintComponents } catch (ConcurrentModificationException ex) { log.warn("Redibujando, datos aun no cargados..."); return; } // ============= DEBUG DEBAJO DE ESTA LINEA ================ // g.drawString( // "zoom: " + zoomFactor + ", angle:" + Math.toDegrees(angle), // 300, 15); // g.drawString((Runtime.getRuntime().freeMemory() / (1024 * 1024)) // + "M / " + (Runtime.getRuntime().totalMemory() / (1024 * 1024)) // + "M", 20, getHeight() - 5); // Rectangle r = getBoundingBox(); // // g.drawRect(r.x + 200, r.y + 200, r.width - 400, r.height - 400); // LatLon tl, br; // tl = getLatLon(r.x, r.y); // br = getLatLon(r.x + r.width, r.y + r.height); // UTM u = new UTM(); // // EastNorth etl = u.latlon2eastNorth(tl); // // EastNorth ebr = u.latlon2eastNorth(br); // EastNorth etl = Main.proj.latlon2eastNorth(tl); // EastNorth ebr = Main.proj.latlon2eastNorth(br); // Point pmi, pma; // pmi = getPoint(etl); // pma = getPoint(ebr); // Rectangle draw = new Rectangle(pmi.x, pma.y, pma.x - pmi.x, pma.y - // pmi.y); // g.setColor(Color.GREEN); // g.drawRect(draw.x + 201, draw.y + 201, draw.width - 402, draw.height // - 402); // g.drawString("+ " + draw, getWidth() / 2, 300); // g.setColor(Color.RED); // g.drawRect(200, 200, getWidth() - 400, getHeight() - 400); // g.setColor(Color.RED); // Point p = getPoint(Main.proj.latlon2eastNorth(getLatLon(getWidth() / // 2, // getHeight() / 2 - 200))); // g.fillOval(p.x - 10, p.y - 10, 20, 20); // g.setColor(Color.BLACK); // g.fillRect(getWidth() / 2 - 5, getHeight() / 2 - 5, 10, 10); // EastNorth mi = getEastNorth(0, getHeight() - 1); // EastNorth ma = getEastNorth(getWidth() - 1, 0); // Point pmi, pma; // pmi = getPoint(mi); // pma = getPoint(ma); // Rectangle r = new Rectangle(pmi.x, pma.y, pma.x - pmi.x, pmi.y - // pma.y); // g.drawString("+ " + r, getWidth() / 2, 300); // g.drawRect(r.x + 200, r.y + 200, r.width - 400, r.height - 400); // LatLon ll = getLatLon(getWidth()/2, getHeight()/2); // g.drawString("+ " + ll.lat() + " x " + ll.lon(), getWidth()/2, // getHeight()/2); // drawCompass(g); } /* * (non-Javadoc) * * @see es.emergya.ui.gis.ICustomMapView#updateMousePosition() */ @Override public void updateMousePosition() { } private Thread turner; // se usa para el giro suave /** * Si algun {@link Marker} esta en {@link CustomMapView#follow} lo sigue, * gira y hace zoom si corresponde. */ protected void follow() { if (lastFollowPos == null) { lastFollowPos = follow.eastNorth; } else { // distancias double dy = follow.eastNorth.getY() - lastFollowPos.getY(); double dx = follow.eastNorth.getX() - lastFollowPos.getX(); // si se ha movido lo bastante... if (Math.abs(dx) > FOLLOW_THRESSHOLD || Math.abs(dy) > FOLLOW_THRESSHOLD) { if (autoTurn) { double na = Math.atan2(dy, dx); na -= lastFollowAngle; // Normalize the angle if (na < -Math.PI) { na += PI2; } if (na > Math.PI) { na -= PI2; } if (smoothTurn) { final double target = na; // para usarlo enel thread if (turner != null && turner.isAlive()) // paramos el // thread si // vamos a girar // otra vez { turner.interrupt(); } turner = new Thread(new Runnable() { public void run() { double na = target; while (Math.abs(na) > 0) { // vamos girando 0.5 // de lo que // queremos na /= 2; lastFollowAngle += na; zoomToFactor(center, zoomFactor, PI_MEDIO - lastFollowAngle); try { Thread.sleep(60); } catch (InterruptedException e) { } } } }); turner.start(); } else { lastFollowAngle += na; // giro brusco } // Normalize the angle if (lastFollowAngle < 0) { lastFollowAngle += PI2; } if (lastFollowAngle > PI2) { lastFollowAngle -= PI2; } } else { lastFollowAngle = -getAngle() + PI_MEDIO; // deshacemos el // giro si no se // gira } if (autoZoom) { // Adjusts the current zoom factor to match an appropiate // zoom // level for the speed of the followed object double dist = (lastDistance + Main.proj.eastNorth2latlon(follow.eastNorth) .greatCircleDistance(Main.proj.eastNorth2latlon(lastFollowPos))) / 2; LatLon ll1 = getLatLon(0, 0); LatLon ll2 = getLatLon((int) (40 / fps), 0); double sampledist = ll1.greatCircleDistance(ll2); // get a // sample distance of 20px on the screen if (dist > sampledist * 1.5) { // if we move more than +-50% // of 20px -> zoom out zoomFactor = Math.max(zoomFactor - 1, getMinZoom()); ; } else if (dist < sampledist * 0.5) { // if we move less // than +-50% of // 20px -> zoom in zoomFactor = Math.min(zoomFactor + 1, getMaxZoom()); ; } lastDistance = dist; } zoomToFactor(follow.eastNorth, zoomFactor, PI_MEDIO - lastFollowAngle); lastFollowPos = new EastNorth(follow.eastNorth.east(), follow.eastNorth.north()); // zoomTo(follow.eastNorth, getScale(), PI_MEDIO - // lastFollowAngle); } } } /** * Dibuja una brujula apuntando al norte * * @param g */ @SuppressWarnings("unused") private void drawCompass(Graphics g) { int x = 50, y = getHeight() - 50; // ((Graphics2D)g).rotate(Math.PI + lastFollowAngle, x, y); ((Graphics2D) g).rotate(-PI_MEDIO - getAngle(), x, y); g.setColor(Color.LIGHT_GRAY); g.fillOval(0, getHeight() - 100, 100, 100); g.setColor(Color.BLACK); g.fillRect(x - 3, y - 3, 50, 6); g.setColor(Color.RED); g.fillRect(x + 42, y - 3, 6, 6); } /* * (non-Javadoc) * * @see es.emergya.ui.gis.ICustomMapView#zoom() */ @Override public int zoom() { return zoomFactor; } /* * (non-Javadoc) * * @see es.emergya.ui.gis.ICustomMapView#zoom2Scale(int) */ @Override public double zoom2Scale(int zoom) { return Math.max(world.east() / OsmMercator.falseEasting(zoom), world.north() / OsmMercator.falseNorthing(zoom)); } /* * (non-Javadoc) * * @see es.emergya.ui.gis.ICustomMapView#getMinZoom() */ @Override public int getMinZoom() { return minZoom; } /* * (non-Javadoc) * * @see es.emergya.ui.gis.ICustomMapView#getMaxZoom() */ @Override public int getMaxZoom() { return maxZoom; } /* * (non-Javadoc) * * @see es.emergya.ui.gis.ICustomMapView#setInitAdapter(es.emergya.ui.gis. * CustomMapView.InitAdapter) */ public void setInitAdapter(InitAdapter initAdapter) { for (ComponentListener l : this.getComponentListeners()) { this.removeComponentListener(l); } this.addComponentListener(initAdapter); } /* * (non-Javadoc) * * @see es.emergya.ui.gis.ICustomMapView#setDefaultInitAdapter() */ @Override public void setDefaultInitAdapter() { setInitAdapter(new InitAdapter()); } /* * (non-Javadoc) * * @see es.emergya.ui.gis.ICustomMapView#rotate(double) */ @Override public void rotate(double r) { angle += r; if (r > Math.PI * 2) { angle -= Math.PI * 2; } if (r < -Math.PI * 2) { angle += Math.PI * 2; } sin = Math.sin(getAngle()); cos = Math.cos(getAngle()); repaint(); } /* * (non-Javadoc) * * @see es.emergya.ui.gis.ICustomMapView#getAngle() */ @Override public double getAngle() { return angle; } /* * (non-Javadoc) * * @see * es.emergya.ui.gis.ICustomMapView#setFollow(org.openstreetmap.josm.gui * .layer.markerlayer.Marker) */ @Override public void setFollow(Marker m) { this.follow = m; this.lastFollowPos = m.eastNorth; } /* * (non-Javadoc) * * @see * es.emergya.ui.gis.ICustomMapView#getPoint(org.openstreetmap.josm.data * .coor.EastNorth) */ @Override public Point getPoint(EastNorth p) { Point pt = super.getPoint(p); return translateR(pt.x, pt.y); } /* * (non-Javadoc) * * @see es.emergya.ui.gis.ICustomMapView#getEastNorth(int, int) */ @Override public EastNorth getEastNorth(int x, int y) { Point p = translate(x, y); return super.getEastNorth(p.x, p.y); } /* * (non-Javadoc) * * @see es.emergya.ui.gis.ICustomMapView#getLatLon(int, int) */ @Override public LatLon getLatLon(int x, int y) { Point p = translate(x, y); return super.getLatLon(p.x, p.y); } /* * (non-Javadoc) * * @see es.emergya.ui.gis.ICustomMapView#getBoundingBox() */ @Override public Rectangle getBoundingBox() { int minx = 0; int miny = 0; int maxx = getWidth(); int maxy = getHeight(); Point p0 = translateR(minx, miny);// tl Point p1 = translateR(minx, maxy);// bl Point p2 = translateR(maxx, maxy);// br Point p3 = translateR(maxx, miny);// tr int[] x = { p0.x, p1.x, p2.x, p3.x }; Arrays.sort(x); int[] y = { p0.y, p1.y, p2.y, p3.y }; Arrays.sort(y); return new Rectangle(x[0], y[0], x[x.length - 1] - x[0], y[y.length - 1] - y[0]); } /** * Returns the position of the point rotated the current rotation from the * center */ private Point translate(Point p) { return translate(p.x, p.y); } /** * Returns the position of the point rotated the oposite to the current * rotation from the center */ private Point translateR(int x, int y) { double x0 = getWidth() / 2; double y0 = getHeight() / 2; double nx = x0 + cos * (x - x0) + sin * (y - y0); double ny = y0 - sin * (x - x0) + cos * (y - y0); return new Point((int) nx, (int) ny); } /** * Returns the position of the point rotated the current rotation from the * center */ private Point translate(int x, int y) { int x0 = getWidth() >> 1; int y0 = getHeight() >> 1; double nx = x0 + cos * (x - x0) - sin * (y - y0); double ny = y0 + sin * (x - x0) + cos * (y - y0); return new Point((int) nx, (int) ny); } public class InitAdapter extends ComponentAdapter { @Override public void componentResized(ComponentEvent e) { removeComponentListener(this); setMouseListeners(); initControlPanels(); setResizeListeners(); // startPositionUpdater(); zoomPerformed(); } protected void setMouseListeners() { MapMover m = new MapMover(CustomMapView.this, CustomMapView.this.contentPane); m.setPanButton(MouseEvent.BUTTON1); } protected void startPositionUpdater() { positionUpdater = new Updater(); new Thread(positionUpdater).start(); } protected void setResizeListeners() { CustomMapView.this.addComponentListener(new ComponentAdapter() { @Override public void componentResized(ComponentEvent e) { super.componentResized(e); int h = e.getComponent().getHeight(); int w = e.getComponent().getWidth(); layerControlPanel.setBounds(0, h - 100, w, 100); // controlPanel.setBounds(0, 0, w, // controlPanel.getHeight()); zoom.setBounds(zoom.getX(), zoom.getY(), zoom.getWidth(), zoom.getHeight()); layerControlPanel.updateUI(); zoom.updateUI(); } }); } protected void initControlPanels() { // zoom = new ZoomControlPanel(CustomMapView.this); // add(zoom); // zoom.setBounds(0, 0, getWidth(), 100); zoom = new JPanel(new BorderLayout()); zoom.setOpaque(false); zoom.setLayout(new BoxLayout(zoom, BoxLayout.Y_AXIS)); JButton in = new JButton(LogicConstants.getIcon("map_button_zoommas")); in.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { zoomToFactor(getCenter(), zoom() + 1); } }); zoom.add(in, BorderLayout.NORTH); JPanel foo = new JPanel(); foo.setOpaque(false); foo.add(new ZoomMapSlider(CustomMapView.this)); zoom.add(foo, BorderLayout.CENTER); JButton out = new JButton(LogicConstants.getIcon("map_button_zoommenos")); out.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { zoomToFactor(getCenter(), zoom() - 1); } }); zoom.add(out, BorderLayout.SOUTH); add(zoom); zoom.setBounds(0, 10, 70, 270); // controlPanel = new ControlPanel(CustomMapView.this); // // add(controlPanel); // controlPanel.setBounds(0, 0, getWidth(), 40); layerDialog.init(); layerControlPanel.setOpaque(false); layerControlPanel.removeAll(); layerControlPanel.add(Box.createHorizontalStrut(10)); for (JToggleButton bt : layerControls) { layerControlPanel.add(bt); layerControlPanel.add(Box.createHorizontalGlue()); } add(layerControlPanel); layerControlPanel.setBounds(0, getHeight() - 100, getWidth(), 100); } } /** * Cambia la visibilidad de los botones de * {@link CustomMapView#layerControlPanel} * * @author fario * */ private class LayerControl implements ActionListener { @Override public void actionPerformed(ActionEvent e) { try { boolean status = false; final String nombreCapa = e.getActionCommand(); for (Layer l : getAllLayers()) { if (l.name.indexOf(nombreCapa) == 0) { l.visible = !l.visible; status = l.visible; updateMarkers(); } } // vehiculos_visibles // personas_visibles // incidencias_visibles String capa_incidences = getI18n().getString("Incidences.incidences"); String capa_vehiculos = getI18n().getString("Resources.resources.vehicles"); String capa_people = getI18n().getString("Resources.resources.people"); Usuario u = UsuarioConsultas.find(Authentication.getUsuario().getNombreUsuario()); if (u != null) { if (nombreCapa.equalsIgnoreCase(capa_incidences)) u.setIncidenciasVisibles(status); else if (nombreCapa.equalsIgnoreCase(capa_vehiculos)) u.setVehiculosVisibles(status); else if (nombreCapa.equalsIgnoreCase(capa_people)) u.setPersonasVisibles(status); UsuarioAdmin.saveOrUpdate(u); } } catch (Throwable t) { log.error("Error actualizando el estado de la capa", t); } } }; /** * Actualiza la capa con marcadores que simulan vehiculos que se mueven * * @author fario * */ @Deprecated private class Updater implements Runnable { private boolean running = true; @Override public void run() { running = true; while (running) { // if(System.currentTimeMillis() - time > 1000/fps){ // buscar todos los markers que son updatable en todas las // marker layers for (Layer l : getAllLayers()) { if (l instanceof MarkerLayer) { for (Marker m : ((MarkerLayer) l).data) { if (m instanceof Updatable) { ((Updatable) m).update(); } } } } repaint(); // } else { try { Thread.sleep((long) (1000 / fps)); } catch (InterruptedException e) { e.printStackTrace(); } // } } } public void stop() { this.running = false; } } /* * (non-Javadoc) * * @see es.emergya.ui.gis.ICustomMapView#movementEnded() */ @Override public void movementEnded() { updateMarkers(); for (MapMovedCallback m : this.movedCallbacks) { m.action(); } } /* * (non-Javadoc) * * @see es.emergya.ui.gis.ICustomMapView#movementStarted() */ @Override public void movementStarted() { } ; /* * (non-Javadoc) * * @see es.emergya.ui.gis.ICustomMapView#addCallback(es.emergya.ui.gis. * MapMoveListener.MapMovedCallback) */ @Override public void addCallback(MapMovedCallback mmc) { if (!this.movedCallbacks.contains(mmc)) { this.movedCallbacks.add(mmc); } } /* * (non-Javadoc) * * @see es.emergya.ui.gis.ICustomMapView#clearCallbacks() */ @Override public void clearCallbacks() { this.movedCallbacks.clear(); this.zoomedCallbacks.clear(); } /* * (non-Javadoc) * * @see es.emergya.ui.gis.ICustomMapView#removeCallback(es.emergya.ui.gis. * MapMoveListener.MapMovedCallback) */ @Override public boolean removeCallback(MapMovedCallback mmc) { return this.movedCallbacks.remove(mmc); } // Separate threads to reload the markers private SwingWorker<Object, Object> mapUpdater; /* * (non-Javadoc) * * @see es.emergya.ui.gis.ICustomMapView#updateMarkers() */ @Override public void updateMarkers() { Rectangle r = getBoundingBox(); final LatLon tl, br; // tomamos los pois en un area de 3 pantallas cuadradas, de manera que // se pueda arrastrar sin notar que no estan cargados los poi de mas // all, ya que solo se deberian cargar cuando deja de moverse. tl = getLatLon(r.x - r.width, r.y - r.height); br = getLatLon(r.x + 2 * r.width, r.y + 2 * r.height); if (mapUpdater == null || mapUpdater.isDone()) { mapUpdater = new SwingWorker<Object, Object>() { @Override protected Object doInBackground() throws Exception { try { updateIncidences(tl, br); updateResources(tl, br); } catch (Throwable t) { log.error("Error al actualizar marcadores", t); } return null; } @Override protected void done() { repaint(); } }; mapUpdater.execute(); } } private void updateResources(final LatLon topleft, final LatLon bottomright) { MarkerLayer people = null, vehicles = null; // tomar las capas vehiculo y persona for (Layer l : getAllLayers()) { if (l.name.equalsIgnoreCase(getI18n().getString("Resources.resources.people"))) { people = (MarkerLayer) l; } if (l.name.equalsIgnoreCase(getI18n().getString("Resources.resources.vehicles"))) { vehicles = (MarkerLayer) l; } if (people != null && vehicles != null) { break; } } if (getParent() instanceof IMapViewer) { // actualizar los recursos // disponibles ((MapViewer) getParent()).updateControls(); } List<Recurso> allres = RecursoConsultas.getAll(Authentication.getUsuario()); boolean peopleShowing = people != null && people.visible; boolean vehiclesShowing = vehicles != null && vehicles.visible; Collection<Marker> peop = new LinkedList<Marker>(); Collection<Marker> veh = new LinkedList<Marker>(); for (Recurso r : allres) { HistoricoGPS h = r.getHistoricoGps(); if (h == null) { continue; } WayPoint w = new WayPoint(new LatLon(h.getPosY(), h.getPosX())); String name = r.getNombre(); if (r.getPatrullas() != null) name += " (" + r.getPatrullas().getNombre() + ")"; w.attr.put("name", name); w.attr.put("symbol", LogicConstants.get("DIRECTORIO_ICONOS_FLOTAS") + "/" + r.getFlotas().getJuegoIconos()); // w.attr.put("color", LogicConstants.get("COLOR_ESTADO_REC_" // + r.getEstadoEurocop().getId(), "#000000")); if (peopleShowing && r.getTipo().equalsIgnoreCase(Recurso.PERSONA)) { CustomMarker<String, Recurso> marker = new CustomMarker<String, Recurso>(w, people, r.getIdentificador(), Type.RESOURCE); marker.setObject(r); peop.add(marker); } else if (vehiclesShowing && r.getTipo().equalsIgnoreCase(Recurso.VEHICULO)) { CustomMarker<String, Recurso> marker = new CustomMarker<String, Recurso>(w, vehicles, r.getIdentificador(), Type.RESOURCE); marker.setObject(r); veh.add(marker); } } if (people != null) { people.data = peop; } if (vehicles != null) { vehicles.data = veh; } } private void updateIncidences(final LatLon topleft, final LatLon bottomright) { MarkerLayer layer = null; // tomar las capas vehiculo y persona for (Layer l : getAllLayers()) { if (l.name.equals(getI18n().getString("Incidences.incidences"))) { layer = (MarkerLayer) l; break; } } if (layer == null) return; List<Incidencia> allres = IncidenciaConsultas.getOpened(); Collection<Marker> nuevoData = new LinkedList<Marker>(); for (Incidencia i : allres) { try { if (i.getGeometria() != null) { final com.vividsolutions.jts.geom.Point centroid = i.getGeometria().getCentroid(); if (centroid != null) { LatLon latlon = new LatLon(centroid.getCoordinate().y, centroid.getCoordinate().x); WayPoint w = new WayPoint(latlon); w.attr.put("name", i.getTitulo() + " (" + i.getPrioridad() + ")"); w.attr.put("symbol", LogicConstants.get("DIRECTORIO_ICONOS_INCIDENCIAS", "incidencia/") + "incidencia_" + i.getEstado().toString() + "_" + i.getCategoria().toString() + "_" + i.getPrioridad().toString()); w.attr.put("color", LogicConstants.get("COLOR_ESTADO_INC_" + i.getEstado().getId(), "#000000")); CustomMarker<Long, Incidencia> marker = new CustomMarker<Long, Incidencia>(w, layer, i.getId(), Type.INCIDENCE); marker.setObject(i); nuevoData.add(marker); } } } catch (Throwable t) { log.error("Error al intentar pintar una incidencia", t); } } layer.data = nuevoData; } }