package com.google.gwt.sample.showcase.client;
import java.util.LinkedList;
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.EventBus;
import com.google.gwt.event.shared.GwtEvent;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.event.shared.SimpleEventBus;
import com.google.gwt.user.client.History;
public class Settings {
private static Settings instance;
public static Settings get() {
if (instance == null) {
instance = new Settings();
instance.ensureUpdatesOnHistoryChange();
}
return instance;
}
private ObservableBoolean predictiveScrolling =
new ObservableBoolean("ps", false);
private ObservableBoolean prefetching =
new ObservableBoolean("pf", false);
private ObservableBoolean conservativeStart =
new ObservableBoolean("cs", false);
private ObservableBoolean windowFilling =
new ObservableBoolean("wf", false);
private ObservableBoolean keyHandling =
new ObservableBoolean("kh", false);
private ObservableBoolean focusDrifting =
new ObservableBoolean("fd", false);
private ObservableBoolean compositeCell =
new ObservableBoolean("cc", false);
private ObservableBoolean[] observables = new ObservableBoolean[] {
prefetching,
predictiveScrolling,
conservativeStart,
windowFilling,
keyHandling,
focusDrifting,
compositeCell
};
private HandlerRegistration historyHandlerReg;
void ensureUpdatesOnHistoryChange() {
if (historyHandlerReg != null) {
return;
}
historyHandlerReg =
History.addValueChangeHandler(new HistoryChangeHandler());
}
public boolean getPredictiveScrolling() {
return predictiveScrolling.getValue();
}
public void setPredictiveScrolling(Boolean value) {
if (predictiveScrolling.setValue(value)) {
updateHistory();
}
}
public HandlerRegistration addPredictiveScrollingValueChangeHandler(
ValueChangeHandler<Boolean> handler) {
return predictiveScrolling.addValueChangeHandler(handler);
}
public boolean getPrefetching() {
return prefetching.getValue();
}
public void setPrefetching(Boolean value) {
if (prefetching.setValue(value)) {
updateHistory();
}
}
public HandlerRegistration addPrefetchingValueChangeHandler(
ValueChangeHandler<Boolean> handler) {
return prefetching.addValueChangeHandler(handler);
}
public boolean getConservativeStart() {
return conservativeStart.getValue();
}
public void setConservativeStart(Boolean value) {
if (conservativeStart.setValue(value)) {
updateHistory();
}
}
public HandlerRegistration addConservativeStartChangeHandler(
ValueChangeHandler<Boolean> handler) {
return conservativeStart.addValueChangeHandler(handler);
}
public boolean getWindowFilling() {
return windowFilling.getValue();
}
public void setWindowFilling(Boolean value) {
if (windowFilling.setValue(value)) {
updateHistory();
}
}
public HandlerRegistration addWindowFillingChangeHandler(
ValueChangeHandler<Boolean> handler) {
return windowFilling.addValueChangeHandler(handler);
}
public boolean getKeyHandling() {
return keyHandling.getValue();
}
public void setKeyHandling(Boolean value) {
if (keyHandling.setValue(value)) {
updateHistory();
}
}
public HandlerRegistration addKeyHandlingChangeHandler(
ValueChangeHandler<Boolean> handler) {
return keyHandling.addValueChangeHandler(handler);
}
public boolean getFocusDrifting() {
return focusDrifting.getValue();
}
public void setFocusDrifting(Boolean value) {
if (focusDrifting.setValue(value)) {
updateHistory();
}
}
public HandlerRegistration addFocusDriftingChangeHandler(
ValueChangeHandler<Boolean> handler) {
return focusDrifting.addValueChangeHandler(handler);
}
public boolean getCompositeCell() {
return compositeCell.getValue();
}
public void setCompositeCell(Boolean value) {
if (compositeCell.setValue(value)) {
updateHistory();
}
}
public HandlerRegistration addCompositeCellChangeHandler(
ValueChangeHandler<Boolean> handler) {
return compositeCell.addValueChangeHandler(handler);
}
private void updateHistory() {
String historyToken = History.getToken();
int startOfParams = historyToken.indexOf("?");
String widgetToken = (startOfParams == -1)
? historyToken : historyToken.substring(0, startOfParams);
History.replaceItem(widgetToken + getHistorySuffix(), false);
}
String getHistorySuffix() {
LinkedList<ObservableBoolean> nonDefaults =
removeThoseWithDefaultValues(observables);
if (nonDefaults.isEmpty()) {
return "";
}
StringBuilder sb = new StringBuilder();
sb.append(nonDefaults.pop().toString());
while (!nonDefaults.isEmpty()) {
sb.append("&");
sb.append(nonDefaults.pop().toString());
}
return "?" + sb.toString();
}
private LinkedList<ObservableBoolean> removeThoseWithDefaultValues(
ObservableBoolean... settings) {
LinkedList<ObservableBoolean> result = new LinkedList<ObservableBoolean>();
for (ObservableBoolean setting : settings) {
if (!setting.isDefault()) {
result.add(setting);
}
}
return result;
}
private final class HistoryChangeHandler
implements ValueChangeHandler<String> {
@Override
public void onValueChange(ValueChangeEvent<String> event) {
// Parse the history token
for (ObservableBoolean setting : observables) {
setting.updateValueFromQueryString(event.getValue());
}
}
}
private static class ObservableBoolean
implements HasValueChangeHandlers<Boolean> {
private EventBus eventBus = new SimpleEventBus();
private String key;
private boolean defaultValue;
private boolean value;
ObservableBoolean(String key, boolean defaultValue) {
this.key = key;
this.defaultValue = defaultValue;
this.value = defaultValue;
}
boolean isDefault() {
return value == defaultValue;
}
boolean getValue() {
return value;
}
boolean setValue(boolean newValue) {
boolean oldValue = value;
value = newValue;
ValueChangeEvent.fireIfNotEqual(this, oldValue, newValue);
return value != oldValue;
}
void updateValueFromQueryString(String query) {
if (query.contains(createOpposite().toString())) {
setValue(!value);
}
}
ObservableBoolean createOpposite() {
return new ObservableBoolean(key, !value);
}
@Override
public void fireEvent(GwtEvent<?> event) {
eventBus.fireEvent(event);
}
@Override
public HandlerRegistration addValueChangeHandler(
ValueChangeHandler<Boolean> handler) {
return eventBus.addHandler(ValueChangeEvent.getType(), handler);
}
@Override
public String toString() {
return key + "=" + (value ? "1" : "0");
}
}
}