/******************************************************************************* * Copyright (c) 2014 Open Door Logistics (www.opendoorlogistics.com) * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Lesser Public License v3 * which accompanies this distribution, and is available at http://www.gnu.org/licenses/lgpl.txt ******************************************************************************/ package com.opendoorlogistics.studio.components.geocoder; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.util.HashSet; import javax.swing.BorderFactory; import javax.swing.JPanel; import javax.swing.SwingUtilities; import com.opendoorlogistics.api.components.ComponentControlLauncherApi; import com.opendoorlogistics.api.components.ComponentExecutionApi.ClosedStateListener; import com.opendoorlogistics.api.components.ComponentExecutionApi.ClosedStatusObservable; import com.opendoorlogistics.api.tables.ODLDatastore; import com.opendoorlogistics.api.tables.ODLTable; import com.opendoorlogistics.api.ui.Disposable; import com.opendoorlogistics.core.gis.map.data.DrawableObjectImpl; import com.opendoorlogistics.core.gis.map.data.LatLongImpl; import com.opendoorlogistics.core.utils.images.ImageUtils; import com.opendoorlogistics.core.utils.ui.LayoutUtils; import com.opendoorlogistics.core.utils.ui.VerticalLayoutPanel; import com.opendoorlogistics.studio.components.geocoder.component.NominatimConfig; import com.opendoorlogistics.studio.components.geocoder.model.GeocodeModel; import com.opendoorlogistics.studio.components.geocoder.model.GeocodeModelListener; public class InteractiveGeocoderPanel extends JPanel implements Disposable, GeocodeModelListener, ClosedStatusObservable { // private final InteractiveMapControl interactive; // private final ReadOnlyMapPanel map; private final NominatimMap nmap; private final SearchResultsPanel searchSubPanel; private final GeocodeItemPanel itemPanel; private final GeocodeToolbar toolbar; private final GeocodeModel model; private final VerticalLayoutPanel mainResultsPanel; private final HashSet<ClosedStateListener> closedStateListeners = new HashSet<>(); public InteractiveGeocoderPanel(NominatimConfig config, ODLDatastore<? extends ODLTable> ds, ComponentControlLauncherApi controlLauncher) { this.model = new GeocodeModel(ds); // go to the first record this.model.gotoNextRecord(); setLayout(new BorderLayout()); // use vertical layout VerticalLayoutPanel vPanel = new VerticalLayoutPanel(); add(vPanel, BorderLayout.CENTER); // create item panel itemPanel = new GeocodeItemPanel(model); // Dimension itemPanelSize = new Dimension(600, 110); // itemPanel.setPreferredSize(itemPanelSize); // itemPanel.setMinimumSize(itemPanelSize); setBorder(itemPanel, ""); vPanel.add(itemPanel); vPanel.addWhitespace(); // create address results searchSubPanel = new SearchResultsPanel(config, model); Dimension searchPanelSize = new Dimension(600, 200); searchSubPanel.setPreferredSize(searchPanelSize); searchSubPanel.setMinimumSize(searchPanelSize); searchSubPanel.table.setPreferredScrollableViewportSize(new Dimension(600, 104)); // // create map // interactive = new InteractiveMapControl(new MapConfig(),new MapModePermissions(0xFFFFFFFFFFFFFFFFL),null,null); // //interactive.setLegendCreator(GeocoderMapAppearance.createLegendCreator()); // interactive.addOnMoveObjectListener(new OnClickPosition() { // // @Override // public void onClickPosition(double latitude, double longitude) { // model.setGeocode(latitude, longitude); // map.setDrawables(GeocoderMapObjects.createDrawable(model)); // } // }); // interactive.setZoomBestFitManager(new ZoomBestFitManager() { // // @Override // public void zoomBestFit(ReadOnlyMapControl viewer, double maxFraction) { // ZoomUtils.zoomToBestFit(viewer, viewer.getLatLongBoundingBox(null), maxFraction, true, 0.001); // } // }); // map = new ReadOnlyMapPanel(interactive, true, controlLauncher) { // // @Override // protected List<Action> createActions() { // List<Action> ret = super.createActions(); // ret.add(null); // // // create action to enter each of the mouse modes // for (final MouseMode mode : new MouseMode[] { MouseMode.NAVIGATE, MouseMode.MOVE_OBJECT }) { // AbstractAction action = new AbstractAction(Strings.convertEnumToDisplayFriendly(mode.toString()), mode.getButtonImageIcon()) { // // @Override // public void actionPerformed(ActionEvent e) { // interactive.setMouseMode(mode); // } // }; // // action.putValue(Action.SHORT_DESCRIPTION, mode.getDescription()); // action.putValue(Action.LONG_DESCRIPTION, mode.getDescription()); // ret.add(action); // } // // return ret; // } // // @Override // protected void createLegendAction(Collection<Action> ret) { // // Turn off the legend... // } // }; // map.setDrawables(GeocoderMapObjects.createDrawable(model)); // map.setPreferredSize(new Dimension(600, 200)); nmap = new NominatimMap(model); // put map in its own panel with a legend and border mainResultsPanel = new VerticalLayoutPanel(); mainResultsPanel.add(searchSubPanel); mainResultsPanel.addNoWrap(nmap.getComponent()); mainResultsPanel.add(ImageUtils.createImagePanel(GeocoderMapObjects.createLegend(), Color.WHITE)); vPanel.addNoWrap(mainResultsPanel); //vPanel.addWhitespace(); // create toolbar toolbar = new GeocodeToolbar(model){ @Override protected void onExit() { InteractiveGeocoderPanel.this.onExit(); } }; add(toolbar, BorderLayout.SOUTH); setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); modelChanged(true, true); model.addListener(this); model.fireListeners(true, true); } private void onExit(){ for(ClosedStateListener listener:closedStateListeners){ listener.onClosed(); } } private void setBorder(JPanel panel, String title) { // panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); // panel.setBorder(BorderFactory.createTitledBorder(title)); panel.setBorder(LayoutUtils.createInsetTitledBorder(title)); // panel.setBorder(BorderFactory.createTitledBorder( // BorderFactory.createEmptyBorder(10,10,10, 10), title)); } protected long createPoint(DrawableObjectImpl newPoint) { throw new UnsupportedOperationException(); } protected boolean movePoint(long globalId, LatLongImpl newPosition) { throw new UnsupportedOperationException(); } @Override public void dispose() { nmap.dispose(); // globalDs.removeListener(fieldSelectorPanel); } // public static void main(String[] args) { // SwingUtilities.invokeLater(new Runnable() { // // @Override // public void run() { // InteractiveGeocoderPanel panel = createWithDummyData(); // ShowPanel.showPanel(panel); // } // // }); // } // public static InteractiveGeocoderPanel createWithDummyData() { // // ODLDatastoreAlterable<ODLTableAlterable> ds = GeocodeModel.createEmptyDs(); // ODLTable table = ds.getTableAt(0); // // for (String address : new String[] { "Union Square, Aberdeen, AB11 5PN", "Queen Anne�s Walk, Basingstoke, RG21 7BE", // "Southgate Place, Bath, BA1 1AP", "Victoria Square, Belfast, BT1 4QG", "Churchill Square, Brighton, BN1 2TE", // "11 Philadelphia Street, Quakers Friars, Bristol, BS1 3BZ", "263-66 Grand Arcade, Cardiff, CF10 2EL", // "24 Princess hay, Exeter, EX1 1GE", "147 Buchanan Street, Glasgow, G1 2JX", "Eastgate Road, Eastville, BS5 6XX", // "Valley Park, Purley Way, Croydon, CR0 4UZ", "Straiton Road, Loanhead,Midlothian, EH20 9PW ", // "Metro Park West, Gateshead, NE11 9XS, United Kingdom", "Heron Way, West Thurrock, Essex, RM20 3WJ, United Kingdom", // "Wellington Road ,Ashton Under Lyne, OL6 7TE ,United Kingdom", // "Goslington , Off Bletcham Way , Milton Keynes, MK1 1QB , United Kingdom", "910 Europa Blvd , Warrington, WA5 7TY, United Kingdom", // "Park Lane, Wednesbury, West Midlands, WS10 9SF, United Kingdom", "2 Drury Way, North Circular Rd, London, NW10 0TH" }) { // int row = table.createEmptyRow(-1); // table.setValueAt(address, row, 0); // } // // System.out.println(ds); // // // UndoRedoDecorator<ODLTableAlterable> undoRedo = new UndoRedoDecorator<>(ODLTableAlterable.class, ds); // // NominatimConfig config = new NominatimConfig(); // config.setEmail("me@me.com"); // InteractiveGeocoderPanel panel = new InteractiveGeocoderPanel(config, undoRedo); // return panel; // } @Override public void modelChanged(boolean recordChanged, boolean searchResultsChanged) { // always repaint the map with a fresh drawable datastore nmap.update(); // rezoom if search results have changed if (searchResultsChanged) { // do zooming after current event as it won't work if controls are // not already visible and sized SwingUtilities.invokeLater(new Runnable() { @Override public void run() { nmap.zoomBestFit(); // final double maxZoomFraction = 0.95; // if(model.getSelectedResultsCount()>1){ // interactive.zoomBestFit(maxZoomFraction); // } // else if(model.getSelectedResultsCount()==1){ // // create dummy positions around the point so we can get // a sensible zoom... // HashSet<GeoPosition>dummies = new HashSet<>(); // double d = 0.005; // for(int lat =-1 ; lat<=1 ; lat+=2){ // for(int lng =-1 ; lng<=1 ; lng+=2){ // dummies.add(new // GeoPosition(model.getSearchResults().get(0).getLatitude() // + lat *d, // model.getSearchResults().get(0).getLongitude() + lat // *d)); // } // } // ReadOnlyMapViewer.zoomToBestFit(interactive, dummies, // maxZoomFraction); // }else{ // interactive.setCenter(new Point2D.Double(0, 0)); // interactive.setZoom(interactive.getTileFactory().getInfo().getMaximumZoomLevel()); // } // map.repaint(); } }); } // update title if record changed if (recordChanged) { setBorder(itemPanel, "Current record (" + (model.getRow() + 1) + "/" + model.getRowCount() + ")"); } // set results border if searched results have changed if (searchResultsChanged) { // setBorder(searchResultsPanel, "Search results for \"" + // model.getAddress() + "\""); setBorder(mainResultsPanel, "Search results for \"" + model.getAddress() + "\""); } } @Override public void addClosedStatusListener(ClosedStateListener listener) { closedStateListeners.add(listener); } @Override public void removeClosedStatusListener(ClosedStateListener listener) { closedStateListeners.remove(listener); } }