1 package autotest.common;
2 
3 import com.google.gwt.event.logical.shared.ValueChangeEvent;
4 import com.google.gwt.event.logical.shared.ValueChangeHandler;
5 import com.google.gwt.user.client.History;
6 
7 import java.util.ArrayList;
8 import java.util.HashMap;
9 import java.util.List;
10 import java.util.Map;
11 
12 /**
13  * Wrapper around gwt.user.client.History that won't call onHistoryChanged for
14  * programmatically-generated history items.
15  *
16  */
17 public class CustomHistory implements ValueChangeHandler<String> {
18     private static final CustomHistory theInstance = new CustomHistory();
19 
20     public static class HistoryToken extends HashMap<String, String> {
21         @Override
toString()22         public String toString() {
23             return Utils.encodeUrlArguments(this);
24         }
25 
fromString(String tokenString)26         public static HistoryToken fromString(String tokenString) {
27             HistoryToken token = new HistoryToken();
28             Utils.decodeUrlArguments(tokenString, token);
29             return token;
30         }
31     }
32 
33     private List<CustomHistoryListener> listeners = new ArrayList<CustomHistoryListener>();
34     private HistoryToken lastHistoryToken = new HistoryToken();
35 
36     public static interface CustomHistoryListener {
onHistoryChanged(Map<String, String> arguments)37         public void onHistoryChanged(Map<String, String> arguments);
38     }
39 
CustomHistory()40     private CustomHistory() {
41         History.addValueChangeHandler(this);
42     }
43 
44     /**
45      * Allows programmatic simulation of history changes, without actually changing history or the
46      * URL.
47      */
simulateHistoryToken(HistoryToken token)48     public static void simulateHistoryToken(HistoryToken token) {
49         theInstance.processHistoryTokenString(token.toString());
50     }
51 
processInitialToken()52     public static void processInitialToken() {
53         theInstance.processHistoryTokenString(History.getToken());
54     }
55 
56     @Override
onValueChange(ValueChangeEvent<String> event)57     public void onValueChange(ValueChangeEvent<String> event) {
58         processHistoryTokenString(event.getValue());
59     }
60 
processHistoryTokenString(String historyTokenString)61     private void processHistoryTokenString(String historyTokenString) {
62         HistoryToken token;
63         try {
64             token = HistoryToken.fromString(historyTokenString);
65         } catch (IllegalArgumentException exc) {
66             return;
67         }
68 
69         if (token.equals(lastHistoryToken)) {
70             return;
71         }
72 
73         lastHistoryToken = token;
74 
75         for (CustomHistoryListener listener : listeners) {
76             listener.onHistoryChanged(token);
77         }
78     }
79 
getLastHistoryToken()80     public static HistoryToken getLastHistoryToken() {
81         return theInstance.lastHistoryToken;
82     }
83 
addHistoryListener(CustomHistoryListener listener)84     public static void addHistoryListener(CustomHistoryListener listener) {
85         theInstance.listeners.add(listener);
86     }
87 
removeHistoryListener(CustomHistoryListener listener)88     public static void removeHistoryListener(CustomHistoryListener listener) {
89         theInstance.listeners.remove(listener);
90     }
91 
newItem(HistoryToken token)92     public static void newItem(HistoryToken token) {
93         if (token.equals(getLastHistoryToken())) {
94             return;
95         }
96         theInstance.lastHistoryToken = token;
97         History.newItem(token.toString());
98     }
99 }
100