package com.project.website.canvas.client.canvastools.map;
import com.google.common.collect.HashBiMap;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.logical.shared.HasValueChangeHandlers;
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.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.TakesValue;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.DisclosurePanel;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.RadioButton;
import com.google.gwt.user.client.ui.Widget;
import com.project.gwtmapstraction.client.mxn.MapProvider;
import com.project.gwtmapstraction.client.mxn.MapstractionMapType;
import com.project.shared.client.events.SimpleEvent;
import com.project.website.canvas.shared.data.MapData;
import com.project.website.canvas.shared.data.MapData.MapType;
public class MapToolOptions extends Composite implements TakesValue<MapData>, HasValueChangeHandlers<MapData>
{
private static MapToolOptionsUiBinder uiBinder = GWT.create(MapToolOptionsUiBinder.class);
interface MapToolOptionsUiBinder extends UiBinder<Widget, MapToolOptions>
{
}
@UiField
FlowPanel providersPanel;
@UiField
FlowPanel mapTypesPanel;
@UiField
DisclosurePanel providersContainerPanel;
@UiField
Button doneButton;
SimpleEvent<Void> doneEvent = new SimpleEvent<Void>();
private MapData mapData;
private HashBiMap<MapProvider, RadioButton> providerButtons = HashBiMap.create();
private HashBiMap<MapType, RadioButton> mapTypeButtons = HashBiMap.create();
private boolean _updatingOptions;
public MapToolOptions(Iterable<MapProvider> availableProviders)
{
initWidget(uiBinder.createAndBindUi(this));
ValueChangeHandler<Boolean> booleanValueChanged = new ValueChangeHandler<Boolean>() {
@Override
public void onValueChange(ValueChangeEvent<Boolean> event)
{
valueUpdated();
}
};
for (MapProvider provider : availableProviders) {
RadioButton providerButton = new RadioButton("provider", provider.getDescription());
providerButton.addValueChangeHandler(booleanValueChanged);
this.providerButtons.put(provider, providerButton);
this.providersPanel.add(providerButton);
}
this.providersContainerPanel.setVisible(1 < this.providerButtons.size());
for (MapType mapType : MapType.values()) {
String description;
switch (mapType) {
case ROAD: description = "Road map"; break;
case HYBRID: description = "Roads + Satellite"; break;
case PHYSICAL: description = "Terrain map"; break;
case SATELLITE: description = "Satellite imagery"; break;
default:
continue;
}
RadioButton mapTypeButton = new RadioButton("mapType", description);
mapTypeButton.addValueChangeHandler(booleanValueChanged);
this.mapTypeButtons.put(mapType, mapTypeButton);
this.mapTypesPanel.add(mapTypeButton);
}
}
protected void valueUpdated()
{
if (this._updatingOptions) {
return;
}
this._updatingOptions = true;
this.updateAvailableOptions();
MapData updatedValue = this.getValue();
this._updatingOptions = false;
ValueChangeEvent.fire(this, updatedValue);
}
@UiHandler("doneButton")
void doneButtonClicked(ClickEvent event)
{
doneEvent.dispatch(null);
}
@Override
public void setValue(MapData value)
{
this.mapData = value;
this.clearButtons();
this.providerButtons.get(MapProvider.valueOf(value.provider)).setValue(true);
this.mapTypeButtons.get(value.mapType).setValue(true);
this.updateAvailableOptions();
}
@Override
public MapData getValue()
{
if (null == this.mapData) {
// TODO is this what we want?
throw new RuntimeException("Must set value first!");
}
MapProvider provider = getSelectedMapProvider();
this.mapData.provider = null != provider ? provider.name() : null;
for (RadioButton button : this.mapTypeButtons.values()) {
if (button.getValue()) {
this.mapData.mapType = this.mapTypeButtons.inverse().get(button);
}
}
return this.mapData;
}
protected void updateAvailableOptions()
{
MapProvider provider = getSelectedMapProvider();
RadioButton currentSelectedButton = null;
for (RadioButton mapTypeButton : this.mapTypeButtons.values())
{
mapTypeButton.setEnabled(false);
if (mapTypeButton.getValue()) {
currentSelectedButton = mapTypeButton;
}
}
RadioButton firstEnabledButton = null;
for (MapstractionMapType mapstractionMapType : provider.getSupportedMapTypes()) {
MapType mapType = MapToolStaticUtils.fromMapstractionMapType(mapstractionMapType);
RadioButton button = this.mapTypeButtons.get(mapType);
button.setEnabled(true);
if (null == firstEnabledButton) {
firstEnabledButton = button;
}
}
if (false == currentSelectedButton.isEnabled()) {
currentSelectedButton.setValue(false);
firstEnabledButton.setValue(true);
}
}
private MapProvider getSelectedMapProvider()
{
MapProvider provider = null;
for (RadioButton button : this.providerButtons.values()) {
if (button.getValue()) {
provider = this.providerButtons.inverse().get(button);
}
}
return provider;
}
public HandlerRegistration addDoneHandler(SimpleEvent.Handler<Void> handler) {
return this.doneEvent.addHandler(handler);
}
private void clearButtons()
{
for (RadioButton button : this.providerButtons.values()) {
button.setValue(false);
}
for (RadioButton button : this.mapTypeButtons.values()) {
button.setValue(false);
}
}
@Override
public HandlerRegistration addValueChangeHandler(ValueChangeHandler<MapData> handler)
{
return this.addHandler(handler, ValueChangeEvent.getType());
}
}