Changeset 5570

Show
Ignore:
Timestamp:
10/01/08 06:40:48 (7 weeks ago)
Author:
artur.signell@…
Message:

Changed the way relative component sizes are handled. Relative sizes are now converted into pixel sizes in ApplictionConnection?.
All containers MUST now implement Container which includes the getAllocatedSpace() method used by the relative size calculator.

This also fixes OrderedLayout? bugs #2021, #2034, #2030, #2102
Also fixes #2127

Location:
trunk
Files:
1 added
30 modified

Legend:

Unmodified
Added
Removed
  • trunk/WebContent/ITMILL/themes/default/orderedlayout/orderedlayout.css

    r5245 r5570  
    2020 
    2121/* Placing error indicator right after the widget with empty caption */ 
    22 .i-orderedlayout-c * { float:left; display: block;} 
     22.i-orderedlayout-c * { float:left;} 
    2323.i-orderedlayout-w-e { float:left;} 
    2424* html .i-orderedlayout-c, * html .i-orderedlayout-w { height: 1%; } 
    25 .i-orderedlayout-w { display: block; } 
    2625.i-orderedlayout-c { float:left; display: block;} 
    2726.i-orderedlayout-w:after, .i-orderedlayout-c:after  { 
  • trunk/WebContent/ITMILL/themes/default/styles.css

    r5562 r5570  
    163163 */ 
    164164@media print { 
     165         
    165166        .i-generated-body { 
    166167                height: auto; 
     
    168169                overflow: visible; 
    169170        } 
     171 
    170172        .i-app { 
    171173                height:auto; 
     
    882884 
    883885/* Placing error indicator right after the widget with empty caption */ 
    884 .i-orderedlayout-c * { float:left; display: block;} 
     886.i-orderedlayout-c * { float:left;} 
    885887.i-orderedlayout-w-e { float:left;} 
    886888* html .i-orderedlayout-c, * html .i-orderedlayout-w { height: 1%; } 
    887 .i-orderedlayout-w { display: block; } 
    888889.i-orderedlayout-c { float:left; display: block;} 
    889890.i-orderedlayout-w:after, .i-orderedlayout-c:after  { 
  • trunk/src/com/itmill/toolkit/terminal/gwt/client/ApplicationConnection.java

    r5559 r5570  
    3636import com.google.gwt.user.client.ui.HasWidgets; 
    3737import com.google.gwt.user.client.ui.Widget; 
     38import com.itmill.toolkit.terminal.gwt.client.RenderInformation.FloatSize; 
     39import com.itmill.toolkit.terminal.gwt.client.RenderInformation.Size; 
    3840import com.itmill.toolkit.terminal.gwt.client.ui.Field; 
    3941import com.itmill.toolkit.terminal.gwt.client.ui.IContextMenu; 
     
    6668    private final Vector pendingVariables = new Vector(); 
    6769 
    68     private final HashMap idToPaintable = new HashMap(); 
    69  
    70     private final HashMap paintableToId = new HashMap(); 
     70    private final HashMap<String, Paintable> idToPaintable = new HashMap<String, Paintable>(); 
     71 
     72    private final HashMap<Paintable, String> paintableToId = new HashMap<Paintable, String>(); 
    7173 
    7274    /** Contains ExtendedTitleInfo by paintable id */ 
    73     private final HashMap paintableToTitle = new HashMap(); 
     75    private final HashMap<Paintable, TooltipInfo> paintableToTitle = new HashMap<Paintable, TooltipInfo>(); 
     76 
     77    private final HashMap<Widget, FloatSize> componentRelativeSizes = new HashMap<Widget, FloatSize>(); 
     78    private final HashMap<Widget, Size> componentOffsetSizes = new HashMap<Widget, Size>(); 
    7479 
    7580    private final WidgetSet widgetSet; 
     
    526531                .get("changes"); 
    527532 
    528         Set<Widget> sizeUpdatedWidgets = new HashSet<Widget>(); 
     533        Vector<Widget> updatedWidgets = new Vector<Widget>(); 
    529534 
    530535        for (int i = 0; i < changes.size(); i++) { 
     
    543548                if (paintable != null) { 
    544549                    Widget widget = (Widget) paintable; 
    545                     int w = widget.getOffsetWidth(); 
    546                     int h = widget.getOffsetHeight(); 
    547550 
    548551                    paintable.updateFromUIDL(uidl, this); 
    549552 
    550                     if (w != widget.getOffsetWidth() 
    551                             || h != widget.getOffsetHeight()) { 
    552                         sizeUpdatedWidgets.add((Widget) paintable); 
    553                     } 
     553                    updatedWidgets.add(widget); 
    554554                } else { 
    555555                    if (!uidl.getTag().equals("window")) { 
     
    568568        } 
    569569 
     570        // Check which widgets' size has been updated 
     571        Set<Widget> sizeUpdatedWidgets = new HashSet<Widget>(); 
     572 
     573        for (Widget widget : updatedWidgets) { 
     574            Size oldSize = componentOffsetSizes.get(widget); 
     575            Size newSize = new Size(widget.getOffsetWidth(), widget 
     576                    .getOffsetHeight()); 
     577 
     578            if (oldSize == null || !oldSize.equals(newSize)) { 
     579                sizeUpdatedWidgets.add(widget); 
     580                componentOffsetSizes.put(widget, newSize); 
     581            } 
     582 
     583        } 
     584 
    570585        Util.componentSizeUpdated(sizeUpdatedWidgets); 
    571586 
     
    589604 
    590605                if (html.length() != 0) { 
    591                     INotification n = new INotification(1000 * 60 * 45); //45min 
     606                    INotification n = new INotification(1000 * 60 * 45); // 45min 
    592607                    n.addEventListener(new NotificationRedirect(url)); 
    593608                    n.show(html, INotification.CENTERED_TOP, 
     
    638653 
    639654    public void unregisterPaintable(Paintable p) { 
    640         Object id = paintableToId.get(p); 
     655        String id = paintableToId.get(p); 
    641656        idToPaintable.remove(id); 
    642657        paintableToTitle.remove(id); 
     
    667682     */ 
    668683    public Paintable getPaintable(String id) { 
    669         return (Paintable) idToPaintable.get(id); 
     684        return idToPaintable.get(id); 
    670685    } 
    671686 
     
    858873        // Switch to correct implementation if needed 
    859874        if (!widgetSet.isCorrectImplementation(component, uidl)) { 
    860             final Container parent = Util.getParentLayout(component); 
     875            final Container parent = Util.getLayout(component); 
    861876            if (parent != null) { 
    862877                final Widget w = (Widget) widgetSet.createWidget(uidl); 
     
    867882            } 
    868883        } 
    869  
    870         updateComponentSize(component, uidl); 
    871884 
    872885        boolean enabled = !uidl.getBooleanAttribute("disabled"); 
     
    941954        // Set captions 
    942955        if (manageCaption) { 
    943             final Container parent = Util.getParentLayout(component); 
     956            final Container parent = Util.getLayout(component); 
    944957            if (parent != null) { 
    945958                parent.updateCaption((Paintable) component, uidl); 
     
    950963            DOM.setElementProperty(component.getElement(), "id", uidl.getId()); 
    951964        } 
     965 
     966        /* 
     967         * updateComponentSize need to be after caption update so caption can be 
     968         * taken into account 
     969         */ 
     970 
     971        updateComponentSize(component, uidl); 
    952972 
    953973        return false; 
     
    957977        String w = uidl.hasAttribute("width") ? uidl 
    958978                .getStringAttribute("width") : ""; 
    959         component.setWidth(w); 
     979 
    960980        String h = uidl.hasAttribute("height") ? uidl 
    961981                .getStringAttribute("height") : ""; 
    962         component.setHeight(h); 
     982 
     983        float relativeWidth = Util.parseRelativeSize(w); 
     984        float relativeHeight = Util.parseRelativeSize(h); 
     985 
     986        if (relativeHeight >= 0.0 || relativeWidth >= 0.0) { 
     987            // One or both is relative 
     988            FloatSize relativeSize = new FloatSize(relativeWidth, 
     989                    relativeHeight); 
     990            componentRelativeSizes.put(component, relativeSize); 
     991            handleComponentRelativeSize(component); 
     992        } else if (relativeHeight < 0.0 && relativeWidth < 0.0) { 
     993            // No relative sizes 
     994            componentRelativeSizes.remove(component); 
     995        } 
     996 
     997        if (relativeHeight < 0.0) { 
     998            component.setHeight(h); 
     999        } 
     1000        if (relativeWidth < 0.0) { 
     1001            component.setWidth(w); 
     1002        } 
     1003    } 
     1004 
     1005    /** 
     1006     * Traverses recursively ancestors until ContainerResizedListener child 
     1007     * widget is found. They will delegate it further if needed. 
     1008     *  
     1009     * @param container 
     1010     */ 
     1011    public void runDescendentsLayout(HasWidgets container) { 
     1012//        getConsole().log( 
     1013//                "runDescendentsLayout(" 
     1014//                        + container.getClass().getName().replaceAll( 
     1015//                                "[^\\.]*\\.", "") + "/" + container.hashCode() 
     1016//                        + ")"); 
     1017        final Iterator childWidgets = container.iterator(); 
     1018        while (childWidgets.hasNext()) { 
     1019            final Widget child = (Widget) childWidgets.next(); 
     1020 
     1021            if (child instanceof Paintable) { 
     1022                handleComponentRelativeSize(child); 
     1023            } 
     1024 
     1025            if (child instanceof ContainerResizedListener) { 
     1026                ((ContainerResizedListener) child).iLayout(); 
     1027            } else if (child instanceof HasWidgets) { 
     1028                final HasWidgets childContainer = (HasWidgets) child; 
     1029                runDescendentsLayout(childContainer); 
     1030            } 
     1031 
     1032        } 
     1033    } 
     1034 
     1035    public void handleComponentRelativeSize(Widget child) { 
     1036        Widget widget = child; 
     1037        FloatSize relativeSize = componentRelativeSizes.get(widget); 
     1038        if (relativeSize == null) { 
     1039            return; 
     1040        } 
     1041 
     1042        Size availPixels = Util.getLayout(widget).getAllocatedSpace(widget); 
     1043        if (relativeSize.getWidth() >= 0) { 
     1044 
     1045            if (availPixels != null) { 
     1046 
     1047                int width = availPixels.getWidth(); 
     1048                width *= relativeSize.getWidth() / 100.0; 
     1049 
     1050                if (width >= 0) { 
     1051//                    getConsole().log( 
     1052//                            "Widget " + widget.getClass().getName() + "/" 
     1053//                                    + widget.hashCode() + " relative width " 
     1054//                                    + relativeSize.getWidth() + "%: " + width 
     1055//                                    + "px"); 
     1056                    widget.setWidth(width + "px"); 
     1057                } 
     1058            } else { 
     1059                widget.setWidth(relativeSize.getWidth() + "%"); 
     1060                ApplicationConnection.getConsole().error( 
     1061                        Util.getLayout(widget).getClass().getName() 
     1062                                + " did not produce allocatedSpace for " 
     1063                                + widget.getClass().getName()); 
     1064            } 
     1065        } 
     1066        if (relativeSize.getHeight() >= 0) { 
     1067            if (availPixels != null) { 
     1068 
     1069                int height = availPixels.getHeight(); 
     1070                height *= relativeSize.getHeight() / 100.0; 
     1071 
     1072                if (height >= 0) { 
     1073//                    getConsole().log( 
     1074//                            "Widget " + widget.getClass().getName() + "/" 
     1075//                                    + widget.hashCode() + " relative height " 
     1076//                                    + relativeSize.getHeight() + "%: " + height 
     1077//                                    + "px"); 
     1078                    widget.setHeight(height + "px"); 
     1079                } 
     1080            } else { 
     1081                widget.setHeight(relativeSize.getHeight() + "%"); 
     1082                ApplicationConnection.getConsole().error( 
     1083                        Util.getLayout(widget).getClass().getName() 
     1084                                + " did not produce allocatedSpace for " 
     1085                                + widget.getClass().getName()); 
     1086            } 
     1087        } 
     1088 
    9631089    } 
    9641090 
     
    10631189     */ 
    10641190    public TooltipInfo getTitleInfo(Paintable titleOwner) { 
    1065         TooltipInfo info = (TooltipInfo) paintableToTitle.get(titleOwner); 
     1191        TooltipInfo info = paintableToTitle.get(titleOwner); 
    10661192        if (info == null) { 
    10671193            info = new TooltipInfo(); 
     
    11201246            getConsole().log( 
    11211247                    "Running re-layout of " + view.getClass().getName()); 
    1122             Util.runDescendentsLayout(view); 
     1248            runDescendentsLayout(view); 
    11231249            isPending = false; 
    11241250        } 
  • trunk/src/com/itmill/toolkit/terminal/gwt/client/Container.java

    r5453 r5570  
    55package com.itmill.toolkit.terminal.gwt.client; 
    66 
     7import java.util.Set; 
     8 
    79import com.google.gwt.user.client.ui.Widget; 
     10import com.itmill.toolkit.terminal.gwt.client.RenderInformation.Size; 
    811 
    912public interface Container extends Paintable { 
     
    5457     * phase. 
    5558     *  
     59     * @param child 
     60     *            Set of child widgets whose size have changed 
    5661     * @return true if the size of the Container remains the same, false if the 
    5762     *         event need to be propagated to the Containers parent 
    5863     */ 
    59     boolean childComponentSizesUpdated(); 
     64    boolean requestLayout(Set<Paintable> child); 
     65 
     66    /** 
     67     * Returns the size currently allocated for the child component. 
     68     *  
     69     * @param child 
     70     * @return 
     71     */ 
     72    Size getAllocatedSpace(Widget child); 
     73 
    6074} 
  • trunk/src/com/itmill/toolkit/terminal/gwt/client/ContainerResizedListener.java

    r5453 r5570  
    1717     * from Util class may be a good helper for this. 
    1818     *  
    19      * The width and height parameters specifies the space available for the 
    20      * component (in pixels) if the parent container can or want to produce 
    21      * these numbers. If the parent container does not know (has not calculated) 
    22      * or cannot produce (undefined dimensions) one of these numbers -1 is 
    23      * passed. 
    24      *  
    25      * Note that these numbers should not be considered the maximum size for the 
    26      * widget if the layout has undefined dimension. In that case the currently 
    27      * allocated space is passed (eg. OrderedLayout with undefined width might 
    28      * pass availableWidth 100 if the widest component in the layout is 100 but 
    29      * it will still stretch if another 200 pixel wide component is rendered) 
    3019     */ 
    31     public void iLayout(int availableWidth, int availableHeight); 
     20    public void iLayout(); 
    3221} 
  • trunk/src/com/itmill/toolkit/terminal/gwt/client/ICaption.java

    r5405 r5570  
    99import com.google.gwt.user.client.Event; 
    1010import com.google.gwt.user.client.ui.HTML; 
     11import com.itmill.toolkit.terminal.gwt.client.RenderInformation.Size; 
    1112import com.itmill.toolkit.terminal.gwt.client.ui.Icon; 
    1213 
     
    2829 
    2930    private boolean placedAfterComponent = false; 
     31 
     32    private Size requiredSpace = new Size(0, 0); 
    3033 
    3134    /** 
     
    139142        } 
    140143 
     144        requiredSpace.setWidth(getOffsetWidth()); 
     145        requiredSpace.setHeight(getOffsetHeight()); 
    141146    } 
    142147 
     
    178183        return placedAfterComponent; 
    179184    } 
     185 
     186    public Size getRequiredSpace() { 
     187        return requiredSpace; 
     188    } 
     189 
     190    public int getWidth() { 
     191        int width = 0; 
     192        if (icon != null) { 
     193            width += icon.getOffsetWidth(); 
     194        } 
     195        if (captionText != null) { 
     196            width += captionText.getOffsetWidth(); 
     197        } 
     198        if (requiredFieldIndicator != null) { 
     199            width += requiredFieldIndicator.getOffsetWidth(); 
     200        } 
     201        if (errorIndicatorElement != null) { 
     202            width += errorIndicatorElement.getOffsetWidth(); 
     203        } 
     204 
     205        if (BrowserInfo.get().isIE6() && shouldBePlacedAfterComponent()) { 
     206            // FIXME: Should find out what the real issue is 
     207            // Workaround for IE6 weirdness 
     208            width += 3; 
     209        } 
     210 
     211        return width; 
     212 
     213    } 
     214 
     215    public int getHeight() { 
     216        return getOffsetHeight(); 
     217    } 
     218 
     219    public void setAlignment(String alignment) { 
     220        DOM.setStyleAttribute(getElement(), "textAlign", alignment); 
     221 
     222    } 
    180223} 
  • trunk/src/com/itmill/toolkit/terminal/gwt/client/Util.java

    r5468 r5570  
    55package com.itmill.toolkit.terminal.gwt.client; 
    66 
     7import java.util.HashMap; 
    78import java.util.HashSet; 
    8 import java.util.Iterator; 
     9import java.util.Map; 
    910import java.util.Set; 
    1011 
    1112import com.google.gwt.user.client.DOM; 
    1213import com.google.gwt.user.client.Element; 
    13 import com.google.gwt.user.client.ui.HasWidgets; 
    1414import com.google.gwt.user.client.ui.Widget; 
    1515 
     
    5151        } 
    5252 
    53         Set<Container> parents = new HashSet<Container>(); 
     53        Map<Container, Set<Paintable>> childWidgets = new HashMap<Container, Set<Paintable>>(); 
    5454 
    5555        for (Widget widget : widgets) { 
     
    5959            } 
    6060            if (parent != null) { 
    61                 parents.add((Container) parent); 
     61                Set<Paintable> set = childWidgets.get(parent); 
     62                if (set == null) { 
     63                    set = new HashSet<Paintable>(); 
     64                    childWidgets.put((Container) parent, set); 
     65                } 
     66                set.add((Paintable) widget); 
    6267            } 
    6368        } 
    6469 
    6570        Set<Widget> parentChanges = new HashSet<Widget>(); 
    66         for (Container parent : parents) { 
    67             if (!parent.childComponentSizesUpdated()) { 
     71        for (Container parent : childWidgets.keySet()) { 
     72            if (!parent.requestLayout(childWidgets.get(parent))) { 
    6873                parentChanges.add((Widget) parent); 
    6974            } 
     
    7378    } 
    7479 
    75     /** 
    76      * Traverses recursively ancestors until ContainerResizedListener child 
    77      * widget is found. They will delegate it futher if needed. 
    78      *  
    79      * @param container 
    80      */ 
    81     public static void runDescendentsLayout(HasWidgets container) { 
    82         final Iterator childWidgets = container.iterator(); 
    83         while (childWidgets.hasNext()) { 
    84             final Widget child = (Widget) childWidgets.next(); 
    85             if (child instanceof ContainerResizedListener) { 
    86                 int w = -1, h = -1; 
    87  
    88                 if (container instanceof WidgetSpaceAllocator) { 
    89                     w = ((WidgetSpaceAllocator) container) 
    90                             .getAllocatedWidth(child); 
    91                     h = ((WidgetSpaceAllocator) container) 
    92                             .getAllocatedHeight(child); 
    93                 } 
    94  
    95                 ((ContainerResizedListener) child).iLayout(w, h); 
    96             } else if (child instanceof HasWidgets) { 
    97                 final HasWidgets childContainer = (HasWidgets) child; 
    98                 runDescendentsLayout(childContainer); 
    99             } 
    100         } 
    101     } 
    102  
    103     public interface WidgetSpaceAllocator { 
    104         int getAllocatedWidth(Widget child); 
    105  
    106         int getAllocatedHeight(Widget child); 
     80    public static float parseRelativeSize(String size) { 
     81        if (size == null || !size.endsWith("%")) { 
     82            return -1; 
     83        } 
     84 
     85        try { 
     86            return Float.parseFloat(size.substring(0, size.length() - 1)); 
     87        } catch (Exception e) { 
     88            ClientExceptionHandler.displayError( 
     89                    "Unable to parse relative size", e); 
     90        } 
     91 
     92        return -1; 
    10793    } 
    10894 
     
    114100     * @return closest parent Container 
    115101     */ 
    116     public static Container getParentLayout(Widget component) { 
     102    public static Container getLayout(Widget component) { 
    117103        Widget parent = component.getParent(); 
    118104        while (parent != null && !(parent instanceof Container)) { 
    119105            parent = parent.getParent(); 
    120106        } 
    121         if (parent != null && ((Container) parent).hasChildComponent(component)) { 
     107        if (parent != null) { 
     108            assert ((Container) parent).hasChildComponent(component); 
     109 
    122110            return (Container) parent; 
    123111        } 
  • trunk/src/com/itmill/toolkit/terminal/gwt/client/ui/IAccordion.java

    r5498 r5570  
    2020import com.itmill.toolkit.terminal.gwt.client.Paintable; 
    2121import com.itmill.toolkit.terminal.gwt.client.UIDL; 
    22 import com.itmill.toolkit.terminal.gwt.client.Util; 
     22import com.itmill.toolkit.terminal.gwt.client.RenderInformation.Size; 
    2323 
    2424public class IAccordion extends ITabsheetBase implements 
     
    129129    } 
    130130 
    131     private void iLayout() { 
    132         iLayout(-1, -1); 
    133     }