/* * #%L * GeoWE Project * %% * Copyright (C) 2015 - 2016 GeoWE.org * %% * This file is part of GeoWE.org. * * GeoWE 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 3 of the License, or * (at your option) any later version. * * GeoWE 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 GeoWE. If not, see <http://www.gnu.org/licenses/>. * #L% */ package org.geowe.client.local.main; import java.util.ArrayList; import java.util.List; import javax.enterprise.context.ApplicationScoped; import javax.inject.Inject; import org.geowe.client.local.initializer.GeoMapInitializer; import org.geowe.client.local.layermanager.AddLayerListener; import org.geowe.client.local.layermanager.ChangeSelectedLayerListener; import org.geowe.client.local.layermanager.LayerManagerWidget; import org.geowe.client.local.layermanager.RemoveLayerListener; import org.geowe.client.local.main.map.GeoMap; import org.geowe.client.local.messages.UIMessages; import org.geowe.client.local.model.vector.VectorLayer; import org.geowe.client.local.ui.ProjectionComboBox; import org.gwtopenmaps.openlayers.client.LonLat; import org.gwtopenmaps.openlayers.client.control.SelectFeature; import org.gwtopenmaps.openlayers.client.layer.Layer; import org.gwtopenmaps.openlayers.client.layer.Vector; import com.google.gwt.core.client.GWT; import com.google.gwt.dom.client.Style.Position; import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.dom.client.Style.VerticalAlign; import com.google.gwt.dom.client.StyleInjector; import com.google.gwt.editor.client.Editor.Path; import com.google.gwt.event.logical.shared.SelectionEvent; import com.google.gwt.event.logical.shared.SelectionHandler; import com.google.gwt.event.logical.shared.ValueChangeEvent; import com.google.gwt.event.logical.shared.ValueChangeHandler; import com.google.gwt.user.client.ui.HasHorizontalAlignment; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.IsWidget; import com.google.gwt.user.client.ui.VerticalPanel; import com.google.gwt.user.client.ui.Widget; import com.sencha.gxt.cell.core.client.form.ComboBoxCell.TriggerAction; import com.sencha.gxt.core.client.Style.Direction; import com.sencha.gxt.core.client.ValueProvider; import com.sencha.gxt.data.shared.LabelProvider; import com.sencha.gxt.data.shared.ListStore; import com.sencha.gxt.data.shared.ModelKeyProvider; import com.sencha.gxt.data.shared.PropertyAccess; import com.sencha.gxt.fx.client.FxElement; import com.sencha.gxt.widget.core.client.form.ComboBox; import com.sencha.gxt.widget.core.client.form.FieldLabel; import com.sencha.gxt.widget.core.client.grid.CellSelectionModel; import com.sencha.gxt.widget.core.client.grid.ColumnConfig; import com.sencha.gxt.widget.core.client.grid.ColumnModel; import com.sencha.gxt.widget.core.client.grid.Grid; /** * Represents the status bar * * @author geowe * */ @ApplicationScoped public class StatusPanelWidget implements IsWidget, ChangeSelectedLayerListener, AddLayerListener, RemoveLayerListener { public static final String LON_LABEL = "X/Lon"; public static final String LAT_LABEL = "Y/Lat"; public static final String SCALE_LABEL = UIMessages.INSTANCE.sbScaleLabel(); public static final String CLICK_COORD_X = UIMessages.INSTANCE.coordX(); public static final String CLICK_COORD_Y = UIMessages.INSTANCE.coordY(); @Inject LayerManagerWidget layerManagerWidget; @Inject GeoMap geoMap; private Vector selectedLayer; private List<Layer> vectorLayers; private HorizontalPanel widget; private VerticalPanel statusPanel; private ProjectionComboBox epsgCombo; private ComboBox<VectorLayerInfo> layerCombo; private ListStore<VectorLayerInfo> layerStore; private Grid<StatusItem> statusGrid; private ListStore<StatusItem> statusStore; @Override public Widget asWidget() { if (widget == null) { widget = new HorizontalPanel(); int barHeight = 210; int topPadding = 50; int barWidth = 250; int right = 5; widget.getElement().getStyle().setPosition(Position.FIXED); widget.getElement().getStyle().setRight(right, Unit.PX); widget.getElement().getStyle().setTop(topPadding, Unit.PX); widget.getElement().getStyle().setHeight(barHeight, Unit.PX); widget.getElement().getStyle().setWidth(barWidth, Unit.PX); widget.getElement().getStyle() .setVerticalAlign(VerticalAlign.MIDDLE); widget.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_RIGHT); widget.setVisible(false); initializeStatusPanel(); widget.add(statusPanel); } return widget; } private void initializeStatusPanel() { String comboWidth = "125px"; statusPanel = new VerticalPanel(); StyleInjector.inject(".statusPanelStyle { " + "background: #E0ECF8;" + "border-radius: 5px 10px;" + "opacity: 0.8}"); statusPanel.setStyleName("statusPanelStyle"); statusPanel.setSpacing(5); statusPanel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER); initializeLayerCombo(comboWidth); initializeEpsgCombo(comboWidth); initializeStatusGrid(); statusPanel.add(new FieldLabel(layerCombo, UIMessages.INSTANCE .sbSelectLayerLabel())); statusPanel.add(new FieldLabel(epsgCombo, UIMessages.INSTANCE .sbEpsgLabel())); statusPanel.add(statusGrid); statusPanel.setVisible(false); } private void initializeLayerCombo(String width) { VectorLayerProperties properties = GWT .create(VectorLayerProperties.class); layerStore = new ListStore<VectorLayerInfo>(properties.key()); layerCombo = new ComboBox<VectorLayerInfo>(layerStore, properties.name()); layerCombo.setEmptyText((UIMessages.INSTANCE.sbLayerComboEmptyText())); layerCombo.setTypeAhead(true); layerCombo.setTriggerAction(TriggerAction.ALL); layerCombo.setForceSelection(true); layerCombo.setEditable(false); layerCombo.enableEvents(); layerCombo.setWidth(width); layerCombo.addSelectionHandler(new SelectionHandler<VectorLayerInfo>() { @Override public void onSelection(SelectionEvent<VectorLayerInfo> event) { layerCombo.setValue(event.getSelectedItem(), true); } }); layerCombo.addValueChangeHandler(new ValueChangeHandler<VectorLayerInfo>() { @Override public void onValueChange( ValueChangeEvent<VectorLayerInfo> event) { VectorLayer layer = (VectorLayer) layerManagerWidget .getSelectedLayer(LayerManagerWidget.VECTOR_TAB); if (layer == null) { layer = (VectorLayer) event.getValue().getLayer(); } new SelectFeature(layer).unselectAll(null); layerManagerWidget.setSelectedLayer( LayerManagerWidget.VECTOR_TAB, layerCombo .getValue().getLayer()); } }); } private void initializeEpsgCombo(String width) { epsgCombo = new ProjectionComboBox(width); epsgCombo.setValue(GeoMap.INTERNAL_EPSG); epsgCombo.addSelectionHandler(new SelectionHandler<String>() { @Override public void onSelection(SelectionEvent<String> event) { epsgCombo.setValue(event.getSelectedItem(), true); } }); epsgCombo.addValueChangeHandler(new ValueChangeHandler<String>() { @Override public void onValueChange(ValueChangeEvent<String> event) { /* * Actualizamos el DisplayProjection para que las coordenadas de * la barra de estado se muestren en el nuevo EPSG seleccionado */ geoMap.configure(epsgCombo.getValue(), GeoMapInitializer.MAX_NUM_ZOOM_LEVEL, GeoMapInitializer.DEFAUL_MAP_UNITS); } }); } private void initializeStatusGrid() { // Creacion del Grid Base StatusItemProperties props = GWT.create(StatusItemProperties.class); statusStore = new ListStore<StatusItem>(props.key()); statusStore.setAutoCommit(true); ColumnConfig<StatusItem, String> nameCol = new ColumnConfig<StatusItem, String>( props.name(), 75, UIMessages.INSTANCE.fedColumnNameText()); ColumnConfig<StatusItem, String> valueCol = new ColumnConfig<StatusItem, String>( props.value(), 150, UIMessages.INSTANCE.fedNewAttributeDefaultNameText()); List<ColumnConfig<StatusItem, ?>> columns = new ArrayList<ColumnConfig<StatusItem, ?>>(); columns.add(nameCol); columns.add(valueCol); statusGrid = new Grid<StatusItem>(statusStore, new ColumnModel<StatusItem>(columns)); statusGrid.setSelectionModel(new CellSelectionModel<StatusItem>()); statusGrid.getColumnModel().getColumn(1).setHideable(false); statusGrid.setHideHeaders(true); statusGrid.setAllowTextSelection(true); statusGrid.getView().setStripeRows(true); statusGrid.getView().setColumnLines(true); statusGrid.setBorders(false); statusStore.add(new StatusItem(LON_LABEL, null)); statusStore.add(new StatusItem(LAT_LABEL, null)); statusStore.add(new StatusItem(SCALE_LABEL, null)); statusStore.add(new StatusItem(CLICK_COORD_X, null)); statusStore.add(new StatusItem(CLICK_COORD_Y, null)); } @Override public void onChange(Vector layer) { setSelectedLayer(layer); } @Override public void onAddLayer(List<Layer> allVectorLayers) { setVectorLayers(allVectorLayers); } @Override public void onRemoveLayer(List<Layer> allVectorLayers) { setVectorLayers(allVectorLayers); /* * Puesto que al eliminar una capa, ninguna de las restantes queda * seleccionada en el LayerManager, se limpia la capa seleccionada de la * combo de capas */ layerCombo.setValue(null); } public void setCurrentCoordinate(LonLat currentCoordinate) { StatusItem lonItem = getStatusItem(LON_LABEL); lonItem.setValue(Double.toString(currentCoordinate.lon())); StatusItem latItem = getStatusItem(LAT_LABEL); latItem.setValue(Double.toString(currentCoordinate.lat())); statusStore.update(lonItem); statusStore.update(latItem); } public void setVectorLayers(List<Layer> vectorLayers) { this.vectorLayers = vectorLayers; updateStatusInfo(); } public void setSelectedLayer(Vector selectedLayer) { this.selectedLayer = selectedLayer; updateStatusInfo(); } public void setScale(String scale) { StatusItem scaleItem = getStatusItem(SCALE_LABEL); scaleItem.setValue(scale); statusStore.update(scaleItem); } public void setClickedCoordinates(double x, double y) { StatusItem messageItemX = getStatusItem(CLICK_COORD_X); messageItemX.setValue(String.valueOf(x)); statusStore.update(messageItemX); StatusItem messageItemY = getStatusItem(CLICK_COORD_Y); messageItemY.setValue(String.valueOf(y)); statusStore.update(messageItemY); } public void showHideStatusBar() { if (statusPanel.isVisible()) { statusPanel.getElement().<FxElement> cast().slideOut(Direction.UP); widget.setVisible(false); } else { widget.setVisible(true); statusPanel.getElement().<FxElement> cast().slideIn(Direction.DOWN); } } private void updateStatusInfo() { if (vectorLayers != null) { List<VectorLayerInfo> vectors = new ArrayList<VectorLayerInfo>(); for (Layer layer : vectorLayers) { vectors.add(new VectorLayerInfo((Vector) layer)); } layerStore.clear(); layerStore.addAll(vectors); layerCombo.redraw(); } if (selectedLayer != null) { layerCombo.setValue(new VectorLayerInfo(selectedLayer)); } } private StatusItem getStatusItem(String name) { for (StatusItem item : statusStore.getAll()) { if (item.getName().equals(name)) { return item; } } return null; } /** * Clase para representar cada uno de los datos a mostrar en la barra de * estado de la aplicacion. * * @author atamunoz * */ public class StatusItem { String name; String value; public StatusItem(String name, String value) { this.name = name; this.value = value; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + getOuterType().hashCode(); result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; StatusItem other = (StatusItem) obj; if (!getOuterType().equals(other.getOuterType())) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } private StatusPanelWidget getOuterType() { return StatusPanelWidget.this; } } public interface StatusItemProperties extends PropertyAccess<StatusItem> { @Path("name") ModelKeyProvider<StatusItem> key(); @Path("name") LabelProvider<StatusItem> nameLabel(); ValueProvider<StatusItem, String> name(); ValueProvider<StatusItem, String> value(); } }