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.

VDebugConsole.java 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  1. /*
  2. @ITMillApache2LicenseForJavaFiles@
  3. */
  4. package com.vaadin.terminal.gwt.client;
  5. import java.util.List;
  6. import java.util.Set;
  7. import com.google.gwt.core.client.JsArray;
  8. import com.google.gwt.user.client.DOM;
  9. import com.google.gwt.user.client.Element;
  10. import com.google.gwt.user.client.Event;
  11. import com.google.gwt.user.client.EventPreview;
  12. import com.google.gwt.user.client.Window;
  13. import com.google.gwt.user.client.Window.Location;
  14. import com.google.gwt.user.client.ui.Button;
  15. import com.google.gwt.user.client.ui.CheckBox;
  16. import com.google.gwt.user.client.ui.ClickListener;
  17. import com.google.gwt.user.client.ui.FlowPanel;
  18. import com.google.gwt.user.client.ui.HTML;
  19. import com.google.gwt.user.client.ui.HorizontalPanel;
  20. import com.google.gwt.user.client.ui.Label;
  21. import com.google.gwt.user.client.ui.Panel;
  22. import com.google.gwt.user.client.ui.Tree;
  23. import com.google.gwt.user.client.ui.TreeItem;
  24. import com.google.gwt.user.client.ui.VerticalPanel;
  25. import com.google.gwt.user.client.ui.Widget;
  26. import com.vaadin.terminal.gwt.client.ui.VOverlay;
  27. public final class VDebugConsole extends VOverlay implements Console {
  28. /**
  29. * Builds number. For example 0-custom_tag in 5.0.0-custom_tag.
  30. */
  31. public static final String VERSION;
  32. /* Initialize version numbers from string replaced by build-script. */
  33. static {
  34. if ("@VERSION@".equals("@" + "VERSION" + "@")) {
  35. VERSION = "5.9.9-INTERNAL-NONVERSIONED-DEBUG-BUILD";
  36. } else {
  37. VERSION = "@VERSION@";
  38. }
  39. }
  40. Element caption = DOM.createDiv();
  41. private Panel panel;
  42. private Button clear = new Button("Clear console");
  43. private Button restart = new Button("Restart app");
  44. private Button forceLayout = new Button("Force layout");
  45. private Button analyzeLayout = new Button("Analyze layouts");
  46. private HorizontalPanel actions;
  47. private boolean collapsed = false;
  48. private boolean resizing;
  49. private int startX;
  50. private int startY;
  51. private int initialW;
  52. private int initialH;
  53. private boolean moving = false;
  54. private int origTop;
  55. private int origLeft;
  56. private ApplicationConnection client;
  57. private static final String help = "Drag=move, shift-drag=resize, doubleclick=min/max."
  58. + "Use debug=quiet to log only to browser console.";
  59. public VDebugConsole(ApplicationConnection client,
  60. ApplicationConfiguration cnf, boolean showWindow) {
  61. super(false, false);
  62. this.client = client;
  63. panel = new FlowPanel();
  64. if (showWindow) {
  65. DOM.appendChild(getContainerElement(), caption);
  66. setWidget(panel);
  67. caption.setClassName("v-debug-console-caption");
  68. setStyleName("v-debug-console");
  69. DOM.setStyleAttribute(getElement(), "zIndex", 20000 + "");
  70. DOM.setStyleAttribute(getElement(), "overflow", "hidden");
  71. sinkEvents(Event.ONDBLCLICK);
  72. sinkEvents(Event.MOUSEEVENTS);
  73. panel.setStyleName("v-debug-console-content");
  74. caption.setInnerHTML("Debug window");
  75. caption.setTitle(help);
  76. show();
  77. minimize();
  78. actions = new HorizontalPanel();
  79. actions.add(clear);
  80. actions.add(restart);
  81. actions.add(forceLayout);
  82. actions.add(analyzeLayout);
  83. panel.add(actions);
  84. panel.add(new HTML("<i>" + help + "</i>"));
  85. clear.addClickListener(new ClickListener() {
  86. public void onClick(Widget sender) {
  87. int width = panel.getOffsetWidth();
  88. int height = panel.getOffsetHeight();
  89. panel = new FlowPanel();
  90. panel.setPixelSize(width, height);
  91. panel.setStyleName("v-debug-console-content");
  92. panel.add(actions);
  93. setWidget(panel);
  94. }
  95. });
  96. restart.addClickListener(new ClickListener() {
  97. public void onClick(Widget sender) {
  98. String queryString = Window.Location.getQueryString();
  99. if (queryString != null
  100. && queryString.contains("restartApplications")) {
  101. Window.Location.reload();
  102. } else {
  103. String url = Location.getHref();
  104. String separator = "?";
  105. if (url.contains("?")) {
  106. separator = "&";
  107. }
  108. if (!url.contains("restartApplication")) {
  109. url += separator;
  110. url += "restartApplication";
  111. }
  112. if (!"".equals(Location.getHash())) {
  113. String hash = Location.getHash();
  114. url = url.replace(hash, "") + hash;
  115. }
  116. Window.Location.replace(url);
  117. }
  118. }
  119. });
  120. forceLayout.addClickListener(new ClickListener() {
  121. public void onClick(Widget sender) {
  122. VDebugConsole.this.client.forceLayout();
  123. }
  124. });
  125. analyzeLayout.addClickListener(new ClickListener() {
  126. public void onClick(Widget sender) {
  127. List<ApplicationConnection> runningApplications = ApplicationConfiguration
  128. .getRunningApplications();
  129. for (ApplicationConnection applicationConnection : runningApplications) {
  130. applicationConnection.analyzeLayouts();
  131. }
  132. }
  133. });
  134. analyzeLayout
  135. .setTitle("Analyzes currently rendered view and "
  136. + "reports possible common problems in usage of relative sizes."
  137. + "Will cause server visit/rendering of whole screen + lose of"
  138. + " all non committed variables form client side.");
  139. }
  140. log("Vaadin application servlet version: " + cnf.getServletVersion());
  141. log("Widget set is built on version: " + VERSION);
  142. log("Application version: " + cnf.getApplicationVersion());
  143. if (!cnf.getServletVersion().equals(VERSION)) {
  144. error("Warning: your widget set seems to be built with a different "
  145. + "version than the one used on server. Unexpected "
  146. + "behavior may occur.");
  147. }
  148. }
  149. private EventPreview dragpreview = new EventPreview() {
  150. public boolean onEventPreview(Event event) {
  151. onBrowserEvent(event);
  152. return false;
  153. }
  154. };
  155. @Override
  156. public void onBrowserEvent(Event event) {
  157. super.onBrowserEvent(event);
  158. switch (DOM.eventGetType(event)) {
  159. case Event.ONMOUSEDOWN:
  160. if (DOM.eventGetShiftKey(event)) {
  161. resizing = true;
  162. DOM.setCapture(getElement());
  163. startX = DOM.eventGetScreenX(event);
  164. startY = DOM.eventGetScreenY(event);
  165. initialW = VDebugConsole.this.getOffsetWidth();
  166. initialH = VDebugConsole.this.getOffsetHeight();
  167. DOM.eventCancelBubble(event, true);
  168. DOM.eventPreventDefault(event);
  169. DOM.addEventPreview(dragpreview);
  170. } else if (DOM.eventGetTarget(event) == caption) {
  171. moving = true;
  172. startX = DOM.eventGetScreenX(event);
  173. startY = DOM.eventGetScreenY(event);
  174. origTop = getAbsoluteTop();
  175. origLeft = getAbsoluteLeft();
  176. DOM.eventCancelBubble(event, true);
  177. DOM.eventPreventDefault(event);
  178. DOM.addEventPreview(dragpreview);
  179. }
  180. break;
  181. case Event.ONMOUSEMOVE:
  182. if (resizing) {
  183. int deltaX = startX - DOM.eventGetScreenX(event);
  184. int detalY = startY - DOM.eventGetScreenY(event);
  185. int w = initialW - deltaX;
  186. if (w < 30) {
  187. w = 30;
  188. }
  189. int h = initialH - detalY;
  190. if (h < 40) {
  191. h = 40;
  192. }
  193. VDebugConsole.this.setPixelSize(w, h);
  194. DOM.eventCancelBubble(event, true);
  195. DOM.eventPreventDefault(event);
  196. } else if (moving) {
  197. int deltaX = startX - DOM.eventGetScreenX(event);
  198. int detalY = startY - DOM.eventGetScreenY(event);
  199. int left = origLeft - deltaX;
  200. if (left < 0) {
  201. left = 0;
  202. }
  203. int top = origTop - detalY;
  204. if (top < 0) {
  205. top = 0;
  206. }
  207. VDebugConsole.this.setPopupPosition(left, top);
  208. DOM.eventCancelBubble(event, true);
  209. DOM.eventPreventDefault(event);
  210. }
  211. break;
  212. case Event.ONLOSECAPTURE:
  213. case Event.ONMOUSEUP:
  214. if (resizing) {
  215. DOM.releaseCapture(getElement());
  216. resizing = false;
  217. } else if (moving) {
  218. DOM.releaseCapture(getElement());
  219. moving = false;
  220. }
  221. DOM.removeEventPreview(dragpreview);
  222. break;
  223. case Event.ONDBLCLICK:
  224. if (DOM.eventGetTarget(event) == caption) {
  225. if (collapsed) {
  226. panel.setVisible(true);
  227. setPixelSize(220, 300);
  228. } else {
  229. panel.setVisible(false);
  230. setPixelSize(120, 20);
  231. }
  232. collapsed = !collapsed;
  233. }
  234. break;
  235. default:
  236. break;
  237. }
  238. }
  239. private void minimize() {
  240. setPixelSize(400, 150);
  241. setPopupPosition(Window.getClientWidth() - 410, Window
  242. .getClientHeight() - 160);
  243. }
  244. @Override
  245. public void setPixelSize(int width, int height) {
  246. panel.setHeight((height - 20) + "px");
  247. panel.setWidth((width - 2) + "px");
  248. }
  249. /*
  250. * (non-Javadoc)
  251. *
  252. * @see com.vaadin.terminal.gwt.client.Console#log(java.lang.String)
  253. */
  254. public void log(String msg) {
  255. panel.add(new HTML(msg));
  256. System.out.println(msg);
  257. consoleLog(msg);
  258. }
  259. /*
  260. * (non-Javadoc)
  261. *
  262. * @see com.vaadin.terminal.gwt.client.Console#error(java.lang.String)
  263. */
  264. public void error(String msg) {
  265. panel.add((new HTML(msg)));
  266. System.err.println(msg);
  267. consoleErr(msg);
  268. }
  269. /*
  270. * (non-Javadoc)
  271. *
  272. * @see com.vaadin.terminal.gwt.client.Console#printObject(java.lang.
  273. * Object)
  274. */
  275. public void printObject(Object msg) {
  276. panel.add((new Label(msg.toString())));
  277. consoleLog(msg.toString());
  278. }
  279. /*
  280. * (non-Javadoc)
  281. *
  282. * @see com.vaadin.terminal.gwt.client.Console#dirUIDL(com.vaadin
  283. * .terminal.gwt.client.UIDL)
  284. */
  285. public void dirUIDL(UIDL u) {
  286. if (panel.isAttached()) {
  287. panel.add(new VUIDLBrowser(u));
  288. }
  289. consoleDir(u);
  290. // consoleLog(u.getChildrenAsXML());
  291. }
  292. private static native void consoleDir(UIDL u)
  293. /*-{
  294. if($wnd.console && $wnd.console.log) {
  295. if($wnd.console.dir) {
  296. $wnd.console.dir(u);
  297. } else {
  298. $wnd.console.log(u);
  299. }
  300. }
  301. }-*/;
  302. private static native void consoleLog(String msg)
  303. /*-{
  304. if($wnd.console && $wnd.console.log) {
  305. $wnd.console.log(msg);
  306. }
  307. }-*/;
  308. private static native void consoleErr(String msg)
  309. /*-{
  310. if($wnd.console) {
  311. if ($wnd.console.error)
  312. $wnd.console.error(msg);
  313. else if ($wnd.console.log)
  314. $wnd.console.log(msg);
  315. }
  316. }-*/;
  317. public void printLayoutProblems(ValueMap meta, ApplicationConnection ac,
  318. Set<Paintable> zeroHeightComponents,
  319. Set<Paintable> zeroWidthComponents) {
  320. JsArray<ValueMap> valueMapArray = meta
  321. .getJSValueMapArray("invalidLayouts");
  322. int size = valueMapArray.length();
  323. panel.add(new HTML("<div>************************</di>"
  324. + "<h4>Layouts analyzed on server, total top level problems: "
  325. + size + " </h4>"));
  326. if (size > 0) {
  327. Tree tree = new Tree();
  328. // Position relative does not work here in IE7
  329. DOM.setStyleAttribute(tree.getElement(), "position", "");
  330. TreeItem root = new TreeItem("Root problems");
  331. for (int i = 0; i < size; i++) {
  332. printLayoutError(valueMapArray.get(i), root, ac);
  333. }
  334. panel.add(tree);
  335. tree.addItem(root);
  336. }
  337. if (zeroHeightComponents.size() > 0 || zeroWidthComponents.size() > 0) {
  338. panel.add(new HTML("<h4> Client side notifications</h4>"
  339. + " <em>Following relative sized components where "
  340. + "rendered to zero size container on client side."
  341. + " Note that these are not necessary invalid "
  342. + "states. Just reported here as they might be.</em>"));
  343. if (zeroHeightComponents.size() > 0) {
  344. panel.add(new HTML(
  345. "<p><strong>Vertically zero size:</strong><p>"));
  346. printClientSideDetectedIssues(zeroHeightComponents, ac);
  347. }
  348. if (zeroWidthComponents.size() > 0) {
  349. panel.add(new HTML(
  350. "<p><strong>Horizontally zero size:</strong><p>"));
  351. printClientSideDetectedIssues(zeroWidthComponents, ac);
  352. }
  353. }
  354. log("************************");
  355. }
  356. private void printClientSideDetectedIssues(
  357. Set<Paintable> zeroHeightComponents, ApplicationConnection ac) {
  358. for (final Paintable paintable : zeroHeightComponents) {
  359. final Container layout = Util.getLayout((Widget) paintable);
  360. VerticalPanel errorDetails = new VerticalPanel();
  361. errorDetails.add(new Label("" + Util.getSimpleName(paintable)
  362. + " inside " + Util.getSimpleName(layout)));
  363. final CheckBox emphasisInUi = new CheckBox(
  364. "Emphasis components parent in UI (actual component is not visible)");
  365. emphasisInUi.addClickListener(new ClickListener() {
  366. public void onClick(Widget sender) {
  367. if (paintable != null) {
  368. Element element2 = ((Widget) layout).getElement();
  369. Widget.setStyleName(element2, "invalidlayout",
  370. emphasisInUi.isChecked());
  371. }
  372. }
  373. });
  374. errorDetails.add(emphasisInUi);
  375. panel.add(errorDetails);
  376. }
  377. }
  378. private void printLayoutError(ValueMap valueMap, TreeItem parent,
  379. final ApplicationConnection ac) {
  380. final String pid = valueMap.getString("id");
  381. final Paintable paintable = ac.getPaintable(pid);
  382. TreeItem errorNode = new TreeItem();
  383. VerticalPanel errorDetails = new VerticalPanel();
  384. errorDetails.add(new Label(Util.getSimpleName(paintable) + " id: "
  385. + pid));
  386. if (valueMap.containsKey("heightMsg")) {
  387. errorDetails.add(new Label("Height problem: "
  388. + valueMap.getString("heightMsg")));
  389. }
  390. if (valueMap.containsKey("widthMsg")) {
  391. errorDetails.add(new Label("Width problem: "
  392. + valueMap.getString("widthMsg")));
  393. }
  394. final CheckBox emphasisInUi = new CheckBox("Emphasis component in UI");
  395. emphasisInUi.addClickListener(new ClickListener() {
  396. public void onClick(Widget sender) {
  397. if (paintable != null) {
  398. Element element2 = ((Widget) paintable).getElement();
  399. Widget.setStyleName(element2, "invalidlayout", emphasisInUi
  400. .isChecked());
  401. }
  402. }
  403. });
  404. errorDetails.add(emphasisInUi);
  405. errorNode.setWidget(errorDetails);
  406. if (valueMap.containsKey("subErrors")) {
  407. HTML l = new HTML(
  408. "<em>Expand this node to show problems that may be dependent on this problem.</em>");
  409. errorDetails.add(l);
  410. JsArray<ValueMap> suberrors = valueMap
  411. .getJSValueMapArray("subErrors");
  412. for (int i = 0; i < suberrors.length(); i++) {
  413. ValueMap value = suberrors.get(i);
  414. printLayoutError(value, errorNode, ac);
  415. }
  416. }
  417. parent.addItem(errorNode);
  418. }
  419. }