You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

VUIDLBrowser.java 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. /*
  2. * Copyright 2011 Vaadin Ltd.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  5. * use this file except in compliance with the License. You may obtain a copy of
  6. * the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  12. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  13. * License for the specific language governing permissions and limitations under
  14. * the License.
  15. */
  16. /**
  17. *
  18. */
  19. package com.vaadin.client;
  20. import java.util.Iterator;
  21. import java.util.Set;
  22. import com.google.gwt.core.client.JsArray;
  23. import com.google.gwt.core.client.JsArrayString;
  24. import com.google.gwt.core.client.Scheduler;
  25. import com.google.gwt.core.client.Scheduler.ScheduledCommand;
  26. import com.google.gwt.dom.client.Document;
  27. import com.google.gwt.dom.client.Element;
  28. import com.google.gwt.dom.client.Style;
  29. import com.google.gwt.dom.client.Style.Position;
  30. import com.google.gwt.dom.client.Style.Unit;
  31. import com.google.gwt.event.dom.client.ClickEvent;
  32. import com.google.gwt.event.dom.client.MouseOutEvent;
  33. import com.google.gwt.event.dom.client.MouseOutHandler;
  34. import com.google.gwt.json.client.JSONArray;
  35. import com.google.gwt.json.client.JSONObject;
  36. import com.google.gwt.json.client.JSONValue;
  37. import com.google.gwt.user.client.ui.RootPanel;
  38. import com.google.gwt.user.client.ui.Widget;
  39. import com.vaadin.client.ui.UnknownComponentConnector;
  40. import com.vaadin.client.ui.window.VWindow;
  41. import com.vaadin.shared.Connector;
  42. /**
  43. * TODO Rename to something more Vaadin7-ish?
  44. */
  45. public class VUIDLBrowser extends SimpleTree {
  46. private static final String HELP = "Shift click handle to open recursively. "
  47. + " Click components to highlight them on client side."
  48. + " Shift click components to highlight them also on the server side.";
  49. private ApplicationConnection client;
  50. private String highlightedPid;
  51. public VUIDLBrowser(final UIDL uidl, ApplicationConnection client) {
  52. this.client = client;
  53. final UIDLItem root = new UIDLItem(uidl);
  54. add(root);
  55. }
  56. public VUIDLBrowser(ValueMap u, ApplicationConnection client) {
  57. this.client = client;
  58. ValueMap valueMap = u.getValueMap("meta");
  59. if (valueMap.containsKey("hl")) {
  60. highlightedPid = valueMap.getString("hl");
  61. }
  62. Set<String> keySet = u.getKeySet();
  63. for (String key : keySet) {
  64. if (key.equals("state")) {
  65. ValueMap stateJson = u.getValueMap(key);
  66. SimpleTree stateChanges = new SimpleTree("shared state");
  67. for (String connectorId : stateJson.getKeySet()) {
  68. stateChanges.add(new SharedStateItem(connectorId, stateJson
  69. .getValueMap(connectorId)));
  70. }
  71. add(stateChanges);
  72. } else if (key.equals("changes")) {
  73. JsArray<UIDL> jsValueMapArray = u.getJSValueMapArray(key)
  74. .cast();
  75. for (int i = 0; i < jsValueMapArray.length(); i++) {
  76. UIDL uidl = jsValueMapArray.get(i);
  77. UIDLItem change = new UIDLItem(uidl);
  78. change.setTitle("change " + i);
  79. add(change);
  80. }
  81. } else if (key.equals("meta")) {
  82. } else {
  83. // TODO consider pretty printing other request data such as
  84. // hierarchy changes
  85. // addItem(key + " : " + u.getAsString(key));
  86. }
  87. }
  88. open(highlightedPid != null);
  89. setTitle(HELP);
  90. }
  91. /**
  92. * A debug view of a server-originated component state change.
  93. */
  94. abstract class StateChangeItem extends SimpleTree {
  95. protected StateChangeItem() {
  96. setTitle(HELP);
  97. addDomHandler(new MouseOutHandler() {
  98. @Override
  99. public void onMouseOut(MouseOutEvent event) {
  100. deHiglight();
  101. }
  102. }, MouseOutEvent.getType());
  103. }
  104. @Override
  105. protected void select(ClickEvent event) {
  106. ComponentConnector connector = getConnector();
  107. highlight(connector);
  108. if (event != null && event.getNativeEvent().getShiftKey()) {
  109. connector.getConnection().highlightComponent(connector);
  110. }
  111. super.select(event);
  112. }
  113. /**
  114. * Returns the Connector associated with this state change.
  115. */
  116. protected ComponentConnector getConnector() {
  117. Connector connector = client.getConnectorMap().getConnector(
  118. getConnectorId());
  119. if (connector instanceof ComponentConnector) {
  120. return (ComponentConnector) connector;
  121. } else {
  122. return null;
  123. }
  124. }
  125. protected abstract String getConnectorId();
  126. }
  127. /**
  128. * A debug view of a Vaadin 7 style shared state change.
  129. */
  130. class SharedStateItem extends StateChangeItem {
  131. private String connectorId;
  132. SharedStateItem(String connectorId, ValueMap stateChanges) {
  133. this.connectorId = connectorId;
  134. ComponentConnector connector = getConnector();
  135. if (connector != null) {
  136. setText(Util.getConnectorString(connector));
  137. } else {
  138. setText("Unknown connector " + connectorId);
  139. }
  140. dir(new JSONObject(stateChanges), this);
  141. }
  142. @Override
  143. protected String getConnectorId() {
  144. return connectorId;
  145. }
  146. private void dir(String key, JSONValue value, SimpleTree tree) {
  147. if (value.isObject() != null) {
  148. SimpleTree subtree = new SimpleTree(key + "=object");
  149. tree.add(subtree);
  150. dir(value.isObject(), subtree);
  151. } else if (value.isArray() != null) {
  152. SimpleTree subtree = new SimpleTree(key + "=array");
  153. dir(value.isArray(), subtree);
  154. tree.add(subtree);
  155. } else {
  156. tree.addItem(key + "=" + value);
  157. }
  158. }
  159. private void dir(JSONObject state, SimpleTree tree) {
  160. for (String key : state.keySet()) {
  161. dir(key, state.get(key), tree);
  162. }
  163. }
  164. private void dir(JSONArray array, SimpleTree tree) {
  165. for (int i = 0; i < array.size(); ++i) {
  166. dir("" + i, array.get(i), tree);
  167. }
  168. }
  169. }
  170. /**
  171. * A debug view of a Vaadin 6 style hierarchical component state change.
  172. */
  173. class UIDLItem extends StateChangeItem {
  174. private UIDL uidl;
  175. UIDLItem(UIDL uidl) {
  176. this.uidl = uidl;
  177. try {
  178. String name = uidl.getTag();
  179. try {
  180. name = getNodeName(uidl, client.getConfiguration(),
  181. Integer.parseInt(name));
  182. } catch (Exception e) {
  183. // NOP
  184. }
  185. setText(name);
  186. addItem("LOADING");
  187. } catch (Exception e) {
  188. setText(uidl.toString());
  189. }
  190. }
  191. @Override
  192. protected String getConnectorId() {
  193. return uidl.getId();
  194. }
  195. private String getNodeName(UIDL uidl, ApplicationConfiguration conf,
  196. int tag) {
  197. Class<? extends ServerConnector> widgetClassByDecodedTag = conf
  198. .getConnectorClassByEncodedTag(tag);
  199. if (widgetClassByDecodedTag == UnknownComponentConnector.class) {
  200. return conf.getUnknownServerClassNameByTag(tag)
  201. + "(NO CLIENT IMPLEMENTATION FOUND)";
  202. } else {
  203. return widgetClassByDecodedTag.getName();
  204. }
  205. }
  206. @Override
  207. public void open(boolean recursive) {
  208. if (getWidgetCount() == 1
  209. && getWidget(0).getElement().getInnerText()
  210. .equals("LOADING")) {
  211. dir();
  212. }
  213. super.open(recursive);
  214. }
  215. public void dir() {
  216. remove(0);
  217. String nodeName = uidl.getTag();
  218. try {
  219. nodeName = getNodeName(uidl, client.getConfiguration(),
  220. Integer.parseInt(nodeName));
  221. } catch (Exception e) {
  222. // NOP
  223. }
  224. Set<String> attributeNames = uidl.getAttributeNames();
  225. for (String name : attributeNames) {
  226. if (uidl.isMapAttribute(name)) {
  227. try {
  228. ValueMap map = uidl.getMapAttribute(name);
  229. JsArrayString keyArray = map.getKeyArray();
  230. nodeName += " " + name + "=" + "{";
  231. for (int i = 0; i < keyArray.length(); i++) {
  232. nodeName += keyArray.get(i) + ":"
  233. + map.getAsString(keyArray.get(i)) + ",";
  234. }
  235. nodeName += "}";
  236. } catch (Exception e) {
  237. }
  238. } else {
  239. final String value = uidl.getAttribute(name);
  240. nodeName += " " + name + "=" + value;
  241. }
  242. }
  243. setText(nodeName);
  244. try {
  245. SimpleTree tmp = null;
  246. Set<String> variableNames = uidl.getVariableNames();
  247. for (String name : variableNames) {
  248. String value = "";
  249. try {
  250. value = uidl.getVariable(name);
  251. } catch (final Exception e) {
  252. try {
  253. String[] stringArrayAttribute = uidl
  254. .getStringArrayAttribute(name);
  255. value = stringArrayAttribute.toString();
  256. } catch (final Exception e2) {
  257. try {
  258. final int intVal = uidl.getIntVariable(name);
  259. value = String.valueOf(intVal);
  260. } catch (final Exception e3) {
  261. value = "unknown";
  262. }
  263. }
  264. }
  265. if (tmp == null) {
  266. tmp = new SimpleTree("variables");
  267. }
  268. tmp.addItem(name + "=" + value);
  269. }
  270. if (tmp != null) {
  271. add(tmp);
  272. }
  273. } catch (final Exception e) {
  274. // Ignored, no variables
  275. }
  276. final Iterator<Object> i = uidl.getChildIterator();
  277. while (i.hasNext()) {
  278. final Object child = i.next();
  279. try {
  280. add(new UIDLItem((UIDL) child));
  281. } catch (final Exception e) {
  282. addItem(child.toString());
  283. }
  284. }
  285. if (highlightedPid != null && highlightedPid.equals(uidl.getId())) {
  286. getElement().getStyle().setBackgroundColor("#fdd");
  287. Scheduler.get().scheduleDeferred(new ScheduledCommand() {
  288. @Override
  289. public void execute() {
  290. getElement().scrollIntoView();
  291. }
  292. });
  293. }
  294. }
  295. }
  296. static Element highlight = Document.get().createDivElement();
  297. static {
  298. Style style = highlight.getStyle();
  299. style.setPosition(Position.ABSOLUTE);
  300. style.setZIndex(VWindow.Z_INDEX + 1000);
  301. style.setBackgroundColor("red");
  302. style.setOpacity(0.2);
  303. if (BrowserInfo.get().isIE()) {
  304. style.setProperty("filter", "alpha(opacity=20)");
  305. }
  306. }
  307. static void highlight(ComponentConnector paintable) {
  308. if (paintable != null) {
  309. Widget w = paintable.getWidget();
  310. Style style = highlight.getStyle();
  311. style.setTop(w.getAbsoluteTop(), Unit.PX);
  312. style.setLeft(w.getAbsoluteLeft(), Unit.PX);
  313. style.setWidth(w.getOffsetWidth(), Unit.PX);
  314. style.setHeight(w.getOffsetHeight(), Unit.PX);
  315. RootPanel.getBodyElement().appendChild(highlight);
  316. }
  317. }
  318. static void deHiglight() {
  319. if (highlight.getParentElement() != null) {
  320. highlight.getParentElement().removeChild(highlight);
  321. }
  322. }
  323. }