package org.activityinfo.ui.client.component.report.editor.map.layerOptions;
/*
* #%L
* ActivityInfo Server
* %%
* Copyright (C) 2009 - 2013 UNICEF
* %%
* This program 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.
*
* This program 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 program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
* #L%
*/
import com.extjs.gxt.ui.client.core.El;
import com.extjs.gxt.ui.client.event.ComponentEvent;
import com.extjs.gxt.ui.client.event.Events;
import com.extjs.gxt.ui.client.event.FxEvent;
import com.extjs.gxt.ui.client.event.Listener;
import com.extjs.gxt.ui.client.fx.FxConfig;
import com.extjs.gxt.ui.client.util.Size;
import com.extjs.gxt.ui.client.widget.Component;
import com.extjs.gxt.ui.client.widget.ContentPanel;
import com.extjs.gxt.ui.client.widget.LayoutContainer;
import com.extjs.gxt.ui.client.widget.button.ToolButton;
import com.extjs.gxt.ui.client.widget.layout.AccordionLayout;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.ui.AbstractImagePrototype;
import com.google.gwt.user.client.ui.HasValue;
import com.google.gwt.user.client.ui.Widget;
import org.activityinfo.i18n.shared.I18N;
import org.activityinfo.legacy.client.Dispatcher;
import org.activityinfo.legacy.shared.command.DimensionType;
import org.activityinfo.legacy.shared.command.Filter;
import org.activityinfo.legacy.shared.reports.model.clustering.Clustering;
import org.activityinfo.legacy.shared.reports.model.layers.*;
import org.activityinfo.ui.client.component.report.editor.map.MapResources;
public final class LayerOptionsPanel extends LayoutContainer implements HasValue<MapLayer> {
public static final int WIDTH = 271;
public static final int HEIGHT = 377;
private MapLayer selectedMapLayer;
// Options for every supported MapLayer type
private BubbleLayerOptions bubbleMapLayerOptions = new BubbleLayerOptions();
private IconLayerOptions iconMapLayerOptions = new IconLayerOptions();
private PiechartLayerOptions piechartMapLayerOptions;
private PolygonLayerOptions polygonLayerOptions = new PolygonLayerOptions();
// Clustering options
private ClusteringOptionsWidget clusteringOptions;
private ContentPanel stylePanel;
private ContentPanel clusteringPanel;
private LayerFilterPanel filterPanel;
private Dispatcher dispatcher;
private AccordionLayout layout;
public LayerOptionsPanel(Dispatcher service) {
super();
this.dispatcher = service;
initializeComponent();
this.piechartMapLayerOptions = new PiechartLayerOptions(service);
bindLayerOptions(bubbleMapLayerOptions);
bindLayerOptions(iconMapLayerOptions);
bindLayerOptions(piechartMapLayerOptions);
bindLayerOptions(polygonLayerOptions);
createClusteringOptions(service);
createFilterPanel(service);
}
private void createClusteringOptions(Dispatcher service) {
clusteringOptions = new ClusteringOptionsWidget(service);
clusteringOptions.addValueChangeHandler(new ValueChangeHandler<Clustering>() {
@Override
public void onValueChange(ValueChangeEvent<Clustering> event) {
if (selectedMapLayer instanceof PointMapLayer) {
((PointMapLayer) selectedMapLayer).setClustering(event.getValue());
ValueChangeEvent.fire(LayerOptionsPanel.this, selectedMapLayer);
}
}
});
clusteringPanel.add(clusteringOptions);
}
private <L extends MapLayer> void bindLayerOptions(HasValue<L> layerOptions) {
layerOptions.addValueChangeHandler(new ValueChangeHandler<L>() {
@Override
public void onValueChange(ValueChangeEvent<L> event) {
ValueChangeEvent.fire(LayerOptionsPanel.this, event.getValue());
}
});
}
private void initializeComponent() {
setWidth(WIDTH);
setHeight(HEIGHT);
layout = new AccordionLayout() {
@Override
protected void renderComponent(Component component, int index, El target) {
super.renderComponent(component, index, target);
// keep the default style of rounded corners on the content
// panels
El.fly(((ContentPanel) component).getElement("header")).removeStyleName("x-accordion-hd");
}
@Override
protected void setItemSize(Component item, Size size) {
// don't set the height of the panels
ContentPanel cp = (ContentPanel) item;
cp.setWidth(size.width);
}
};
layout.setHideCollapseTool(true);
setLayout(layout);
// setFieldsetHeadingToLayerName();
stylePanel = new ContentPanel();
stylePanel.setHeadingText(I18N.CONSTANTS.style());
stylePanel.setIcon(AbstractImagePrototype.create(MapResources.INSTANCE.styleIcon()));
stylePanel.setCollapsible(true);
stylePanel.setHideCollapseTool(true);
stylePanel.setAnimCollapse(true);
ToolButton closeBtn = new ToolButton("x-tool-close");
closeBtn.addListener(Events.Select, new Listener<ComponentEvent>() {
@Override
public void handleEvent(ComponentEvent ce) {
fadeOut();
}
});
stylePanel.getHeader().addTool(closeBtn);
add(stylePanel);
clusteringPanel = new ContentPanel();
clusteringPanel.setIcon(AbstractImagePrototype.create(MapResources.INSTANCE.clusterIcon()));
clusteringPanel.setHeadingText(I18N.CONSTANTS.clustering());
clusteringPanel.setCollapsible(true);
clusteringPanel.setHideCollapseTool(true);
clusteringPanel.setAnimCollapse(true);
add(clusteringPanel);
}
private void createFilterPanel(Dispatcher service) {
filterPanel = new LayerFilterPanel(service);
filterPanel.addValueChangeHandler(new ValueChangeHandler<Filter>() {
@Override
public void onValueChange(ValueChangeEvent<Filter> event) {
selectedMapLayer.setFilter(event.getValue());
ValueChangeEvent.fire(LayerOptionsPanel.this, selectedMapLayer);
}
});
add(filterPanel);
}
private LayerOptionsWidget fromLayer(MapLayer mapLayer) {
if (mapLayer instanceof BubbleMapLayer) {
return bubbleMapLayerOptions;
} else if (mapLayer instanceof IconMapLayer) {
return iconMapLayerOptions;
} else if (mapLayer instanceof PiechartMapLayer) {
return piechartMapLayerOptions;
} else if (mapLayer instanceof PolygonMapLayer) {
return polygonLayerOptions;
}
throw new IllegalArgumentException("layer: " + mapLayer.getClass().getName());
}
private Filter baseFilterFromLayer(MapLayer layer) {
Filter filter = new Filter();
filter.addRestriction(DimensionType.Indicator, layer.getIndicatorIds());
return filter;
}
private void setStyleOptions(LayerOptionsWidget layerOptionsWidget) {
stylePanel.removeAll();
stylePanel.add((Widget) layerOptionsWidget);
stylePanel.layout();
}
public void fadeOut() {
el().fadeOut(new FxConfig(new Listener<FxEvent>() {
@Override
public void handleEvent(FxEvent be) {
hide();
}
}));
}
@Override
public HandlerRegistration addValueChangeHandler(ValueChangeHandler<MapLayer> handler) {
return this.addHandler(handler, ValueChangeEvent.getType());
}
@Override
public MapLayer getValue() {
return selectedMapLayer;
}
@Override
public void setValue(MapLayer mapLayer) {
if (mapLayer != selectedMapLayer) {
this.selectedMapLayer = mapLayer;
LayerOptionsWidget layerOptionsWidget = fromLayer(mapLayer);
layerOptionsWidget.setValue(mapLayer);
setStyleOptions(layerOptionsWidget);
clusteringOptions.loadForm(mapLayer);
if (mapLayer instanceof PointMapLayer) {
clusteringOptions.setValue(((PointMapLayer) mapLayer).getClustering(), false);
clusteringPanel.show();
} else {
clusteringPanel.hide();
}
filterPanel.getFilterPanelSet().applyBaseFilter(baseFilterFromLayer(mapLayer));
filterPanel.setValue(mapLayer.getFilter(), false);
}
}
@Override
public void setValue(MapLayer mapLayer, boolean fireEvents) {
setValue(mapLayer);
if (fireEvents) {
ValueChangeEvent.fire(this, mapLayer);
}
}
public void showStyle(MapLayer mapLayer) {
show(mapLayer, stylePanel);
}
public void showAggregation(MapLayer mapLayer) {
show(mapLayer, clusteringPanel);
}
public void showFilter(MapLayer mapLayer) {
show(mapLayer, filterPanel);
}
private void show(MapLayer mapLayer, ContentPanel panel) {
if (!isVisible()) {
setVisible(true);
}
el().fadeIn(FxConfig.NONE);
setValue(mapLayer);
layout.setActiveItem(panel);
}
public void onLayerSelectionChanged(MapLayer model) {
if (model == null) {
setVisible(false);
} else if (isVisible()) {
setValue(model);
}
}
}