diff options
Diffstat (limited to 'src/com/vaadin')
23 files changed, 440 insertions, 103 deletions
diff --git a/src/com/vaadin/data/util/FilesystemContainer.java b/src/com/vaadin/data/util/FilesystemContainer.java index adcfcfe3a7..1c9671d52d 100644 --- a/src/com/vaadin/data/util/FilesystemContainer.java +++ b/src/com/vaadin/data/util/FilesystemContainer.java @@ -32,10 +32,6 @@ import com.vaadin.terminal.Resource; * @VERSION@ * @since 3.0 */ -/** - * @author mattitahvonen - * - */ @SuppressWarnings("serial") public class FilesystemContainer implements Container.Hierarchical { @@ -404,10 +400,9 @@ public class FilesystemContainer implements Container.Hierarchical { for (final Iterator<File> i = ll.iterator(); i.hasNext();) { final File lf = i.next(); + col.add(lf); if (lf.isDirectory()) { addItemIds(col, lf); - } else { - col.add(lf); } } } diff --git a/src/com/vaadin/data/util/IndexedContainer.java b/src/com/vaadin/data/util/IndexedContainer.java index b246a50a6b..f5dddf5e23 100644 --- a/src/com/vaadin/data/util/IndexedContainer.java +++ b/src/com/vaadin/data/util/IndexedContainer.java @@ -362,6 +362,9 @@ public class IndexedContainer implements Container.Indexed, * @see com.vaadin.data.Container#removeItem(java.lang.Object) */ public boolean removeItem(Object itemId) { + if (itemId == null) { + return false; + } if (items.remove(itemId) == null) { return false; diff --git a/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java b/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java index 8060edfe74..a523e8b00e 100755 --- a/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java +++ b/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java @@ -693,10 +693,9 @@ public class ApplicationConnection { return; } - ApplicationConnection.getConsole() - .log( - "JSON parsing took " - + (new Date().getTime() - start.getTime())); + ApplicationConnection.getConsole().log( + "JSON parsing took " + (new Date().getTime() - start.getTime()) + + "ms"); // Handle redirect if (json.containsKey("redirect")) { String url = json.getValueMap("redirect").getString("url"); @@ -1474,6 +1473,11 @@ public class ApplicationConnection { } } + if (configuration.useDebugIdInDOM() && uidl.getId().startsWith("PID_S")) { + DOM.setElementProperty(component.getElement(), "id", uidl.getId() + .substring(5)); + } + if (!visible) { // component is invisible, delete old size to notify parent, if // later make visible @@ -1575,12 +1579,6 @@ public class ApplicationConnection { parent.updateCaption((Paintable) component, uidl); } } - - if (configuration.useDebugIdInDOM() && uidl.getId().startsWith("PID_S")) { - DOM.setElementProperty(component.getElement(), "id", uidl.getId() - .substring(5)); - } - /* * updateComponentSize need to be after caption update so caption can be * taken into account diff --git a/src/com/vaadin/terminal/gwt/client/Util.java b/src/com/vaadin/terminal/gwt/client/Util.java index a46f9fa7d7..ca0165974a 100644 --- a/src/com/vaadin/terminal/gwt/client/Util.java +++ b/src/com/vaadin/terminal/gwt/client/Util.java @@ -548,18 +548,29 @@ public class Util { if ("hidden".equals(originalOverflow)) { return; } + + // check the scrolltop value before hiding the element + final int scrolltop = elem.getScrollTop(); elem.getStyle().setProperty("overflow", "hidden"); DeferredCommand.addCommand(new Command() { public void execute() { // Dough, Safari scroll auto means actually just a moped elem.getStyle().setProperty("overflow", originalOverflow); - if (elem.getScrollTop() > 0) { + + if (scrolltop > 0 || elem.getScrollTop() > 0) { + int scrollvalue = scrolltop; + if (scrolltop == 0) { + // mysterious are the ways of webkits scrollbar + // handling. In some cases webkit reports bad (0) + // scrolltop before hiding the elment temporary, + // sometimes after. + scrollvalue = elem.getScrollTop(); + } // fix another bug where scrollbar remains in wrong // position - int scrolltop = elem.getScrollTop(); - elem.setScrollTop(scrolltop - 1); - elem.setScrollTop(scrolltop); + elem.setScrollTop(scrollvalue - 1); + elem.setScrollTop(scrollvalue); } } }); diff --git a/src/com/vaadin/terminal/gwt/client/VTooltip.java b/src/com/vaadin/terminal/gwt/client/VTooltip.java index b42b4f3bf3..f9a3c70c61 100644 --- a/src/com/vaadin/terminal/gwt/client/VTooltip.java +++ b/src/com/vaadin/terminal/gwt/client/VTooltip.java @@ -91,6 +91,11 @@ public class VTooltip extends VOverlay { if (y + offsetHeight + MARGIN - Window.getScrollTop() > Window .getClientHeight()) { y = tooltipEventMouseY - 5 - offsetHeight; + if (y - Window.getScrollTop() < 0) { + // tooltip does not fit on top of the mouse either, + // put it at the top of the screen + y = Window.getScrollTop(); + } } setPopupPosition(x, y); diff --git a/src/com/vaadin/terminal/gwt/client/ui/VButton.java b/src/com/vaadin/terminal/gwt/client/ui/VButton.java index de1d720618..36d9f5ec1e 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VButton.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VButton.java @@ -394,6 +394,10 @@ public class VButton extends FocusWidget implements Paintable, ClickHandler { int w = Integer .parseInt(width.substring(0, width.length() - 2)); w -= getHorizontalBorderAndPaddingWidth(getElement()); + if (w < 0) { + // validity check for IE + w = 0; + } width = w + "px"; } } diff --git a/src/com/vaadin/terminal/gwt/client/ui/VCheckBox.java b/src/com/vaadin/terminal/gwt/client/ui/VCheckBox.java index 3bd6f656f2..389c2210d3 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VCheckBox.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VCheckBox.java @@ -4,12 +4,17 @@ package com.vaadin.terminal.gwt.client.ui; +import com.google.gwt.dom.client.InputElement; +import com.google.gwt.dom.client.LabelElement; +import com.google.gwt.dom.client.Node; +import com.google.gwt.dom.client.NodeList; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Element; import com.google.gwt.user.client.Event; import com.vaadin.terminal.gwt.client.ApplicationConnection; +import com.vaadin.terminal.gwt.client.BrowserInfo; import com.vaadin.terminal.gwt.client.Paintable; import com.vaadin.terminal.gwt.client.UIDL; import com.vaadin.terminal.gwt.client.Util; @@ -102,6 +107,36 @@ public class VCheckBox extends com.google.gwt.user.client.ui.CheckBox implements } @Override + public void setText(String text) { + super.setText(text); + if (BrowserInfo.get().isIE() && BrowserInfo.get().getIEVersion() < 8) { + + boolean breakLink = text == null || "".equals(text); + + // break or create link between label element and checkbox, to + // enable native focus outline around checkbox element itself, if + // caption is not present + NodeList<Node> childNodes = getElement().getChildNodes(); + String id = null; + for (int i = 0; i < childNodes.getLength(); i++) { + Node item = childNodes.getItem(i); + if (item.getNodeName().toLowerCase().equals("input")) { + InputElement input = (InputElement) item; + id = input.getId(); + } + if (item.getNodeName().toLowerCase().equals("label")) { + LabelElement label = (LabelElement) item; + if (breakLink) { + label.setHtmlFor(""); + } else { + label.setHtmlFor(id); + } + } + } + } + } + + @Override public void onBrowserEvent(Event event) { if (icon != null && (event.getTypeInt() == Event.ONCLICK) && (DOM.eventGetTarget(event) == icon.getElement())) { diff --git a/src/com/vaadin/terminal/gwt/client/ui/VMenuBar.java b/src/com/vaadin/terminal/gwt/client/ui/VMenuBar.java index 43ba72dc82..9cad1fbd91 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VMenuBar.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VMenuBar.java @@ -86,9 +86,12 @@ public class VMenuBar extends Widget implements Paintable, @Override public void setWidth(String width) { Util.setWidthExcludingPaddingAndBorder(this, width, 0); - hideChildren(); - setSelected(null); - menuVisible = false; + if (!subMenu) { + // Only needed for root level menu + hideChildren(); + setSelected(null); + menuVisible = false; + } } /** @@ -657,7 +660,8 @@ public class VMenuBar extends Widget implements Paintable, protected boolean isSeparator = false; public CustomMenuItem(String html, Command cmd) { - setElement(DOM.createDiv()); + // We need spans to allow inline-block in IE + setElement(DOM.createSpan()); setHTML(html); setCommand(cmd); diff --git a/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java b/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java index 61e35a28bf..3c5ef55a6d 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java @@ -194,6 +194,9 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler { : CACHE_RATE_DEFAULT); recalcWidths = uidl.hasAttribute("recalcWidths"); + if (recalcWidths) { + tHead.clear(); + } if (uidl.hasAttribute("pagelength")) { pageLength = uidl.getIntAttribute("pagelength"); @@ -206,8 +209,8 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler { if (firstvisible != lastRequestedFirstvisible && scrollBody != null) { // received 'surprising' firstvisible from server: scroll there firstRowInViewPort = firstvisible; - bodyContainer.setScrollPosition(firstvisible - * scrollBody.getRowHeight()); + bodyContainer.setScrollPosition((int) (firstvisible * scrollBody + .getRowHeight())); } showRowHeaders = uidl.getBooleanAttribute("rowheaders"); @@ -292,7 +295,9 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler { .getIntAttribute("firstrow"), uidl.getIntAttribute("rows")); bodyContainer.add(scrollBody); initialContentReceived = true; + ApplicationConnection.getConsole().log("foo"); if (isAttached()) { + ApplicationConnection.getConsole().log("bar"); sizeInit(); } scrollBody.restoreRowVisibility(); @@ -709,6 +714,8 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler { * We must force an update of the row height as this point as it * might have been (incorrectly) calculated earlier */ + + int bodyHeight; if (pageLength == totalRows) { /* * A hack to support variable height rows when paging is off. @@ -717,13 +724,17 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler { * height. */ // int bodyHeight = scrollBody.getOffsetHeight(); - int bodyHeight = scrollBody.getRequiredHeight(); - bodyContainer.setHeight(bodyHeight + "px"); - Util.runWebkitOverflowAutoFix(bodyContainer.getElement()); + bodyHeight = scrollBody.getRequiredHeight(); } else { - int bodyHeight = (scrollBody.getRowHeight(true) * pageLength); - bodyContainer.setHeight(bodyHeight + "px"); + bodyHeight = (int) Math.round(scrollBody.getRowHeight(true) + * pageLength); } + boolean needsSpaceForHorizontalSrollbar = (total > availW); + if (needsSpaceForHorizontalSrollbar) { + bodyHeight += Util.getNativeScrollbarSize(); + } + bodyContainer.setHeight(bodyHeight + "px"); + Util.runWebkitOverflowAutoFix(bodyContainer.getElement()); } isNewBody = false; @@ -733,8 +744,9 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler { // without DeferredCommand.addCommand(new Command() { public void execute() { - bodyContainer.setScrollPosition(firstvisible - * scrollBody.getRowHeight()); + bodyContainer + .setScrollPosition((int) (firstvisible * scrollBody + .getRowHeight())); firstRowInViewPort = firstvisible; } }); @@ -753,7 +765,8 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler { if (lastInNewSet > totalRows - 1) { lastInNewSet = totalRows - 1; } - rowRequestHandler.setReqRows(lastInNewSet - firstInNewSet); + rowRequestHandler.setReqRows(lastInNewSet - firstInNewSet + + 1); rowRequestHandler.deferRowFetch(1); } } @@ -772,7 +785,8 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler { return true; } } else { - int fakeheight = scrollBody.getRowHeight() * totalRows; + int fakeheight = (int) Math.round(scrollBody.getRowHeight() + * totalRows); int availableHeight = bodyContainer.getElement().getPropertyInt( "clientHeight"); if (fakeheight > availableHeight) { @@ -1757,7 +1771,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler { public static final int DEFAULT_ROW_HEIGHT = 24; - private int rowHeight = -1; + private double rowHeight = -1; private final List<Widget> renderedRows = new ArrayList<Widget>(); @@ -1886,11 +1900,13 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler { reactLastRow = totalRows - 1; } if (lastRendered < reactLastRow) { + ApplicationConnection.getConsole().log("GET BELOW"); // get some cache rows below visible area rowRequestHandler.setReqFirstRow(lastRendered + 1); - rowRequestHandler.setReqRows(reactLastRow - lastRendered - 1); + rowRequestHandler.setReqRows(reactLastRow - lastRendered); rowRequestHandler.deferRowFetch(1); } else if (scrollBody.getFirstRendered() > reactFirstRow) { + ApplicationConnection.getConsole().log("GET ABOVE"); /* * Branch for fetching cache above visible area. * @@ -2023,23 +2039,23 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler { } private void fixSpacers() { - int prepx = getRowHeight() * firstRendered; + int prepx = (int) Math.round(getRowHeight() * firstRendered); if (prepx < 0) { prepx = 0; } - DOM.setStyleAttribute(preSpacer, "height", prepx + "px"); - int postpx = getRowHeight() * (totalRows - 1 - lastRendered); + preSpacer.getStyle().setPropertyPx("height", prepx); + int postpx = (int) (getRowHeight() * (totalRows - 1 - lastRendered)); if (postpx < 0) { postpx = 0; } - DOM.setStyleAttribute(postSpacer, "height", postpx + "px"); + postSpacer.getStyle().setPropertyPx("height", postpx); } - public int getRowHeight() { + public double getRowHeight() { return getRowHeight(false); } - public int getRowHeight(boolean forceUpdate) { + public double getRowHeight(boolean forceUpdate) { if (tBodyMeasurementsDone && !forceUpdate) { return rowHeight; } else { @@ -2047,7 +2063,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler { if (tBodyElement.getRows().getLength() > 0) { int tableHeight = getTableHeight(); int rowCount = tBodyElement.getRows().getLength(); - rowHeight = tableHeight / rowCount; + rowHeight = tableHeight / (double) rowCount; } else { if (isAttached()) { // measure row height by adding a dummy row @@ -2602,7 +2618,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler { return new RenderSpace(w, 0) { @Override public int getHeight() { - return getRowHeight(); + return (int) getRowHeight(); } }; } @@ -2679,7 +2695,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler { return; } - int rowHeight = scrollBody.getRowHeight(); + int rowHeight = (int) scrollBody.getRowHeight(); int bodyH = bodyContainer.getOffsetHeight(); int rowsAtOnce = bodyH / rowHeight; boolean anotherPartlyVisible = ((bodyH % rowHeight) != 0); @@ -2696,10 +2712,8 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler { if (currentlyVisible < pageLength && currentlyVisible < totalRows) { // shake scrollpanel to fill empty space - bodyContainer.setScrollPosition(bodyContainer - .getScrollPosition() + 1); - bodyContainer.setScrollPosition(bodyContainer - .getScrollPosition() - 1); + bodyContainer.setScrollPosition(scrollTop + 1); + bodyContainer.setScrollPosition(scrollTop - 1); } } } @@ -2804,6 +2818,21 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler { } colIndex++; } + if ((height == null || "".equals(height)) + && totalRows == pageLength) { + // fix body height (may vary if lazy loading is offhorizontal + // scrollbar appears/disappears) + int bodyHeight = scrollBody.getRequiredHeight(); + boolean needsSpaceForHorizontalSrollbar = (availW < usedMinimumWidth); + if (needsSpaceForHorizontalSrollbar) { + bodyHeight += Util.getNativeScrollbarSize(); + } + int heightBefore = getOffsetHeight(); + bodyContainer.setHeight(bodyHeight + "px"); + if (heightBefore != getOffsetHeight()) { + Util.notifyParentOfSizeChange(VScrollTable.this, false); + } + } scrollBody.reLayoutComponents(); DeferredCommand.addCommand(new Command() { public void execute() { @@ -2855,6 +2884,8 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler { } private int contentAreaBorderHeight = -1; + private int scrollLeft; + private int scrollTop; /** * @return border top + border bottom of the scrollable area of table @@ -2886,6 +2917,12 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler { if (initializedAndAttached) { updatePageLength(); } + if (!rendering) { + // Webkit may sometimes get an odd rendering bug (white space + // between header and body), see bug #3875. Running + // overflow hack here to shake body element a bit. + Util.runWebkitOverflowAutoFix(bodyContainer.getElement()); + } } /* @@ -2901,8 +2938,9 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler { if (visible) { DeferredCommand.addCommand(new Command() { public void execute() { - bodyContainer.setScrollPosition(firstRowInViewPort - * scrollBody.getRowHeight()); + bodyContainer + .setScrollPosition((int) (firstRowInViewPort * scrollBody + .getRowHeight())); } }); } @@ -2933,24 +2971,38 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler { * user scrolls */ public void onScroll(ScrollEvent event) { - int scrollLeft = bodyContainer.getElement().getScrollLeft(); - int scrollTop = bodyContainer.getScrollPosition(); + scrollLeft = bodyContainer.getElement().getScrollLeft(); + scrollTop = bodyContainer.getScrollPosition(); if (!initializedAndAttached) { return; } if (!enabled) { - bodyContainer.setScrollPosition(firstRowInViewPort - * scrollBody.getRowHeight()); + bodyContainer + .setScrollPosition((int) (firstRowInViewPort * scrollBody + .getRowHeight())); return; } rowRequestHandler.cancel(); + if (BrowserInfo.get().isSafari() && event != null && scrollTop == 0) { + // due to the webkitoverflowworkaround, top may sometimes report 0 + // for webkit, although it really is not. Expecting to have the + // correct + // value available soon. + DeferredCommand.addCommand(new Command() { + public void execute() { + onScroll(null); + } + }); + return; + } + // fix headers horizontal scrolling tHead.setHorizontalScrollPosition(scrollLeft); firstRowInViewPort = (int) Math.ceil(scrollTop - / (double) scrollBody.getRowHeight()); + / scrollBody.getRowHeight()); if (firstRowInViewPort > totalRows - pageLength) { firstRowInViewPort = totalRows - pageLength; } diff --git a/src/com/vaadin/terminal/gwt/client/ui/VSlider.java b/src/com/vaadin/terminal/gwt/client/ui/VSlider.java index 1ca8b814a5..732ba84a3f 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VSlider.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VSlider.java @@ -10,6 +10,7 @@ import com.google.gwt.user.client.DeferredCommand; import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.Timer;
+import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Widget;
import com.vaadin.terminal.gwt.client.ApplicationConnection;
import com.vaadin.terminal.gwt.client.BrowserInfo;
@@ -43,9 +44,18 @@ public class VSlider extends Widget implements Paintable, Field, private int resolution;
private Double value;
private boolean vertical;
- private int size = -1;
+ private final int size = -1;
private boolean arrows;
+ private final HTML feedback = new HTML("", false);
+ private final VOverlay feedbackPopup = new VOverlay(true, false, true) {
+ @Override
+ public void show() {
+ super.show();
+ updateFeedbackPosition();
+ }
+ };
+
/* DOM element for slider's base */
private final Element base;
private final int BASE_BORDER_WIDTH = 1;
@@ -94,6 +104,9 @@ public class VSlider extends Widget implements Paintable, Field, | Event.ONMOUSEOUT);
DOM.sinkEvents(bigger, Event.ONMOUSEDOWN | Event.ONMOUSEUP
| Event.ONMOUSEOUT);
+
+ feedbackPopup.addStyleName(CLASSNAME + "-feedback");
+ feedbackPopup.setWidget(feedback);
}
public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
@@ -136,6 +149,8 @@ public class VSlider extends Widget implements Paintable, Field, resolution = uidl.getIntAttribute("resolution");
value = new Double(uidl.getDoubleVariable("value"));
+ setFeedbackValue(value);
+
handleSize = uidl.getIntAttribute("hsize");
buildBase();
@@ -154,6 +169,29 @@ public class VSlider extends Widget implements Paintable, Field, }
}
+ private void setFeedbackValue(double value) {
+ String currentValue = "" + value;
+ if (resolution == 0) {
+ currentValue = "" + new Double(value).intValue();
+ }
+ feedback.setText(currentValue);
+ }
+
+ private void updateFeedbackPosition() {
+ if (vertical) {
+ feedbackPopup.setPopupPosition(DOM.getAbsoluteLeft(handle)
+ + handle.getOffsetWidth(), DOM.getAbsoluteTop(handle)
+ + handle.getOffsetHeight() / 2
+ - feedbackPopup.getOffsetHeight() / 2);
+ } else {
+ feedbackPopup.setPopupPosition(DOM.getAbsoluteLeft(handle)
+ + handle.getOffsetWidth() / 2
+ - feedbackPopup.getOffsetWidth() / 2, DOM
+ .getAbsoluteTop(handle)
+ - feedbackPopup.getOffsetHeight());
+ }
+ }
+
private void buildBase() {
final String styleAttribute = vertical ? "height" : "width";
final String domProperty = vertical ? "offsetHeight" : "offsetWidth";
@@ -244,6 +282,7 @@ public class VSlider extends Widget implements Paintable, Field, final int range = baseSize - handleSize;
double v = value.doubleValue();
+
// Round value to resolution
if (resolution > 0) {
v = Math.round(v * Math.pow(10, resolution));
@@ -268,11 +307,9 @@ public class VSlider extends Widget implements Paintable, Field, DOM.setStyleAttribute(handle, styleAttribute, (Math.round(pos)) + "px");
- // TODO give more detailed info when dragging and do roundup
- DOM.setElementAttribute(handle, "title", "" + v);
-
// Update value
this.value = new Double(v);
+ setFeedbackValue(v);
if (updateToServer) {
updateValueToServer();
@@ -329,7 +366,10 @@ public class VSlider extends Widget implements Paintable, Field, switch (DOM.eventGetType(event)) {
case Event.ONMOUSEDOWN:
if (!disabled && !readonly) {
+ feedbackPopup.show();
dragging = true;
+ DOM.setElementProperty(handle, "className", CLASSNAME
+ + "-handle " + CLASSNAME + "-handle-active");
DOM.setCapture(getElement());
DOM.eventPreventDefault(event); // prevent selecting text
DOM.eventCancelBubble(event, true);
@@ -337,12 +377,14 @@ public class VSlider extends Widget implements Paintable, Field, break;
case Event.ONMOUSEMOVE:
if (dragging) {
- // DOM.setCapture(getElement());
setValueByEvent(event, false);
+ updateFeedbackPosition();
}
break;
case Event.ONMOUSEUP:
+ feedbackPopup.hide();
dragging = false;
+ DOM.setElementProperty(handle, "className", CLASSNAME + "-handle");
DOM.releaseCapture(getElement());
setValueByEvent(event, true);
break;
@@ -381,8 +423,8 @@ public class VSlider extends Widget implements Paintable, Field, .eventGetClientX(event);
final String domProperty = vertical ? "offsetHeight" : "offsetWidth";
- final double handleSize = Integer.parseInt(DOM.getElementProperty(
- handle, domProperty));
+ final int handleSize = Integer.parseInt(DOM.getElementProperty(handle,
+ domProperty));
final double baseSize = Integer.parseInt(DOM.getElementProperty(base,
domProperty));
final double baseOffset = vertical ? DOM.getAbsoluteTop(base)
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VSplitPanel.java b/src/com/vaadin/terminal/gwt/client/ui/VSplitPanel.java index 82839f2f31..ffada53252 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VSplitPanel.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VSplitPanel.java @@ -434,7 +434,6 @@ public class VSplitPanel extends ComplexPanel implements Container, newX = getOffsetWidth() - getSplitterSize(); } DOM.setStyleAttribute(splitter, "left", newX + "px"); - updateSplitPosition(newX); if (origX != newX) { resized = true; } @@ -450,7 +449,6 @@ public class VSplitPanel extends ComplexPanel implements Container, newY = getOffsetHeight() - getSplitterSize(); } DOM.setStyleAttribute(splitter, "top", newY + "px"); - updateSplitPosition(newY); if (origY != newY) { resized = true; } @@ -463,6 +461,7 @@ public class VSplitPanel extends ComplexPanel implements Container, } resizing = false; onMouseMove(event); + updateSplitPositionToServer(); } /** @@ -593,12 +592,14 @@ public class VSplitPanel extends ComplexPanel implements Container, /** * Updates the new split position back to server. - * - * @param pos - * The new position of the split handle. */ - private void updateSplitPosition(int pos) { + private void updateSplitPositionToServer() { // We always send pixel values to server + final String position = orientation == ORIENTATION_HORIZONTAL ? splitter + .getStyle().getProperty("left") + : splitter.getStyle().getProperty("top"); + final int pos = Integer.parseInt(position.substring(0, position + .length() - 2)); client.updateVariable(id, "position", pos, immediate); } diff --git a/src/com/vaadin/terminal/gwt/client/ui/VWindow.java b/src/com/vaadin/terminal/gwt/client/ui/VWindow.java index e8a96c63fb..e1ab149dc5 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VWindow.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VWindow.java @@ -795,8 +795,8 @@ public class VWindow extends VOverlay implements Container, ScrollListener { } } - if (type == Event.ONMOUSEDOWN) { - // !DOM.isOrHasChild(contentPanel.getElement(), target) + if (type == Event.ONMOUSEDOWN + && !DOM.isOrHasChild(contentPanel.getElement(), target)) { Util.focus(contentPanel.getElement()); } } diff --git a/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java b/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java index fd31333930..eda9670ff7 100644 --- a/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java +++ b/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java @@ -28,10 +28,12 @@ import javax.portlet.PortalContext; import javax.portlet.PortletConfig; import javax.portlet.PortletContext; import javax.portlet.PortletException; +import javax.portlet.PortletMode; import javax.portlet.PortletRequest; import javax.portlet.PortletResponse; import javax.portlet.PortletSession; import javax.portlet.PortletURL; +import javax.portlet.RenderMode; import javax.portlet.RenderRequest; import javax.portlet.RenderResponse; import javax.portlet.ResourceRequest; @@ -424,7 +426,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet /* * Always use the main window when running inside a portlet. */ - Window window = application.getMainWindow(); + Window window = getPortletWindow(request, application); if (window == null) { throw new PortletException(ERROR_NO_WINDOW_FOUND); } @@ -492,6 +494,28 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet } } + /** + * Returns a window for a portlet mode. To define custom content for a + * portlet mode, add (in the application) a window whose name matches the + * portlet mode name. By default, the main window is returned. + * + * Alternatively, a PortletListener can change the main window content. + * + * @param request + * @param application + * @return Window to show in the portlet for the given portlet mode + */ + protected Window getPortletWindow(PortletRequest request, + Application application) { + PortletMode mode = request.getPortletMode(); + Window window = application.getWindow(mode.toString()); + if (window != null) { + return window; + } + // no specific window found + return application.getMainWindow(); + } + private void updateBrowserProperties(WebBrowser browser, PortletRequest request) { browser.updateBrowserProperties(request.getLocale(), null, request @@ -624,12 +648,55 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet handleRequest(request, response); } + /** + * Handles a request for the "view" (default) portlet mode. In Vaadin, the + * basic portlet modes ("view", "edit" and "help") are handled identically, + * and their behavior can be changed by registering windows in the + * application with window names identical to the portlet mode names. + * Alternatively, a PortletListener can change the application main window + * contents. + * + * To implement custom portlet modes, subclass the portlet class and + * implement a method annotated with {@link RenderMode} for the custom mode, + * calling {@link #handleRequest(PortletRequest, PortletResponse)} directly + * from it. + * + * Note that the portlet class in the portlet configuration needs to be + * changed when overriding methods of this class. + * + * @param request + * @param response + * @throws PortletException + * @throws IOException + */ @Override protected void doView(RenderRequest request, RenderResponse response) throws PortletException, IOException { handleRequest(request, response); } + /** + * Handle a request for the "edit" portlet mode. + * + * @see #doView(RenderRequest, RenderResponse) + */ + @Override + protected void doEdit(RenderRequest request, RenderResponse response) + throws PortletException, IOException { + handleRequest(request, response); + } + + /** + * Handle a request for the "help" portlet mode. + * + * @see #doView(RenderRequest, RenderResponse) + */ + @Override + protected void doHelp(RenderRequest request, RenderResponse response) + throws PortletException, IOException { + handleRequest(request, response); + } + @Override public void serveResource(ResourceRequest request, ResourceResponse response) throws PortletException, IOException { diff --git a/src/com/vaadin/terminal/gwt/server/JsonPaintTarget.java b/src/com/vaadin/terminal/gwt/server/JsonPaintTarget.java index e0f888e6cb..e745282605 100644 --- a/src/com/vaadin/terminal/gwt/server/JsonPaintTarget.java +++ b/src/com/vaadin/terminal/gwt/server/JsonPaintTarget.java @@ -1009,13 +1009,11 @@ public class JsonPaintTarget implements PaintTarget { * integer strings to optimized transferred data. */ Class<? extends Paintable> class1 = paintable.getClass(); - ClientWidget annotation = class1.getAnnotation(ClientWidget.class); - while (annotation == null) { + while (!hasClientWidgetMapping(class1)) { Class<?> superclass = class1.getSuperclass(); if (superclass != null && Paintable.class.isAssignableFrom(superclass)) { class1 = (Class<? extends Paintable>) superclass; - annotation = class1.getAnnotation(ClientWidget.class); } else { System.out .append("Warning: no superclass of givent has ClientWidget" @@ -1023,11 +1021,30 @@ public class JsonPaintTarget implements PaintTarget { break; } } + usedPaintableTypes.add(class1); return AbstractCommunicationManager.getTagForType(class1); } + private boolean hasClientWidgetMapping(Class<? extends Paintable> class1) { + try { + ClientWidget annotation = class1.getAnnotation(ClientWidget.class); + return annotation != null; + } catch (RuntimeException e) { + if (e.getStackTrace()[0].getClassName().equals( + "org.glassfish.web.loader.WebappClassLoader")) { + // Glassfish 3 is darn eager to load the value class, even + // though we just want to check if the annotation exists. + // See #3920, remove this hack when fixed in glassfish + return true; + } else { + // throw exception forward + throw e; + } + } + } + Collection<Class<? extends Paintable>> getUsedPaintableTypes() { return usedPaintableTypes; } diff --git a/src/com/vaadin/terminal/gwt/server/PortletApplicationContext.java b/src/com/vaadin/terminal/gwt/server/PortletApplicationContext.java index b8d058d88a..af9ed1b9a6 100644 --- a/src/com/vaadin/terminal/gwt/server/PortletApplicationContext.java +++ b/src/com/vaadin/terminal/gwt/server/PortletApplicationContext.java @@ -22,9 +22,8 @@ import com.vaadin.Application; /**
* @author marc
- * @deprecated Use Portlet 2.0 class {@link PortletApplicationContext2} instead.
*/
-@SuppressWarnings({"serial", "unchecked"})
+@SuppressWarnings( { "serial", "unchecked" })
@Deprecated
public class PortletApplicationContext extends WebApplicationContext implements
Serializable {
diff --git a/src/com/vaadin/terminal/gwt/server/PortletApplicationContext2.java b/src/com/vaadin/terminal/gwt/server/PortletApplicationContext2.java index 2471680d29..8effcb6c65 100644 --- a/src/com/vaadin/terminal/gwt/server/PortletApplicationContext2.java +++ b/src/com/vaadin/terminal/gwt/server/PortletApplicationContext2.java @@ -13,6 +13,8 @@ import javax.portlet.ActionResponse; import javax.portlet.EventRequest; import javax.portlet.EventResponse; import javax.portlet.MimeResponse; +import javax.portlet.PortletMode; +import javax.portlet.PortletModeException; import javax.portlet.PortletResponse; import javax.portlet.PortletSession; import javax.portlet.PortletURL; @@ -351,4 +353,31 @@ public class PortletApplicationContext2 extends AbstractWebApplicationContext { "Shared parameters can only be set from a portlet request"); } } + + /** + * Sets the portlet mode. This may trigger a new render request. + * + * Portlet modes used by a portlet need to be declared in portlet.xml . + * + * @param window + * a window in which the render URL can be opened if necessary + * @param portletMode + * the portlet mode to switch to + * @throws PortletModeException + * if the portlet mode is not allowed for some reason + * (configuration, permissions etc.) + */ + public void setPortletMode(Window window, PortletMode portletMode) + throws IllegalStateException, PortletModeException { + if (response instanceof MimeResponse) { + PortletURL url = ((MimeResponse) response).createRenderURL(); + url.setPortletMode(portletMode); + window.open(new ExternalResource(url.toString())); + } else if (response instanceof StateAwareResponse) { + ((StateAwareResponse) response).setPortletMode(portletMode); + } else { + throw new IllegalStateException( + "Portlet mode can only be changed from a portlet request"); + } + } } diff --git a/src/com/vaadin/terminal/gwt/server/PortletCommunicationManager.java b/src/com/vaadin/terminal/gwt/server/PortletCommunicationManager.java index 679468dd0b..092bc4c55e 100644 --- a/src/com/vaadin/terminal/gwt/server/PortletCommunicationManager.java +++ b/src/com/vaadin/terminal/gwt/server/PortletCommunicationManager.java @@ -24,9 +24,9 @@ import com.vaadin.ui.Window; /** * TODO document me! - * + * * @author peholmst - * + * */ @SuppressWarnings("serial") public class PortletCommunicationManager extends AbstractCommunicationManager { @@ -165,6 +165,19 @@ public class PortletCommunicationManager extends AbstractCommunicationManager { + themeName + "/" + resource); } + /** + * Find the application window to use based on the portlet mode. For + * internal use only, not in the {@link Callback} interface. + * + * @param request + * @param application + * @return + */ + public Window getPortletWindow(PortletRequest request, + Application application) { + return portlet.getPortletWindow(request, application); + } + } public PortletCommunicationManager(Application application) { @@ -202,8 +215,9 @@ public class PortletCommunicationManager extends AbstractCommunicationManager { ((ActionResponse) response.getWrappedResponse()) .sendRedirect(dummyURL == null ? "http://www.google.com" : dummyURL); - } else + } else { super.sendUploadResponse(request, response); + } } public void handleUidlRequest(ResourceRequest request, @@ -223,4 +237,18 @@ public class PortletCommunicationManager extends AbstractCommunicationManager { new AbstractApplicationPortletWrapper(applicationPortlet)); } + @Override + protected Window doGetApplicationWindow(Request request, Callback callback, + Application application, Window assumedWindow) { + // find window based on portlet mode + if (assumedWindow == null + && callback instanceof AbstractApplicationPortletWrapper + && request.getWrappedRequest() instanceof PortletRequest) { + assumedWindow = ((AbstractApplicationPortletWrapper) callback) + .getPortletWindow((PortletRequest) request + .getWrappedRequest(), application); + } + return super.doGetApplicationWindow(request, callback, application, + assumedWindow); + } } diff --git a/src/com/vaadin/terminal/gwt/server/PortletRequestListener.java b/src/com/vaadin/terminal/gwt/server/PortletRequestListener.java index 43898faa54..f2a3386b13 100644 --- a/src/com/vaadin/terminal/gwt/server/PortletRequestListener.java +++ b/src/com/vaadin/terminal/gwt/server/PortletRequestListener.java @@ -11,15 +11,15 @@ import com.vaadin.service.ApplicationContext.TransactionListener; import com.vaadin.terminal.Terminal; /** - * {@link Application} that implements this interface gets notified of request - * start and end by terminal. It is quite similar to + * An {@link Application} that implements this interface gets notified of + * request start and end by the terminal. It is quite similar to the * {@link HttpServletRequestListener}, but the parameters are Portlet specific. - * If Application is used deployed as both Servlet and Portlet, one most likely - * needs to implement both. + * If an Application is deployed as both a Servlet and a Portlet, one most + * likely needs to implement both. * <p> * Only JSR 286 style Portlets are supported. * <p> - * Interface can be used for several helper tasks including: + * The interface can be used for several helper tasks including: * <ul> * <li>Opening and closing database connections * <li>Implementing {@link ThreadLocal} @@ -28,7 +28,7 @@ import com.vaadin.terminal.Terminal; * <p> * Alternatives for implementing similar features are are Servlet {@link Filter} * s and {@link TransactionListener}s in Vaadin. - * + * * @since 6.2 * @see HttpServletRequestListener */ @@ -37,7 +37,7 @@ public interface PortletRequestListener extends Serializable { /** * This method is called before {@link Terminal} applies the request to * Application. - * + * * @param requestData * the {@link PortletRequest} about to change Application state */ diff --git a/src/com/vaadin/terminal/gwt/widgetsetutils/WidgetMapGenerator.java b/src/com/vaadin/terminal/gwt/widgetsetutils/WidgetMapGenerator.java index 2727da3ecc..54dc7153dc 100644 --- a/src/com/vaadin/terminal/gwt/widgetsetutils/WidgetMapGenerator.java +++ b/src/com/vaadin/terminal/gwt/widgetsetutils/WidgetMapGenerator.java @@ -120,14 +120,10 @@ public class WidgetMapGenerator extends Generator { if (typeOracle.findType(annotation.value().getName()) == null) { // GWT widget not inherited - logger - .log( - Type.WARN, - "Widget implementation for " - + class1.getName() - + " not available for GWT compiler (but mapped " - + "for component found in classpath). If this is not " - + "intentional, check your gwt module definition file."); + logger.log(Type.WARN, "Widget class " + + annotation.value().getName() + + " was not found. The component " + class1.getName() + + " will not be included in the widgetset."); iterator.remove(); } diff --git a/src/com/vaadin/ui/AbstractComponent.java b/src/com/vaadin/ui/AbstractComponent.java index 92bf90831b..4619c2ab8d 100644 --- a/src/com/vaadin/ui/AbstractComponent.java +++ b/src/com/vaadin/ui/AbstractComponent.java @@ -521,7 +521,8 @@ public abstract class AbstractComponent implements Component, MethodEventSource } if (parent != null && this.parent != null) { - throw new IllegalStateException("Component already has a parent."); + throw new IllegalStateException(getClass().getName() + + " already has a parent."); } // Send detach event if the component have been connected to a window diff --git a/src/com/vaadin/ui/GridLayout.java b/src/com/vaadin/ui/GridLayout.java index f1195e9ef4..19abe8d142 100644 --- a/src/com/vaadin/ui/GridLayout.java +++ b/src/com/vaadin/ui/GridLayout.java @@ -830,8 +830,9 @@ public class GridLayout extends AbstractLayout implements } /** - * An <code>Exception</code> object which is thrown when two Items occupy - * the same space on a grid. + * Gridlayout does not support laying components on top of each other. An + * <code>OverlapsException</code> is thrown when a component already exists + * (even partly) at the same space on a grid with the new component. * * @author IT Mill Ltd. * @version @@ -851,6 +852,32 @@ public class GridLayout extends AbstractLayout implements this.existingArea = existingArea; } + @Override + public String getMessage() { + StringBuilder sb = new StringBuilder(); + Component component = existingArea.getComponent(); + sb.append(component); + sb.append("( type = "); + sb.append(component.getClass().getName()); + if (component.getCaption() != null) { + sb.append(", caption = \""); + sb.append(component.getCaption()); + sb.append("\""); + } + sb.append(")"); + sb.append(" is already added to "); + sb.append(existingArea.column1); + sb.append(","); + sb.append(existingArea.column1); + sb.append(","); + sb.append(existingArea.row1); + sb.append(","); + sb.append(existingArea.row2); + sb.append("(column1, column2, row1, row2)."); + + return sb.toString(); + } + /** * Gets the area . * diff --git a/src/com/vaadin/ui/SplitPanel.java b/src/com/vaadin/ui/SplitPanel.java index 916c8bb5cc..5e67b93369 100644 --- a/src/com/vaadin/ui/SplitPanel.java +++ b/src/com/vaadin/ui/SplitPanel.java @@ -284,7 +284,7 @@ public class SplitPanel extends AbstractLayout { * the new size of the first region in percentage */ public void setSplitPosition(int pos) { - setSplitPosition(pos, UNITS_PERCENTAGE); + setSplitPosition(pos, UNITS_PERCENTAGE, true); } /** @@ -296,9 +296,27 @@ public class SplitPanel extends AbstractLayout { * the unit (from {@link Sizeable}) in which the size is given. */ public void setSplitPosition(int pos, int unit) { + setSplitPosition(pos, unit, true); + } + + /** + * Moves the position of the splitter. + * + * @param pos + * the new size of the first region in percentage + * @param unit + * the unit (from {@link Sizeable}) in which the size is given. + * @param repaintNotNeeded + * true if client side needs to be updated. Use false if the + * position info has come from the client side, thus it already + * knows the position. + */ + private void setSplitPosition(int pos, int unit, boolean repaintNeeded) { this.pos = pos; posUnit = unit; - requestRepaint(); + if (repaintNeeded) { + requestRepaint(); + } } /** @@ -335,8 +353,8 @@ public class SplitPanel extends AbstractLayout { if (variables.containsKey("position") && !isLocked()) { Integer newPos = (Integer) variables.get("position"); - // Client always sends pixel values - setSplitPosition(newPos, UNITS_PIXELS); + // Client always sends pixel values. Repaint is not needed. + setSplitPosition(newPos, UNITS_PIXELS, false); } if (variables.containsKey(SPLITTER_CLICK_EVENT)) { diff --git a/src/com/vaadin/ui/Upload.java b/src/com/vaadin/ui/Upload.java index e3512a4795..7a3fac9167 100644 --- a/src/com/vaadin/ui/Upload.java +++ b/src/com/vaadin/ui/Upload.java @@ -49,6 +49,11 @@ import com.vaadin.terminal.gwt.client.ui.VUpload; * selected, instead of the common pattern of file selection field and upload * button. * + * <p> + * Note! Because of browser dependent implementations of <input type="file"> + * element, setting size for Upload component is not supported. For some + * browsers setting size may work to some extend. + * * @author IT Mill Ltd. * @version * @VERSION@ |