diff options
author | Matti Tahvonen <matti.tahvonen@itmill.com> | 2008-12-17 13:52:59 +0000 |
---|---|---|
committer | Matti Tahvonen <matti.tahvonen@itmill.com> | 2008-12-17 13:52:59 +0000 |
commit | 45a80c0b64d3374e519a7b50325bd703f383107f (patch) | |
tree | 86ac4c00ccc67298b92aa525fad424516b4023db /src/com/itmill | |
parent | d54e4916938ae5b2101ddcec3a871132352575cd (diff) | |
download | vaadin-framework-45a80c0b64d3374e519a7b50325bd703f383107f.tar.gz vaadin-framework-45a80c0b64d3374e519a7b50325bd703f383107f.zip |
relative size handling changes towards #2319
svn changeset:6252/svn branch:trunk
Diffstat (limited to 'src/com/itmill')
8 files changed, 296 insertions, 85 deletions
diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ApplicationConfiguration.java b/src/com/itmill/toolkit/terminal/gwt/client/ApplicationConfiguration.java index 10738998f3..93ce11fb69 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ApplicationConfiguration.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ApplicationConfiguration.java @@ -2,6 +2,7 @@ package com.itmill.toolkit.terminal.gwt.client; import java.util.ArrayList; import java.util.Iterator; +import java.util.List; import com.google.gwt.core.client.JavaScriptObject; @@ -13,7 +14,8 @@ public class ApplicationConfiguration { private String appUri; private JavaScriptObject versionInfo; - private static ArrayList unstartedApplications = new ArrayList(); + private static ArrayList<ApplicationConnection> unstartedApplications = new ArrayList<ApplicationConnection>(); + private static ArrayList<ApplicationConnection> runningApplications = new ArrayList<ApplicationConnection>(); public String getRootPanelId() { return id; @@ -93,15 +95,19 @@ public class ApplicationConfiguration { */ public static boolean startNextApplication() { if (unstartedApplications.size() > 0) { - ApplicationConnection a = (ApplicationConnection) unstartedApplications - .remove(0); + ApplicationConnection a = unstartedApplications.remove(0); a.start(); + runningApplications.add(a); return true; } else { return false; } } + public static List<ApplicationConnection> getRunningApplications() { + return runningApplications; + } + private native static void loadAppIdListFromDOM(ArrayList list) /*-{ diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ApplicationConnection.java b/src/com/itmill/toolkit/terminal/gwt/client/ApplicationConnection.java index 1b20fa3efe..8d1d4271ae 100755 --- a/src/com/itmill/toolkit/terminal/gwt/client/ApplicationConnection.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ApplicationConnection.java @@ -169,7 +169,7 @@ public class ApplicationConnection { * to avoid session-id problems. */ void start() { - makeUidlRequest("", true, false); + makeUidlRequest("", true, false, false); } /** @@ -294,7 +294,7 @@ public class ApplicationConnection { } private void makeUidlRequest(String requestData, boolean repaintAll, - boolean forceSync) { + boolean forceSync, boolean analyzeLayouts) { startRequest(); // Security: double cookie submission pattern @@ -304,6 +304,9 @@ public class ApplicationConnection { String uri = getAppUri() + "UIDL" + configuration.getPathInfo(); if (repaintAll) { uri += "?repaintAll=1"; + if (analyzeLayouts) { + uri += "&analyzeLayouts=1"; + } } if (windowName != null && windowName.length() > 0) { uri += (repaintAll ? "&" : "?") + "windowName=" + windowName; @@ -683,6 +686,10 @@ public class ApplicationConnection { } applicationRunning = false; } + if (meta.containsKey("invalidLayouts")) { + getConsole().printLayoutProblems( + meta.get("invalidLayouts").isArray(), this); + } } final long prosessingTime = (new Date().getTime()) - start.getTime(); @@ -836,7 +843,7 @@ public class ApplicationConnection { req.append(VAR_BURST_SEPARATOR); } } - makeUidlRequest(req.toString(), false, forceSync); + makeUidlRequest(req.toString(), false, forceSync, false); } public void updateVariable(String paintableId, String variableName, @@ -1477,4 +1484,8 @@ public class ApplicationConnection { public void captionSizeUpdated(Widget component) { captionSizeChanges.add(component); } + + public void analyzeLayouts() { + makeUidlRequest("", true, false, true); + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/Console.java b/src/com/itmill/toolkit/terminal/gwt/client/Console.java index 51cc9311f4..28d4b38843 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/Console.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/Console.java @@ -4,6 +4,8 @@ package com.itmill.toolkit.terminal.gwt.client; +import com.google.gwt.json.client.JSONArray; + public interface Console { public abstract void log(String msg); @@ -14,4 +16,7 @@ public interface Console { public abstract void dirUIDL(UIDL u); + public abstract void printLayoutProblems(JSONArray array, + ApplicationConnection applicationConnection); + }
\ No newline at end of file diff --git a/src/com/itmill/toolkit/terminal/gwt/client/IDebugConsole.java b/src/com/itmill/toolkit/terminal/gwt/client/IDebugConsole.java index c6464df23d..cf9d71954f 100755 --- a/src/com/itmill/toolkit/terminal/gwt/client/IDebugConsole.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/IDebugConsole.java @@ -4,6 +4,11 @@ package com.itmill.toolkit.terminal.gwt.client; +import java.util.List; + +import com.google.gwt.json.client.JSONArray; +import com.google.gwt.json.client.JSONObject; +import com.google.gwt.json.client.JSONValue; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Element; import com.google.gwt.user.client.Event; @@ -11,12 +16,16 @@ import com.google.gwt.user.client.EventPreview; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.Window.Location; import com.google.gwt.user.client.ui.Button; +import com.google.gwt.user.client.ui.CheckBox; import com.google.gwt.user.client.ui.ClickListener; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.Panel; +import com.google.gwt.user.client.ui.Tree; +import com.google.gwt.user.client.ui.TreeItem; +import com.google.gwt.user.client.ui.VerticalPanel; import com.google.gwt.user.client.ui.Widget; import com.itmill.toolkit.terminal.gwt.client.ui.IToolkitOverlay; @@ -43,6 +52,7 @@ public final class IDebugConsole extends IToolkitOverlay implements Console { private Button clear = new Button("Clear console"); private Button restart = new Button("Restart app"); private Button forceLayout = new Button("Force layout"); + private Button analyzeLayout = new Button("Analyze layout"); private HorizontalPanel actions; private boolean collapsed = false; @@ -95,6 +105,7 @@ public final class IDebugConsole extends IToolkitOverlay implements Console { actions.add(clear); actions.add(restart); actions.add(forceLayout); + actions.add(analyzeLayout); panel.add(actions); @@ -139,6 +150,20 @@ public final class IDebugConsole extends IToolkitOverlay implements Console { IDebugConsole.this.client.forceLayout(); } }); + + analyzeLayout.addClickListener(new ClickListener() { + public void onClick(Widget sender) { + List<ApplicationConnection> runningApplications = ApplicationConfiguration + .getRunningApplications(); + for (ApplicationConnection applicationConnection : runningApplications) { + applicationConnection.analyzeLayouts(); + } + } + }); + analyzeLayout + .setTitle("Repaints everything with analyze flag, giving information " + + "about most likely invalid layouts."); + } log("Toolkit application servlet version: " + cnf.getSerletVersion()); @@ -321,4 +346,67 @@ public final class IDebugConsole extends IToolkitOverlay implements Console { } }-*/; + public void printLayoutProblems(JSONArray array, ApplicationConnection ac) { + log("************************"); + int size = array.size(); + log("Layout analyzed, total top level errors: " + size); + if (size > 0) { + Tree tree = new Tree(); + TreeItem root = new TreeItem("Root errors"); + for (int i = 0; i < size; i++) { + JSONObject error = array.get(i).isObject(); + printLayoutError(error, root, ac); + } + panel.add(tree); + tree.addItem(root); + } + log("************************"); + } + + private void printLayoutError(JSONObject error, TreeItem parent, + final ApplicationConnection ac) { + final String pid = error.get("id").isString().stringValue(); + final Paintable paintable = ac.getPaintable(pid); + + TreeItem errorNode = new TreeItem(); + VerticalPanel errorDetails = new VerticalPanel(); + errorDetails.add(new Label("Error in " + Util.getSimpleName(paintable) + + " id: " + pid)); + if (error.containsKey("heightMsg")) { + errorDetails.add(new Label("Height error: " + + error.get("heightMsg"))); + } + if (error.containsKey("widthMsg")) { + errorDetails + .add(new Label("Width error: " + error.get("widthMsg"))); + } + final CheckBox emphasisInUi = new CheckBox("Emphasis component in UI"); + emphasisInUi.addClickListener(new ClickListener() { + public void onClick(Widget sender) { + if (paintable != null) { + Element element2 = ((Widget) paintable).getElement(); + Widget.setStyleName(element2, "invalidlayout", emphasisInUi + .isChecked()); + } + } + }); + errorDetails.add(emphasisInUi); + errorNode.setWidget(errorDetails); + if (error.containsKey("subErrors")) { + HTML l = new HTML( + "<em>Expand this tree node to show errors that may be dependent about this error</em>"); + errorDetails.add(l); + JSONArray array = error.get("subErrors").isArray(); + for (int i = 0; i < array.size(); i++) { + JSONValue value = array.get(i); + if (value != null && value.isObject() != null) { + printLayoutError(value.isObject(), errorNode, ac); + } else { + System.out.print(value); + } + } + + } + parent.addItem(errorNode); + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/NullConsole.java b/src/com/itmill/toolkit/terminal/gwt/client/NullConsole.java index 2c158b6ab7..ab22b42216 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/NullConsole.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/NullConsole.java @@ -4,6 +4,8 @@ package com.itmill.toolkit.terminal.gwt.client; +import com.google.gwt.json.client.JSONArray; + /** * Client side console implementation for non-debug mode that discards all * messages. @@ -23,4 +25,7 @@ public class NullConsole implements Console { public void printObject(Object msg) { } + public void printLayoutProblems(JSONArray array, ApplicationConnection ac) { + } + } diff --git a/src/com/itmill/toolkit/terminal/gwt/server/CommunicationManager.java b/src/com/itmill/toolkit/terminal/gwt/server/CommunicationManager.java index 5b39bba5ca..acdc8665d1 100644 --- a/src/com/itmill/toolkit/terminal/gwt/server/CommunicationManager.java +++ b/src/com/itmill/toolkit/terminal/gwt/server/CommunicationManager.java @@ -54,6 +54,7 @@ import com.itmill.toolkit.terminal.VariableOwner; import com.itmill.toolkit.terminal.Paintable.RepaintRequestEvent; import com.itmill.toolkit.terminal.Terminal.ErrorEvent; import com.itmill.toolkit.terminal.gwt.client.ApplicationConnection; +import com.itmill.toolkit.terminal.gwt.server.DebugUtilities.InvalidLayout; import com.itmill.toolkit.ui.AbstractField; import com.itmill.toolkit.ui.Component; import com.itmill.toolkit.ui.Upload; @@ -88,6 +89,8 @@ public class CommunicationManager implements Paintable.RepaintRequestListener { private static final int MAX_BUFFER_SIZE = 64 * 1024; + private static final String GET_PARAM_ANALYZE_LAYOUTS = "analyzeLayouts"; + private final ArrayList dirtyPaintabletSet = new ArrayList(); private final HashMap paintableIdMap = new HashMap(); @@ -225,6 +228,11 @@ public class CommunicationManager implements Paintable.RepaintRequestListener { // repaint requested or session has timed out and new one is created boolean repaintAll = (request.getParameter(GET_PARAM_REPAINT_ALL) != null) || request.getSession().isNew(); + boolean analyzeLayouts = false; + if (repaintAll) { + // analyzing can be done only with repaintAll + analyzeLayouts = (request.getParameter(GET_PARAM_ANALYZE_LAYOUTS) != null); + } final OutputStream out = response.getOutputStream(); final PrintWriter outWriter = new PrintWriter(new BufferedWriter( @@ -286,7 +294,7 @@ public class CommunicationManager implements Paintable.RepaintRequestListener { } paintAfterVariablechanges(request, response, applicationServlet, - repaintAll, outWriter, window); + repaintAll, outWriter, window, analyzeLayouts); // Mark this window to be open on client currentlyOpenWindowsInClient.add(window.getName()); @@ -303,8 +311,8 @@ public class CommunicationManager implements Paintable.RepaintRequestListener { private void paintAfterVariablechanges(HttpServletRequest request, HttpServletResponse response, ApplicationServlet applicationServlet, boolean repaintAll, - final PrintWriter outWriter, Window window) throws IOException, - ServletException, PaintException { + final PrintWriter outWriter, Window window, boolean analyzeLayouts) + throws IOException, ServletException, PaintException { // If repaint is requested, clean all ids in this root window if (repaintAll) { @@ -337,6 +345,8 @@ public class CommunicationManager implements Paintable.RepaintRequestListener { // all if (!window.getName().equals(closingWindowName)) { + List<InvalidLayout> invalidComponentRelativeSizes = null; + // re-get window - may have been changed Window newWindow = getApplicationWindow(request, application, window); @@ -434,6 +444,12 @@ public class CommunicationManager implements Paintable.RepaintRequestListener { paintTarget.endTag("change"); } paintablePainted(p); + + if (analyzeLayouts) { + invalidComponentRelativeSizes = DebugUtilities + .validateComponentRelativeSizes(((Window) p) + .getLayout(), null, null); + } } } @@ -446,6 +462,23 @@ public class CommunicationManager implements Paintable.RepaintRequestListener { if (repaintAll) { metaOpen = true; outWriter.write("\"repaintAll\":true"); + if (analyzeLayouts) { + outWriter.write(", \"invalidLayouts\":"); + outWriter.write("["); + if (invalidComponentRelativeSizes != null) { + boolean first = true; + for (InvalidLayout invalidLayout : invalidComponentRelativeSizes) { + if (!first) { + outWriter.write(","); + } else { + first = false; + } + invalidLayout.reportErrors(outWriter, this, + System.err); + } + } + outWriter.write("]"); + } } SystemMessages ci = null; @@ -727,7 +760,8 @@ public class CommunicationManager implements Paintable.RepaintRequestListener { new CharArrayWriter()); try { paintAfterVariablechanges(request, response, - applicationServlet, true, outWriter, window); + applicationServlet, true, outWriter, window, + false); } catch (ServletException e) { // We will ignore all servlet exceptions } diff --git a/src/com/itmill/toolkit/terminal/gwt/server/DebugUtilities.java b/src/com/itmill/toolkit/terminal/gwt/server/DebugUtilities.java index fdbb6618f4..7da98ed0f0 100644 --- a/src/com/itmill/toolkit/terminal/gwt/server/DebugUtilities.java +++ b/src/com/itmill/toolkit/terminal/gwt/server/DebugUtilities.java @@ -1,9 +1,14 @@ package com.itmill.toolkit.terminal.gwt.server; +import java.io.PrintStream; +import java.io.PrintWriter; import java.util.HashMap; import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; import java.util.Map; import java.util.Stack; +import java.util.Vector; import com.itmill.toolkit.terminal.Sizeable; import com.itmill.toolkit.ui.AbstractOrderedLayout; @@ -29,35 +34,48 @@ public class DebugUtilities { * * @param component * component to check + * @return set of first level errors found */ - public static boolean validateComponentRelativeSizes(Component component, - boolean recursive) { - - boolean valid = checkWidths(component) && checkHeights(component); - - if (recursive) { - if (component instanceof Panel) { - Panel panel = (Panel) component; - if (!validateComponentRelativeSizes(panel.getLayout(), false)) { - valid = false; - } - } else if (component instanceof ComponentContainer) { - ComponentContainer lo = (ComponentContainer) component; - Iterator it = lo.getComponentIterator(); - while (it.hasNext()) { - if (!validateComponentRelativeSizes((Component) it.next(), - false)) { - valid = false; - } + public static List<InvalidLayout> validateComponentRelativeSizes( + Component component, List<InvalidLayout> errors, + InvalidLayout parent) { + + boolean invalidHeight = !checkHeights(component); + boolean invalidWidth = !checkWidths(component); + + if (invalidHeight || invalidWidth) { + InvalidLayout error = new InvalidLayout(component, invalidHeight, + invalidWidth); + if (parent != null) { + parent.addError(error); + } else { + if (errors == null) { + errors = new LinkedList<InvalidLayout>(); } + errors.add(error); + } + parent = error; + } + + if (component instanceof Panel) { + Panel panel = (Panel) component; + errors = validateComponentRelativeSizes(panel.getLayout(), errors, + parent); + } else if (component instanceof ComponentContainer) { + ComponentContainer lo = (ComponentContainer) component; + Iterator it = lo.getComponentIterator(); + while (it.hasNext()) { + errors = validateComponentRelativeSizes((Component) it.next(), + errors, parent); } } - return valid; + return errors; } - private static void showError(String msg, Stack<ComponentInfo> attributes, - boolean widthError) { + private static void printServerError(String msg, + Stack<ComponentInfo> attributes, boolean widthError, + PrintStream errorStream) { StringBuffer err = new StringBuffer(); err.append("IT MILL Toolkit DEBUG\n"); @@ -78,23 +96,72 @@ public class DebugUtilities { err.append("\n"); err .append("Components may be invisible or not render as expected. Relative sizes were replaced by undefined sizes.\n"); - System.err.println(err); + errorStream.println(err); } public static boolean checkHeights(Component component) { - String msg = null; try { + if (!hasRelativeHeight(component)) { + return true; + } if (component instanceof Window) { return true; } + return !(component.getParent() != null && parentCannotDefineHeight(component)); + } catch (Exception e) { + e.printStackTrace(); + return true; + } + } + + public static boolean checkWidths(Component component) { + try { + if (!hasRelativeWidth(component)) { + return true; + } + if (component instanceof Window) { + return true; + } + return !(component.getParent() != null && parentCannotDefineWidth(component)); + } catch (Exception e) { + e.printStackTrace(); + return true; + } + } + + public static class InvalidLayout { + + private Component component; + + private boolean invalidHeight; + private boolean invalidWidth; + + private Vector<InvalidLayout> subErrors = new Vector<InvalidLayout>(); + + public InvalidLayout(Component component, boolean height, boolean width) { + this.component = component; + invalidHeight = height; + invalidWidth = width; + } + + public void addError(InvalidLayout error) { + subErrors.add(error); + } + + public void reportErrors(PrintWriter clientJSON, + CommunicationManager communicationManager, + PrintStream serverErrorStream) { + clientJSON.write("{"); Component parent = component.getParent(); - Stack<ComponentInfo> attributes = null; + String paintableId = communicationManager.getPaintableId(component); - if (hasRelativeHeight(component) && parent != null - && parentCannotDefineHeight(parent, component)) { + clientJSON.print("id:\"" + paintableId + "\""); + if (invalidHeight) { + Stack<ComponentInfo> attributes = null; + String msg = ""; // set proper error messages if (parent instanceof AbstractOrderedLayout) { AbstractOrderedLayout ol = (AbstractOrderedLayout) parent; @@ -123,29 +190,12 @@ public class DebugUtilities { msg = "Relative height component's parent should not have undefined height."; attributes = getHeightAttributes(component); } + printServerError(msg, attributes, false, serverErrorStream); + clientJSON.print(",\"heightMsg\":\"" + msg + "\""); } - - if (msg != null) { - showError(msg, attributes, false); - } - } catch (Exception e) { - e.printStackTrace(); - } - return (msg == null); - } - - public static boolean checkWidths(Component component) { - String msg = null; - try { - if (component instanceof Window) { - return true; - } - - Component parent = component.getParent(); - Stack<ComponentInfo> attributes = null; - - if (hasRelativeWidth(component) && parent != null - && parentCannotDefineWidth(parent, component)) { + if (invalidWidth) { + Stack<ComponentInfo> attributes = null; + String msg = ""; if (parent instanceof AbstractOrderedLayout) { AbstractOrderedLayout ol = (AbstractOrderedLayout) parent; boolean horizontal = true; @@ -173,16 +223,27 @@ public class DebugUtilities { msg = "Relative width component's parent should not have undefined width."; attributes = getWidthAttributes(component); } + clientJSON.print(",\"widthMsg\":\"" + msg + "\""); + printServerError(msg, attributes, true, serverErrorStream); } - - if (msg != null) { - showError(msg, attributes, true); + if (subErrors.size() > 0) { + serverErrorStream.println("Sub erros >>"); + clientJSON.write(", \"subErrors\" : ["); + boolean first = true; + for (InvalidLayout subError : subErrors) { + if (first) { + clientJSON.print(","); + } else { + first = false; + } + subError.reportErrors(clientJSON, communicationManager, + serverErrorStream); + } + clientJSON.write("]"); + serverErrorStream.println("<< Sub erros"); } - } catch (Exception e) { - e.printStackTrace(); + clientJSON.write("}"); } - - return (msg == null); } private static class ComponentInfo { @@ -316,8 +377,12 @@ public class DebugUtilities { return false; } - private static boolean parentCannotDefineHeight(Component parent, - Component component) { + public static boolean parentCannotDefineHeight(Component component) { + Component parent = component.getParent(); + if (parent == null) { + // main window, valid situation + return false; + } if (parent.getHeight() < 0) { if (parent instanceof Window) { Window w = (Window) parent; @@ -375,7 +440,7 @@ public class DebugUtilities { } else { if (hasRelativeHeight(parent) && parent.getParent() != null) { - return parentCannotDefineHeight(parent.getParent(), parent); + return parentCannotDefineHeight(parent); } else { return false; } @@ -402,8 +467,12 @@ public class DebugUtilities { && paintable.getWidthUnits() == Sizeable.UNITS_PERCENTAGE; } - private static boolean parentCannotDefineWidth(Component parent, - Component component) { + public static boolean parentCannotDefineWidth(Component component) { + Component parent = component.getParent(); + if (parent == null) { + // main window, valid situation + return false; + } if (parent instanceof Window) { Window w = (Window) parent; if (w.getParent() == null) { @@ -469,7 +538,7 @@ public class DebugUtilities { } } else { if (hasRelativeWidth(parent) && parent.getParent() != null) { - return parentCannotDefineWidth(parent.getParent(), parent); + return parentCannotDefineWidth(parent); } else { return false; } diff --git a/src/com/itmill/toolkit/ui/AbstractComponent.java b/src/com/itmill/toolkit/ui/AbstractComponent.java index 5a692736e7..94e194d351 100644 --- a/src/com/itmill/toolkit/ui/AbstractComponent.java +++ b/src/com/itmill/toolkit/ui/AbstractComponent.java @@ -609,22 +609,15 @@ public abstract class AbstractComponent implements Component, MethodEventSource // Only paint content of visible components. if (isVisible()) { - boolean validHeight = true; - boolean validWidth = true; - - if (getApplication() != null && getApplication().isDebugMode()) { - validHeight = DebugUtilities.checkHeights(this); - validWidth = DebugUtilities.checkWidths(this); - } - if (!validHeight || !validWidth) { - addStyleName("invalidlayout"); - } - - if (validHeight && getHeight() >= 0) { + if (getHeight() >= 0 + && (getHeightUnits() != UNITS_PERCENTAGE || !DebugUtilities + .parentCannotDefineHeight(this))) { target.addAttribute("height", "" + getCSSHeight()); } - if (validWidth && getWidth() >= 0) { + if (getWidth() >= 0 + && (getWidthUnits() != UNITS_PERCENTAGE || !DebugUtilities + .parentCannotDefineWidth(this))) { target.addAttribute("width", "" + getCSSWidth()); } if (styles != null && styles.size() > 0) { |