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 36KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004
  1. /*
  2. @VaadinApache2LicenseForJavaFiles@
  3. */
  4. package com.vaadin.terminal.gwt.client;
  5. import java.util.Collection;
  6. import java.util.Date;
  7. import java.util.HashSet;
  8. import java.util.LinkedList;
  9. import java.util.List;
  10. import java.util.Set;
  11. import com.google.gwt.core.client.GWT;
  12. import com.google.gwt.core.client.JsArray;
  13. import com.google.gwt.core.client.Scheduler.ScheduledCommand;
  14. import com.google.gwt.dom.client.Style;
  15. import com.google.gwt.dom.client.Style.FontWeight;
  16. import com.google.gwt.dom.client.Style.Overflow;
  17. import com.google.gwt.dom.client.Style.Position;
  18. import com.google.gwt.dom.client.Style.Unit;
  19. import com.google.gwt.event.dom.client.ClickEvent;
  20. import com.google.gwt.event.dom.client.ClickHandler;
  21. import com.google.gwt.event.dom.client.KeyCodes;
  22. import com.google.gwt.event.dom.client.MouseOutEvent;
  23. import com.google.gwt.event.dom.client.MouseOutHandler;
  24. import com.google.gwt.event.logical.shared.ValueChangeEvent;
  25. import com.google.gwt.event.logical.shared.ValueChangeHandler;
  26. import com.google.gwt.event.shared.HandlerRegistration;
  27. import com.google.gwt.event.shared.UmbrellaException;
  28. import com.google.gwt.http.client.Request;
  29. import com.google.gwt.http.client.RequestBuilder;
  30. import com.google.gwt.http.client.RequestCallback;
  31. import com.google.gwt.http.client.RequestException;
  32. import com.google.gwt.http.client.Response;
  33. import com.google.gwt.http.client.UrlBuilder;
  34. import com.google.gwt.i18n.client.DateTimeFormat;
  35. import com.google.gwt.storage.client.Storage;
  36. import com.google.gwt.user.client.Cookies;
  37. import com.google.gwt.user.client.DOM;
  38. import com.google.gwt.user.client.Element;
  39. import com.google.gwt.user.client.Event;
  40. import com.google.gwt.user.client.Event.NativePreviewEvent;
  41. import com.google.gwt.user.client.Event.NativePreviewHandler;
  42. import com.google.gwt.user.client.EventPreview;
  43. import com.google.gwt.user.client.Window;
  44. import com.google.gwt.user.client.Window.Location;
  45. import com.google.gwt.user.client.ui.Button;
  46. import com.google.gwt.user.client.ui.CheckBox;
  47. import com.google.gwt.user.client.ui.FlowPanel;
  48. import com.google.gwt.user.client.ui.HTML;
  49. import com.google.gwt.user.client.ui.HorizontalPanel;
  50. import com.google.gwt.user.client.ui.Label;
  51. import com.google.gwt.user.client.ui.Panel;
  52. import com.google.gwt.user.client.ui.RootPanel;
  53. import com.google.gwt.user.client.ui.VerticalPanel;
  54. import com.google.gwt.user.client.ui.Widget;
  55. import com.vaadin.terminal.gwt.client.ui.VLazyExecutor;
  56. import com.vaadin.terminal.gwt.client.ui.VOverlay;
  57. import com.vaadin.terminal.gwt.client.ui.notification.VNotification;
  58. import com.vaadin.terminal.gwt.client.ui.root.RootConnector;
  59. import com.vaadin.terminal.gwt.client.ui.window.WindowConnector;
  60. /**
  61. * A helper console for client side development. The debug console can also be
  62. * used to resolve layout issues, inspect the communication between browser and
  63. * the server, start GWT dev mode and restart application.
  64. *
  65. * <p>
  66. * This implementation is used vaadin is in debug mode (see manual) and
  67. * developer appends "?debug" query parameter to url. Debug information can also
  68. * be shown on browsers internal console only, by appending "?debug=quiet" query
  69. * parameter.
  70. * <p>
  71. * This implementation can be overridden with GWT deferred binding.
  72. *
  73. */
  74. public class VDebugConsole extends VOverlay implements Console {
  75. private final class HighlightModeHandler implements NativePreviewHandler {
  76. private final Label label;
  77. private HighlightModeHandler(Label label) {
  78. this.label = label;
  79. }
  80. @Override
  81. public void onPreviewNativeEvent(NativePreviewEvent event) {
  82. if (event.getTypeInt() == Event.ONKEYDOWN
  83. && event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ESCAPE) {
  84. highlightModeRegistration.removeHandler();
  85. VUIDLBrowser.deHiglight();
  86. return;
  87. }
  88. if (event.getTypeInt() == Event.ONMOUSEMOVE) {
  89. VUIDLBrowser.deHiglight();
  90. Element eventTarget = Util.getElementFromPoint(event
  91. .getNativeEvent().getClientX(), event.getNativeEvent()
  92. .getClientY());
  93. if (getElement().isOrHasChild(eventTarget)) {
  94. return;
  95. }
  96. for (ApplicationConnection a : ApplicationConfiguration
  97. .getRunningApplications()) {
  98. ComponentConnector connector = Util.getConnectorForElement(
  99. a, a.getRootConnector().getWidget(), eventTarget);
  100. if (connector == null) {
  101. connector = Util.getConnectorForElement(a,
  102. RootPanel.get(), eventTarget);
  103. }
  104. if (connector != null) {
  105. String pid = connector.getConnectorId();
  106. VUIDLBrowser.highlight(connector);
  107. label.setText("Currently focused :"
  108. + connector.getClass() + " ID:" + pid);
  109. event.cancel();
  110. event.consume();
  111. event.getNativeEvent().stopPropagation();
  112. return;
  113. }
  114. }
  115. }
  116. if (event.getTypeInt() == Event.ONCLICK) {
  117. VUIDLBrowser.deHiglight();
  118. event.cancel();
  119. event.consume();
  120. event.getNativeEvent().stopPropagation();
  121. highlightModeRegistration.removeHandler();
  122. Element eventTarget = Util.getElementFromPoint(event
  123. .getNativeEvent().getClientX(), event.getNativeEvent()
  124. .getClientY());
  125. for (ApplicationConnection a : ApplicationConfiguration
  126. .getRunningApplications()) {
  127. ComponentConnector paintable = Util.getConnectorForElement(
  128. a, a.getRootConnector().getWidget(), eventTarget);
  129. if (paintable == null) {
  130. paintable = Util.getConnectorForElement(a,
  131. RootPanel.get(), eventTarget);
  132. }
  133. if (paintable != null) {
  134. a.highlightComponent(paintable);
  135. return;
  136. }
  137. }
  138. }
  139. event.cancel();
  140. }
  141. }
  142. private static final String POS_COOKIE_NAME = "VDebugConsolePos";
  143. private HandlerRegistration highlightModeRegistration;
  144. Element caption = DOM.createDiv();
  145. private Panel panel;
  146. private Button clear = new Button("C");
  147. private Button restart = new Button("R");
  148. private Button forceLayout = new Button("FL");
  149. private Button analyzeLayout = new Button("AL");
  150. private Button savePosition = new Button("S");
  151. private Button highlight = new Button("H");
  152. private Button connectorStats = new Button("CS");
  153. private CheckBox devMode = new CheckBox("Dev");
  154. private CheckBox superDevMode = new CheckBox("SDev");
  155. private CheckBox autoScroll = new CheckBox("Autoscroll ");
  156. private HorizontalPanel actions;
  157. private boolean collapsed = false;
  158. private boolean resizing;
  159. private int startX;
  160. private int startY;
  161. private int initialW;
  162. private int initialH;
  163. private boolean moving = false;
  164. private int origTop;
  165. private int origLeft;
  166. private static final String help = "Drag title=move, shift-drag=resize, doubleclick title=min/max."
  167. + "Use debug=quiet to log only to browser console.";
  168. private static final int DEFAULT_WIDTH = 650;
  169. private static final int DEFAULT_HEIGHT = 400;
  170. public VDebugConsole() {
  171. super(false, false);
  172. getElement().getStyle().setOverflow(Overflow.HIDDEN);
  173. clear.setTitle("Clear console");
  174. restart.setTitle("Restart app");
  175. forceLayout.setTitle("Force layout");
  176. analyzeLayout.setTitle("Analyze layouts");
  177. savePosition.setTitle("Save pos");
  178. }
  179. private EventPreview dragpreview = new EventPreview() {
  180. @Override
  181. public boolean onEventPreview(Event event) {
  182. onBrowserEvent(event);
  183. return false;
  184. }
  185. };
  186. private boolean quietMode;
  187. @Override
  188. public void onBrowserEvent(Event event) {
  189. super.onBrowserEvent(event);
  190. switch (DOM.eventGetType(event)) {
  191. case Event.ONMOUSEDOWN:
  192. if (DOM.eventGetShiftKey(event)) {
  193. resizing = true;
  194. DOM.setCapture(getElement());
  195. startX = DOM.eventGetScreenX(event);
  196. startY = DOM.eventGetScreenY(event);
  197. initialW = VDebugConsole.this.getOffsetWidth();
  198. initialH = VDebugConsole.this.getOffsetHeight();
  199. DOM.eventCancelBubble(event, true);
  200. DOM.eventPreventDefault(event);
  201. DOM.addEventPreview(dragpreview);
  202. } else if (DOM.eventGetTarget(event) == caption) {
  203. moving = true;
  204. startX = DOM.eventGetScreenX(event);
  205. startY = DOM.eventGetScreenY(event);
  206. origTop = getAbsoluteTop();
  207. origLeft = getAbsoluteLeft();
  208. DOM.eventCancelBubble(event, true);
  209. DOM.eventPreventDefault(event);
  210. DOM.addEventPreview(dragpreview);
  211. }
  212. break;
  213. case Event.ONMOUSEMOVE:
  214. if (resizing) {
  215. int deltaX = startX - DOM.eventGetScreenX(event);
  216. int detalY = startY - DOM.eventGetScreenY(event);
  217. int w = initialW - deltaX;
  218. if (w < 30) {
  219. w = 30;
  220. }
  221. int h = initialH - detalY;
  222. if (h < 40) {
  223. h = 40;
  224. }
  225. VDebugConsole.this.setPixelSize(w, h);
  226. DOM.eventCancelBubble(event, true);
  227. DOM.eventPreventDefault(event);
  228. } else if (moving) {
  229. int deltaX = startX - DOM.eventGetScreenX(event);
  230. int detalY = startY - DOM.eventGetScreenY(event);
  231. int left = origLeft - deltaX;
  232. if (left < 0) {
  233. left = 0;
  234. }
  235. int top = origTop - detalY;
  236. if (top < 0) {
  237. top = 0;
  238. }
  239. VDebugConsole.this.setPopupPosition(left, top);
  240. DOM.eventCancelBubble(event, true);
  241. DOM.eventPreventDefault(event);
  242. }
  243. break;
  244. case Event.ONLOSECAPTURE:
  245. case Event.ONMOUSEUP:
  246. if (resizing) {
  247. DOM.releaseCapture(getElement());
  248. resizing = false;
  249. } else if (moving) {
  250. DOM.releaseCapture(getElement());
  251. moving = false;
  252. }
  253. DOM.removeEventPreview(dragpreview);
  254. break;
  255. case Event.ONDBLCLICK:
  256. if (DOM.eventGetTarget(event) == caption) {
  257. if (collapsed) {
  258. panel.setVisible(true);
  259. setToDefaultSizeAndPos();
  260. } else {
  261. panel.setVisible(false);
  262. setPixelSize(120, 20);
  263. setPopupPosition(Window.getClientWidth() - 125,
  264. Window.getClientHeight() - 25);
  265. }
  266. collapsed = !collapsed;
  267. }
  268. break;
  269. default:
  270. break;
  271. }
  272. }
  273. private void setToDefaultSizeAndPos() {
  274. String cookie = Cookies.getCookie(POS_COOKIE_NAME);
  275. int width, height, top, left;
  276. boolean autoScrollValue = false;
  277. if (cookie != null) {
  278. String[] split = cookie.split(",");
  279. left = Integer.parseInt(split[0]);
  280. top = Integer.parseInt(split[1]);
  281. width = Integer.parseInt(split[2]);
  282. height = Integer.parseInt(split[3]);
  283. autoScrollValue = Boolean.valueOf(split[4]);
  284. } else {
  285. int windowHeight = Window.getClientHeight();
  286. int windowWidth = Window.getClientWidth();
  287. width = DEFAULT_WIDTH;
  288. height = DEFAULT_HEIGHT;
  289. if (height > windowHeight / 2) {
  290. height = windowHeight / 2;
  291. }
  292. if (width > windowWidth / 2) {
  293. width = windowWidth / 2;
  294. }
  295. top = windowHeight - (height + 10);
  296. left = windowWidth - (width + 10);
  297. }
  298. setPixelSize(width, height);
  299. setPopupPosition(left, top);
  300. autoScroll.setValue(autoScrollValue);
  301. }
  302. @Override
  303. public void setPixelSize(int width, int height) {
  304. if (height < 20) {
  305. height = 20;
  306. }
  307. if (width < 2) {
  308. width = 2;
  309. }
  310. panel.setHeight((height - 20) + "px");
  311. panel.setWidth((width - 2) + "px");
  312. getElement().getStyle().setWidth(width, Unit.PX);
  313. }
  314. /*
  315. * (non-Javadoc)
  316. *
  317. * @see com.vaadin.terminal.gwt.client.Console#log(java.lang.String)
  318. */
  319. @Override
  320. public void log(String msg) {
  321. if (msg == null) {
  322. msg = "null";
  323. }
  324. msg = addTimestamp(msg);
  325. // remoteLog(msg);
  326. logToDebugWindow(msg, false);
  327. GWT.log(msg);
  328. consoleLog(msg);
  329. System.out.println(msg);
  330. }
  331. private List<String> msgQueue = new LinkedList<String>();
  332. private ScheduledCommand doSend = new ScheduledCommand() {
  333. @Override
  334. public void execute() {
  335. if (!msgQueue.isEmpty()) {
  336. RequestBuilder requestBuilder = new RequestBuilder(
  337. RequestBuilder.POST, getRemoteLogUrl());
  338. try {
  339. String requestData = "";
  340. for (String str : msgQueue) {
  341. requestData += str;
  342. requestData += "\n";
  343. }
  344. requestBuilder.sendRequest(requestData,
  345. new RequestCallback() {
  346. @Override
  347. public void onResponseReceived(Request request,
  348. Response response) {
  349. // TODO Auto-generated method stub
  350. }
  351. @Override
  352. public void onError(Request request,
  353. Throwable exception) {
  354. // TODO Auto-generated method stub
  355. }
  356. });
  357. } catch (RequestException e) {
  358. // TODO Auto-generated catch block
  359. e.printStackTrace();
  360. }
  361. msgQueue.clear();
  362. }
  363. }
  364. };
  365. private VLazyExecutor sendToRemoteLog = new VLazyExecutor(350, doSend);
  366. protected String getRemoteLogUrl() {
  367. return "http://sun-vehje.local:8080/remotelog/";
  368. }
  369. protected void remoteLog(String msg) {
  370. msgQueue.add(msg);
  371. sendToRemoteLog.trigger();
  372. }
  373. /**
  374. * Logs the given message to the debug window.
  375. *
  376. * @param msg
  377. * The message to log. Must not be null.
  378. */
  379. private void logToDebugWindow(String msg, boolean error) {
  380. Widget row;
  381. if (error) {
  382. row = createErrorHtml(msg);
  383. } else {
  384. row = new HTML(msg);
  385. }
  386. panel.add(row);
  387. if (autoScroll.getValue()) {
  388. row.getElement().scrollIntoView();
  389. }
  390. }
  391. private HTML createErrorHtml(String msg) {
  392. HTML html = new HTML(msg);
  393. html.getElement().getStyle().setColor("#f00");
  394. html.getElement().getStyle().setFontWeight(FontWeight.BOLD);
  395. return html;
  396. }
  397. /*
  398. * (non-Javadoc)
  399. *
  400. * @see com.vaadin.terminal.gwt.client.Console#error(java.lang.String)
  401. */
  402. @Override
  403. public void error(String msg) {
  404. if (msg == null) {
  405. msg = "null";
  406. }
  407. msg = addTimestamp(msg);
  408. logToDebugWindow(msg, true);
  409. GWT.log(msg);
  410. consoleErr(msg);
  411. System.out.println(msg);
  412. }
  413. DateTimeFormat timestampFormat = DateTimeFormat.getFormat("HH:mm:ss:SSS");
  414. @SuppressWarnings("deprecation")
  415. private String addTimestamp(String msg) {
  416. Date date = new Date();
  417. String timestamp = timestampFormat.format(date);
  418. return timestamp + " " + msg;
  419. }
  420. /*
  421. * (non-Javadoc)
  422. *
  423. * @see com.vaadin.terminal.gwt.client.Console#printObject(java.lang.
  424. * Object)
  425. */
  426. @Override
  427. public void printObject(Object msg) {
  428. String str;
  429. if (msg == null) {
  430. str = "null";
  431. } else {
  432. str = msg.toString();
  433. }
  434. panel.add((new Label(str)));
  435. consoleLog(str);
  436. }
  437. /*
  438. * (non-Javadoc)
  439. *
  440. * @see com.vaadin.terminal.gwt.client.Console#dirUIDL(com.vaadin
  441. * .terminal.gwt.client.UIDL)
  442. */
  443. @Override
  444. public void dirUIDL(ValueMap u, ApplicationConfiguration conf) {
  445. if (panel.isAttached()) {
  446. VUIDLBrowser vuidlBrowser = new VUIDLBrowser(u, conf);
  447. vuidlBrowser.setText("Response:");
  448. panel.add(vuidlBrowser);
  449. }
  450. consoleDir(u);
  451. // consoleLog(u.getChildrenAsXML());
  452. }
  453. private static native void consoleDir(ValueMap u)
  454. /*-{
  455. if($wnd.console && $wnd.console.log) {
  456. if($wnd.console.dir) {
  457. $wnd.console.dir(u);
  458. } else {
  459. $wnd.console.log(u);
  460. }
  461. }
  462. }-*/;
  463. private static native void consoleLog(String msg)
  464. /*-{
  465. if($wnd.console && $wnd.console.log) {
  466. $wnd.console.log(msg);
  467. }
  468. }-*/;
  469. private static native void consoleErr(String msg)
  470. /*-{
  471. if($wnd.console) {
  472. if ($wnd.console.error)
  473. $wnd.console.error(msg);
  474. else if ($wnd.console.log)
  475. $wnd.console.log(msg);
  476. }
  477. }-*/;
  478. @Override
  479. public void printLayoutProblems(ValueMap meta, ApplicationConnection ac,
  480. Set<ComponentConnector> zeroHeightComponents,
  481. Set<ComponentConnector> zeroWidthComponents) {
  482. JsArray<ValueMap> valueMapArray = meta
  483. .getJSValueMapArray("invalidLayouts");
  484. int size = valueMapArray.length();
  485. panel.add(new HTML("<div>************************</di>"
  486. + "<h4>Layouts analyzed on server, total top level problems: "
  487. + size + " </h4>"));
  488. if (size > 0) {
  489. SimpleTree root = new SimpleTree("Root problems");
  490. for (int i = 0; i < size; i++) {
  491. printLayoutError(valueMapArray.get(i), root, ac);
  492. }
  493. panel.add(root);
  494. }
  495. if (zeroHeightComponents.size() > 0 || zeroWidthComponents.size() > 0) {
  496. panel.add(new HTML("<h4> Client side notifications</h4>"
  497. + " <em>The following relative sized components were "
  498. + "rendered to a zero size container on the client side."
  499. + " Note that these are not necessarily invalid "
  500. + "states, but reported here as they might be.</em>"));
  501. if (zeroHeightComponents.size() > 0) {
  502. panel.add(new HTML(
  503. "<p><strong>Vertically zero size:</strong><p>"));
  504. printClientSideDetectedIssues(zeroHeightComponents, ac);
  505. }
  506. if (zeroWidthComponents.size() > 0) {
  507. panel.add(new HTML(
  508. "<p><strong>Horizontally zero size:</strong><p>"));
  509. printClientSideDetectedIssues(zeroWidthComponents, ac);
  510. }
  511. }
  512. log("************************");
  513. }
  514. private void printClientSideDetectedIssues(
  515. Set<ComponentConnector> zeroHeightComponents,
  516. ApplicationConnection ac) {
  517. for (final ComponentConnector paintable : zeroHeightComponents) {
  518. final ServerConnector parent = paintable.getParent();
  519. VerticalPanel errorDetails = new VerticalPanel();
  520. errorDetails.add(new Label("" + Util.getSimpleName(paintable)
  521. + " inside " + Util.getSimpleName(parent)));
  522. if (parent instanceof ComponentConnector) {
  523. ComponentConnector parentComponent = (ComponentConnector) parent;
  524. final Widget layout = parentComponent.getWidget();
  525. final CheckBox emphasisInUi = new CheckBox(
  526. "Emphasize components parent in UI (the actual component is not visible)");
  527. emphasisInUi.addClickHandler(new ClickHandler() {
  528. @Override
  529. public void onClick(ClickEvent event) {
  530. Element element2 = layout.getElement();
  531. Widget.setStyleName(element2, "invalidlayout",
  532. emphasisInUi.getValue().booleanValue());
  533. }
  534. });
  535. errorDetails.add(emphasisInUi);
  536. }
  537. panel.add(errorDetails);
  538. }
  539. }
  540. private void printLayoutError(ValueMap valueMap, SimpleTree root,
  541. final ApplicationConnection ac) {
  542. final String pid = valueMap.getString("id");
  543. final ComponentConnector paintable = (ComponentConnector) ConnectorMap
  544. .get(ac).getConnector(pid);
  545. SimpleTree errorNode = new SimpleTree();
  546. VerticalPanel errorDetails = new VerticalPanel();
  547. errorDetails.add(new Label(Util.getSimpleName(paintable) + " id: "
  548. + pid));
  549. if (valueMap.containsKey("heightMsg")) {
  550. errorDetails.add(new Label("Height problem: "
  551. + valueMap.getString("heightMsg")));
  552. }
  553. if (valueMap.containsKey("widthMsg")) {
  554. errorDetails.add(new Label("Width problem: "
  555. + valueMap.getString("widthMsg")));
  556. }
  557. final CheckBox emphasisInUi = new CheckBox("Emphasize component in UI");
  558. emphasisInUi.addClickHandler(new ClickHandler() {
  559. @Override
  560. public void onClick(ClickEvent event) {
  561. if (paintable != null) {
  562. Element element2 = paintable.getWidget().getElement();
  563. Widget.setStyleName(element2, "invalidlayout",
  564. emphasisInUi.getValue());
  565. }
  566. }
  567. });
  568. errorDetails.add(emphasisInUi);
  569. errorNode.add(errorDetails);
  570. if (valueMap.containsKey("subErrors")) {
  571. HTML l = new HTML(
  572. "<em>Expand this node to show problems that may be dependent on this problem.</em>");
  573. errorDetails.add(l);
  574. JsArray<ValueMap> suberrors = valueMap
  575. .getJSValueMapArray("subErrors");
  576. for (int i = 0; i < suberrors.length(); i++) {
  577. ValueMap value = suberrors.get(i);
  578. printLayoutError(value, errorNode, ac);
  579. }
  580. }
  581. root.add(errorNode);
  582. }
  583. @Override
  584. public void log(Throwable e) {
  585. if (e instanceof UmbrellaException) {
  586. UmbrellaException ue = (UmbrellaException) e;
  587. for (Throwable t : ue.getCauses()) {
  588. log(t);
  589. }
  590. return;
  591. }
  592. log(Util.getSimpleName(e) + ": " + e.getMessage());
  593. GWT.log(e.getMessage(), e);
  594. }
  595. @Override
  596. public void error(Throwable e) {
  597. handleError(e, this);
  598. }
  599. static void handleError(Throwable e, Console target) {
  600. if (e instanceof UmbrellaException) {
  601. UmbrellaException ue = (UmbrellaException) e;
  602. for (Throwable t : ue.getCauses()) {
  603. target.error(t);
  604. }
  605. return;
  606. }
  607. String exceptionText = Util.getSimpleName(e);
  608. String message = e.getMessage();
  609. if (message != null && message.length() != 0) {
  610. exceptionText += ": " + e.getMessage();
  611. }
  612. target.error(exceptionText);
  613. GWT.log(e.getMessage(), e);
  614. if (!GWT.isProdMode()) {
  615. e.printStackTrace();
  616. }
  617. try {
  618. VNotification.createNotification(VNotification.DELAY_FOREVER).show(
  619. "<h1>Uncaught client side exception</h1><br />"
  620. + exceptionText, VNotification.CENTERED, "error");
  621. } catch (Exception e2) {
  622. // Just swallow this exception
  623. }
  624. }
  625. @Override
  626. public void init() {
  627. panel = new FlowPanel();
  628. if (!quietMode) {
  629. DOM.appendChild(getContainerElement(), caption);
  630. setWidget(panel);
  631. caption.setClassName("v-debug-console-caption");
  632. setStyleName("v-debug-console");
  633. getElement().getStyle().setZIndex(20000);
  634. getElement().getStyle().setOverflow(Overflow.HIDDEN);
  635. sinkEvents(Event.ONDBLCLICK);
  636. sinkEvents(Event.MOUSEEVENTS);
  637. panel.setStyleName("v-debug-console-content");
  638. caption.setInnerHTML("Debug window");
  639. caption.getStyle().setHeight(25, Unit.PX);
  640. caption.setTitle(help);
  641. show();
  642. setToDefaultSizeAndPos();
  643. actions = new HorizontalPanel();
  644. Style style = actions.getElement().getStyle();
  645. style.setPosition(Position.ABSOLUTE);
  646. style.setBackgroundColor("#666");
  647. style.setLeft(135, Unit.PX);
  648. style.setHeight(25, Unit.PX);
  649. style.setTop(0, Unit.PX);
  650. actions.add(clear);
  651. actions.add(restart);
  652. actions.add(forceLayout);
  653. actions.add(analyzeLayout);
  654. actions.add(highlight);
  655. actions.add(connectorStats);
  656. connectorStats.setTitle("Show connector statistics for client");
  657. highlight
  658. .setTitle("Select a component and print details about it to the server log and client side console.");
  659. actions.add(savePosition);
  660. savePosition
  661. .setTitle("Saves the position and size of debug console to a cookie");
  662. actions.add(autoScroll);
  663. addDevMode();
  664. addSuperDevMode();
  665. autoScroll
  666. .setTitle("Automatically scroll so that new messages are visible");
  667. panel.add(actions);
  668. panel.add(new HTML("<i>" + help + "</i>"));
  669. clear.addClickHandler(new ClickHandler() {
  670. @Override
  671. public void onClick(ClickEvent event) {
  672. int width = panel.getOffsetWidth();
  673. int height = panel.getOffsetHeight();
  674. panel = new FlowPanel();
  675. panel.setPixelSize(width, height);
  676. panel.setStyleName("v-debug-console-content");
  677. panel.add(actions);
  678. setWidget(panel);
  679. }
  680. });
  681. restart.addClickHandler(new ClickHandler() {
  682. @Override
  683. public void onClick(ClickEvent event) {
  684. String queryString = Window.Location.getQueryString();
  685. if (queryString != null
  686. && queryString.contains("restartApplications")) {
  687. Window.Location.reload();
  688. } else {
  689. String url = Location.getHref();
  690. String separator = "?";
  691. if (url.contains("?")) {
  692. separator = "&";
  693. }
  694. if (!url.contains("restartApplication")) {
  695. url += separator;
  696. url += "restartApplication";
  697. }
  698. if (!"".equals(Location.getHash())) {
  699. String hash = Location.getHash();
  700. url = url.replace(hash, "") + hash;
  701. }
  702. Window.Location.replace(url);
  703. }
  704. }
  705. });
  706. forceLayout.addClickHandler(new ClickHandler() {
  707. @Override
  708. public void onClick(ClickEvent event) {
  709. for (ApplicationConnection applicationConnection : ApplicationConfiguration
  710. .getRunningApplications()) {
  711. applicationConnection.forceLayout();
  712. }
  713. }
  714. });
  715. analyzeLayout.addClickHandler(new ClickHandler() {
  716. @Override
  717. public void onClick(ClickEvent event) {
  718. List<ApplicationConnection> runningApplications = ApplicationConfiguration
  719. .getRunningApplications();
  720. for (ApplicationConnection applicationConnection : runningApplications) {
  721. applicationConnection.analyzeLayouts();
  722. }
  723. }
  724. });
  725. analyzeLayout
  726. .setTitle("Analyzes currently rendered view and "
  727. + "reports possible common problems in usage of relative sizes."
  728. + "Will cause server visit/rendering of whole screen and loss of"
  729. + " all non committed variables form client side.");
  730. savePosition.addClickHandler(new ClickHandler() {
  731. @Override
  732. public void onClick(ClickEvent event) {
  733. String pos = getAbsoluteLeft() + "," + getAbsoluteTop()
  734. + "," + getOffsetWidth() + "," + getOffsetHeight()
  735. + "," + autoScroll.getValue();
  736. Cookies.setCookie(POS_COOKIE_NAME, pos);
  737. }
  738. });
  739. highlight.addClickHandler(new ClickHandler() {
  740. @Override
  741. public void onClick(ClickEvent event) {
  742. final Label label = new Label("--");
  743. log("<i>Use mouse to select a component or click ESC to exit highlight mode.</i>");
  744. panel.add(label);
  745. highlightModeRegistration = Event
  746. .addNativePreviewHandler(new HighlightModeHandler(
  747. label));
  748. }
  749. });
  750. }
  751. connectorStats.addClickHandler(new ClickHandler() {
  752. @Override
  753. public void onClick(ClickEvent event) {
  754. for (ApplicationConnection a : ApplicationConfiguration
  755. .getRunningApplications()) {
  756. dumpConnectorInfo(a);
  757. }
  758. }
  759. });
  760. log("Starting Vaadin client side engine. Widgetset: "
  761. + GWT.getModuleName());
  762. log("Widget set is built on version: "
  763. + ApplicationConfiguration.VERSION);
  764. logToDebugWindow("<div class=\"v-theme-version v-theme-version-"
  765. + ApplicationConfiguration.VERSION.replaceAll("\\.", "_")
  766. + "\">Warning: widgetset version "
  767. + ApplicationConfiguration.VERSION
  768. + " does not seem to match theme version </div>", true);
  769. }
  770. private void addSuperDevMode() {
  771. final Storage sessionStorage = Storage.getSessionStorageIfSupported();
  772. if (sessionStorage == null) {
  773. return;
  774. }
  775. actions.add(superDevMode);
  776. if (Location.getParameter("superdevmode") != null) {
  777. superDevMode.setValue(true);
  778. }
  779. superDevMode.addValueChangeHandler(new ValueChangeHandler<Boolean>() {
  780. @Override
  781. public void onValueChange(ValueChangeEvent<Boolean> event) {
  782. SuperDevMode.redirect(event.getValue());
  783. }
  784. });
  785. }
  786. private void addDevMode() {
  787. actions.add(devMode);
  788. if (Location.getParameter("gwt.codesvr") != null) {
  789. devMode.setValue(true);
  790. }
  791. devMode.addClickHandler(new ClickHandler() {
  792. @Override
  793. public void onClick(ClickEvent event) {
  794. if (devMode.getValue()) {
  795. addHMParameter();
  796. } else {
  797. removeHMParameter();
  798. }
  799. }
  800. private void addHMParameter() {
  801. UrlBuilder createUrlBuilder = Location.createUrlBuilder();
  802. createUrlBuilder.setParameter("gwt.codesvr", "localhost:9997");
  803. Location.assign(createUrlBuilder.buildString());
  804. }
  805. private void removeHMParameter() {
  806. UrlBuilder createUrlBuilder = Location.createUrlBuilder();
  807. createUrlBuilder.removeParameter("gwt.codesvr");
  808. Location.assign(createUrlBuilder.buildString());
  809. }
  810. });
  811. }
  812. protected void dumpConnectorInfo(ApplicationConnection a) {
  813. RootConnector root = a.getRootConnector();
  814. log("================");
  815. log("Connector hierarchy for Root: " + root.getState().getCaption()
  816. + " (" + root.getConnectorId() + ")");
  817. Set<ServerConnector> connectorsInHierarchy = new HashSet<ServerConnector>();
  818. SimpleTree rootHierachy = dumpConnectorHierarchy(root, "",
  819. connectorsInHierarchy);
  820. if (panel.isAttached()) {
  821. rootHierachy.open(true);
  822. panel.add(rootHierachy);
  823. }
  824. ConnectorMap connectorMap = a.getConnectorMap();
  825. Collection<? extends ServerConnector> registeredConnectors = connectorMap
  826. .getConnectors();
  827. log("Sub windows:");
  828. Set<ServerConnector> subWindowHierarchyConnectors = new HashSet<ServerConnector>();
  829. for (WindowConnector wc : root.getSubWindows()) {
  830. SimpleTree windowHierachy = dumpConnectorHierarchy(wc, "",
  831. subWindowHierarchyConnectors);
  832. if (panel.isAttached()) {
  833. windowHierachy.open(true);
  834. panel.add(windowHierachy);
  835. }
  836. }
  837. log("Registered connectors not in hierarchy (should be empty):");
  838. for (ServerConnector registeredConnector : registeredConnectors) {
  839. if (connectorsInHierarchy.contains(registeredConnector)) {
  840. continue;
  841. }
  842. if (subWindowHierarchyConnectors.contains(registeredConnector)) {
  843. continue;
  844. }
  845. error(getConnectorString(registeredConnector));
  846. }
  847. log("Unregistered connectors in hierarchy (should be empty):");
  848. for (ServerConnector hierarchyConnector : connectorsInHierarchy) {
  849. if (!connectorMap.hasConnector(hierarchyConnector.getConnectorId())) {
  850. error(getConnectorString(hierarchyConnector));
  851. }
  852. }
  853. log("================");
  854. }
  855. private SimpleTree dumpConnectorHierarchy(final ServerConnector connector,
  856. String indent, Set<ServerConnector> connectors) {
  857. SimpleTree simpleTree = new SimpleTree(getConnectorString(connector)) {
  858. @Override
  859. protected void select(ClickEvent event) {
  860. super.select(event);
  861. if (connector instanceof ComponentConnector) {
  862. VUIDLBrowser.highlight((ComponentConnector) connector);
  863. }
  864. }
  865. };
  866. simpleTree.addDomHandler(new MouseOutHandler() {
  867. @Override
  868. public void onMouseOut(MouseOutEvent event) {
  869. VUIDLBrowser.deHiglight();
  870. }
  871. }, MouseOutEvent.getType());
  872. connectors.add(connector);
  873. String msg = indent + "* " + getConnectorString(connector);
  874. GWT.log(msg);
  875. consoleLog(msg);
  876. System.out.println(msg);
  877. for (ServerConnector c : connector.getChildren()) {
  878. simpleTree.add(dumpConnectorHierarchy(c, indent + " ", connectors));
  879. }
  880. return simpleTree;
  881. }
  882. private static String getConnectorString(ServerConnector connector) {
  883. return Util.getConnectorString(connector);
  884. }
  885. @Override
  886. public void setQuietMode(boolean quietDebugMode) {
  887. quietMode = quietDebugMode;
  888. }
  889. }