diff --git a/vaadin-spreadsheet-testbench-api/src/main/java/com/vaadin/addon/spreadsheet/elements/ElementUtil.java b/vaadin-spreadsheet-testbench-api/src/main/java/com/vaadin/addon/spreadsheet/elements/ElementUtil.java new file mode 100644 index 000000000..5fd50d25b --- /dev/null +++ b/vaadin-spreadsheet-testbench-api/src/main/java/com/vaadin/addon/spreadsheet/elements/ElementUtil.java @@ -0,0 +1,50 @@ +/** + * Copyright 2019 HealthPivots, all rights reserved + * + * @Created: Apr 10, 2019 + */ +package com.vaadin.addon.spreadsheet.elements; + +import org.openqa.selenium.JavascriptExecutor; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.phantomjs.PhantomJSDriver; + +import com.vaadin.testbench.TestBenchDriverProxy; + +/** + * ElementUtil + */ +public class ElementUtil { + + /** + * Helper to work around lack of PhantomJS direct support for contextClick events. + * May need to wait for the context click to appear after calling. + * + * @param driver + * @param webElement + + * @see com.vaadin.testbench.TestBenchElement#contextClick() + * @see "https://github.com/ariya/phantomjs/issues/14005" + */ + public static void phantomJSContextClick(WebDriver driver, WebElement webElement) { + WebDriver actualDriver = driver; + if (actualDriver instanceof TestBenchDriverProxy) { + actualDriver = ((TestBenchDriverProxy)actualDriver).getActualDriver(); + } + if (actualDriver instanceof PhantomJSDriver) { + String script = + "var element = arguments[0];" + + "var event = document.createEvent('HTMLEvents');" + + "event.initEvent('contextmenu', true, false);" + + "element.dispatchEvent(event);"; + ((JavascriptExecutor)driver) + .executeScript(script, new Object[]{webElement}); + } + } + + private ElementUtil() { + // unused + } + +} diff --git a/vaadin-spreadsheet-testbench-api/src/main/java/com/vaadin/addon/spreadsheet/elements/SheetCellElement.java b/vaadin-spreadsheet-testbench-api/src/main/java/com/vaadin/addon/spreadsheet/elements/SheetCellElement.java index c2f2d45d6..7799ccc43 100644 --- a/vaadin-spreadsheet-testbench-api/src/main/java/com/vaadin/addon/spreadsheet/elements/SheetCellElement.java +++ b/vaadin-spreadsheet-testbench-api/src/main/java/com/vaadin/addon/spreadsheet/elements/SheetCellElement.java @@ -19,10 +19,14 @@ import java.util.List; +import org.openqa.selenium.JavascriptExecutor; import org.openqa.selenium.Keys; +import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; +import org.openqa.selenium.phantomjs.PhantomJSDriver; import com.vaadin.testbench.By; +import com.vaadin.testbench.TestBenchDriverProxy; import com.vaadin.testbench.elementsbase.AbstractElement; /** @@ -147,4 +151,18 @@ public boolean hasCommentIndicator() { return !indicators.isEmpty(); } + /** + * Override to allow cell context menu tests to pass for PhantomJS. + * See the linked issue below for code. PhantomJS doesn't support context + * menu directly with Selenium. + * + * @see com.vaadin.testbench.TestBenchElement#contextClick() + * @see "https://github.com/ariya/phantomjs/issues/14005" + */ + @Override + public void contextClick() { + // for PhantomJS, this won't open the context menu + super.contextClick(); + ElementUtil.phantomJSContextClick(getDriver(), getWrappedElement()); + } } diff --git a/vaadin-spreadsheet-testbench-api/src/main/java/com/vaadin/addon/spreadsheet/elements/SheetHeaderElement.java b/vaadin-spreadsheet-testbench-api/src/main/java/com/vaadin/addon/spreadsheet/elements/SheetHeaderElement.java index af4eaa19e..5a5586079 100644 --- a/vaadin-spreadsheet-testbench-api/src/main/java/com/vaadin/addon/spreadsheet/elements/SheetHeaderElement.java +++ b/vaadin-spreadsheet-testbench-api/src/main/java/com/vaadin/addon/spreadsheet/elements/SheetHeaderElement.java @@ -35,4 +35,20 @@ public TestBenchElement getResizeHandle() { findElement(By.className("header-resize-dnd-second")), getCommandExecutor()); } + + + /** + * Override to allow cell context menu tests to pass for PhantomJS. + * See the linked issue below for code. PhantomJS doesn't support context + * menu directly with Selenium. + * + * @see com.vaadin.testbench.TestBenchElement#contextClick() + * @see "https://github.com/ariya/phantomjs/issues/14005" + */ + @Override + public void contextClick() { + // for PhantomJS, this won't open the context menu + super.contextClick(); + ElementUtil.phantomJSContextClick(getDriver(), getWrappedElement()); + } } diff --git a/vaadin-spreadsheet/reference/BordersWithHiddenColumnsAndRowsTest-test_PhantomJS_sheet1_row_3_hidden.png b/vaadin-spreadsheet/reference/BordersWithHiddenColumnsAndRowsTest-test_PhantomJS_sheet1_row_3_hidden.png index 6bf9820e7..285533ce7 100644 Binary files a/vaadin-spreadsheet/reference/BordersWithHiddenColumnsAndRowsTest-test_PhantomJS_sheet1_row_3_hidden.png and b/vaadin-spreadsheet/reference/BordersWithHiddenColumnsAndRowsTest-test_PhantomJS_sheet1_row_3_hidden.png differ diff --git a/vaadin-spreadsheet/reference/BordersWithHiddenColumnsAndRowsTest-test_PhantomJS_sheet2_initial.png b/vaadin-spreadsheet/reference/BordersWithHiddenColumnsAndRowsTest-test_PhantomJS_sheet2_initial.png index f281e19a9..f07109a9d 100644 Binary files a/vaadin-spreadsheet/reference/BordersWithHiddenColumnsAndRowsTest-test_PhantomJS_sheet2_initial.png and b/vaadin-spreadsheet/reference/BordersWithHiddenColumnsAndRowsTest-test_PhantomJS_sheet2_initial.png differ diff --git a/vaadin-spreadsheet/reference/CellBorderInGridlessSheetTest-openSpreadsheet_fromExcelFileWith_bordersAndNoGrid_thereAreBorders_PhantomJS_bordersAndNoGrid.png b/vaadin-spreadsheet/reference/CellBorderInGridlessSheetTest-openSpreadsheet_fromExcelFileWith_bordersAndNoGrid_thereAreBorders_PhantomJS_bordersAndNoGrid.png index d026dcb2a..9d4bfcac1 100644 Binary files a/vaadin-spreadsheet/reference/CellBorderInGridlessSheetTest-openSpreadsheet_fromExcelFileWith_bordersAndNoGrid_thereAreBorders_PhantomJS_bordersAndNoGrid.png and b/vaadin-spreadsheet/reference/CellBorderInGridlessSheetTest-openSpreadsheet_fromExcelFileWith_bordersAndNoGrid_thereAreBorders_PhantomJS_bordersAndNoGrid.png differ diff --git a/vaadin-spreadsheet/reference/CellOverflowTest-cellTextInput_htmlText_renderedAsText_PhantomJS_htmlText.png b/vaadin-spreadsheet/reference/CellOverflowTest-cellTextInput_htmlText_renderedAsText_PhantomJS_htmlText.png index 2f05a9a39..f269ccd59 100644 Binary files a/vaadin-spreadsheet/reference/CellOverflowTest-cellTextInput_htmlText_renderedAsText_PhantomJS_htmlText.png and b/vaadin-spreadsheet/reference/CellOverflowTest-cellTextInput_htmlText_renderedAsText_PhantomJS_htmlText.png differ diff --git a/vaadin-spreadsheet/reference/CellOverflowTest-cellTextInput_longHtmlText_inputWrappedAndShownAsText_PhantomJS_longHtmlTextWrapped.png b/vaadin-spreadsheet/reference/CellOverflowTest-cellTextInput_longHtmlText_inputWrappedAndShownAsText_PhantomJS_longHtmlTextWrapped.png index 75b03772d..48f85a38b 100644 Binary files a/vaadin-spreadsheet/reference/CellOverflowTest-cellTextInput_longHtmlText_inputWrappedAndShownAsText_PhantomJS_longHtmlTextWrapped.png and b/vaadin-spreadsheet/reference/CellOverflowTest-cellTextInput_longHtmlText_inputWrappedAndShownAsText_PhantomJS_longHtmlTextWrapped.png differ diff --git a/vaadin-spreadsheet/reference/ConditionalFormatterTBTest-conditionalFormatting_formulaWithRelativeRowCol_formattingApplied_PhantomJS_relative_formula.png b/vaadin-spreadsheet/reference/ConditionalFormatterTBTest-conditionalFormatting_formulaWithRelativeRowCol_formattingApplied_PhantomJS_relative_formula.png index 2de6e6930..a7819a4dd 100644 Binary files a/vaadin-spreadsheet/reference/ConditionalFormatterTBTest-conditionalFormatting_formulaWithRelativeRowCol_formattingApplied_PhantomJS_relative_formula.png and b/vaadin-spreadsheet/reference/ConditionalFormatterTBTest-conditionalFormatting_formulaWithRelativeRowCol_formattingApplied_PhantomJS_relative_formula.png differ diff --git a/vaadin-spreadsheet/reference/CustomComponentCreateTest-CustomEditor_AddEditor_DisplayEditorImmediately_PhantomJS_customeditor_addcell_displayeditor.png b/vaadin-spreadsheet/reference/CustomComponentCreateTest-CustomEditor_AddEditor_DisplayEditorImmediately_PhantomJS_customeditor_addcell_displayeditor.png index 66cb0d370..5123a5c81 100644 Binary files a/vaadin-spreadsheet/reference/CustomComponentCreateTest-CustomEditor_AddEditor_DisplayEditorImmediately_PhantomJS_customeditor_addcell_displayeditor.png and b/vaadin-spreadsheet/reference/CustomComponentCreateTest-CustomEditor_AddEditor_DisplayEditorImmediately_PhantomJS_customeditor_addcell_displayeditor.png differ diff --git a/vaadin-spreadsheet/reference/GroupingRenderTest-testRenderingLargeGrouping_PhantomJS_grouping_render_large.png b/vaadin-spreadsheet/reference/GroupingRenderTest-testRenderingLargeGrouping_PhantomJS_grouping_render_large.png index 9d76571de..87d9d421b 100644 Binary files a/vaadin-spreadsheet/reference/GroupingRenderTest-testRenderingLargeGrouping_PhantomJS_grouping_render_large.png and b/vaadin-spreadsheet/reference/GroupingRenderTest-testRenderingLargeGrouping_PhantomJS_grouping_render_large.png differ diff --git a/vaadin-spreadsheet/reference/GroupingTest-grouping_themeHasChanged_theSpreadsheetIsRenderedCorrectly_PhantomJS_grouping_styling_demo.png b/vaadin-spreadsheet/reference/GroupingTest-grouping_themeHasChanged_theSpreadsheetIsRenderedCorrectly_PhantomJS_grouping_styling_demo.png index f39ec622a..fdd6e2ba8 100644 Binary files a/vaadin-spreadsheet/reference/GroupingTest-grouping_themeHasChanged_theSpreadsheetIsRenderedCorrectly_PhantomJS_grouping_styling_demo.png and b/vaadin-spreadsheet/reference/GroupingTest-grouping_themeHasChanged_theSpreadsheetIsRenderedCorrectly_PhantomJS_grouping_styling_demo.png differ diff --git a/vaadin-spreadsheet/reference/GroupingTest-grouping_themeHasChanged_theSpreadsheetIsRenderedCorrectly_PhantomJS_grouping_styling_legacy.png b/vaadin-spreadsheet/reference/GroupingTest-grouping_themeHasChanged_theSpreadsheetIsRenderedCorrectly_PhantomJS_grouping_styling_legacy.png index c10823603..80f9c93b3 100644 Binary files a/vaadin-spreadsheet/reference/GroupingTest-grouping_themeHasChanged_theSpreadsheetIsRenderedCorrectly_PhantomJS_grouping_styling_legacy.png and b/vaadin-spreadsheet/reference/GroupingTest-grouping_themeHasChanged_theSpreadsheetIsRenderedCorrectly_PhantomJS_grouping_styling_legacy.png differ diff --git a/vaadin-spreadsheet/reference/MergeTests-testColumnAlignments_PhantomJS_column_alignments.png b/vaadin-spreadsheet/reference/MergeTests-testColumnAlignments_PhantomJS_column_alignments.png index 15ff38d84..e34c2a7ff 100644 Binary files a/vaadin-spreadsheet/reference/MergeTests-testColumnAlignments_PhantomJS_column_alignments.png and b/vaadin-spreadsheet/reference/MergeTests-testColumnAlignments_PhantomJS_column_alignments.png differ diff --git a/vaadin-spreadsheet/reference/MergedAlignmentTest-alignment_spreadsheetWithMergedCellsWithAlignedContents_correctAlignments_PhantomJS_alignment_with_merged_cells.png b/vaadin-spreadsheet/reference/MergedAlignmentTest-alignment_spreadsheetWithMergedCellsWithAlignedContents_correctAlignments_PhantomJS_alignment_with_merged_cells.png index 39b37e179..f65218bef 100644 Binary files a/vaadin-spreadsheet/reference/MergedAlignmentTest-alignment_spreadsheetWithMergedCellsWithAlignedContents_correctAlignments_PhantomJS_alignment_with_merged_cells.png and b/vaadin-spreadsheet/reference/MergedAlignmentTest-alignment_spreadsheetWithMergedCellsWithAlignedContents_correctAlignments_PhantomJS_alignment_with_merged_cells.png differ diff --git a/vaadin-spreadsheet/reference/MergedCellNarrowFirstColumnTest-overflowBasedOnFullMergedWidth_PhantomJS_mergedNarrowColumn.png b/vaadin-spreadsheet/reference/MergedCellNarrowFirstColumnTest-overflowBasedOnFullMergedWidth_PhantomJS_mergedNarrowColumn.png old mode 100755 new mode 100644 index 0cdbf071a..ef45b334f Binary files a/vaadin-spreadsheet/reference/MergedCellNarrowFirstColumnTest-overflowBasedOnFullMergedWidth_PhantomJS_mergedNarrowColumn.png and b/vaadin-spreadsheet/reference/MergedCellNarrowFirstColumnTest-overflowBasedOnFullMergedWidth_PhantomJS_mergedNarrowColumn.png differ diff --git a/vaadin-spreadsheet/reference/MergedCellOverflowTest-overflow_spreadsheetWithMergedAndFormattedArea_noOverflowFromFirstCell_PhantomJS_mergedOverflow.png b/vaadin-spreadsheet/reference/MergedCellOverflowTest-overflow_spreadsheetWithMergedAndFormattedArea_noOverflowFromFirstCell_PhantomJS_mergedOverflow.png index 208aacd14..ac7b0d5c3 100644 Binary files a/vaadin-spreadsheet/reference/MergedCellOverflowTest-overflow_spreadsheetWithMergedAndFormattedArea_noOverflowFromFirstCell_PhantomJS_mergedOverflow.png and b/vaadin-spreadsheet/reference/MergedCellOverflowTest-overflow_spreadsheetWithMergedAndFormattedArea_noOverflowFromFirstCell_PhantomJS_mergedOverflow.png differ diff --git a/vaadin-spreadsheet/reference/RowColumnStylesTest-styles_sheetHasRowAndColumnStyles_spreadsheetIsRenderedCorrectly_PhantomJS_row_and_column_styles.png b/vaadin-spreadsheet/reference/RowColumnStylesTest-styles_sheetHasRowAndColumnStyles_spreadsheetIsRenderedCorrectly_PhantomJS_row_and_column_styles.png index 06f21f370..5b6f5cefe 100644 Binary files a/vaadin-spreadsheet/reference/RowColumnStylesTest-styles_sheetHasRowAndColumnStyles_spreadsheetIsRenderedCorrectly_PhantomJS_row_and_column_styles.png and b/vaadin-spreadsheet/reference/RowColumnStylesTest-styles_sheetHasRowAndColumnStyles_spreadsheetIsRenderedCorrectly_PhantomJS_row_and_column_styles.png differ diff --git a/vaadin-spreadsheet/reference/ScrollTBTest-testHiddenColumnHeaderScrollingFix_PhantomJS_hiddenColumnScroll.png b/vaadin-spreadsheet/reference/ScrollTBTest-testHiddenColumnHeaderScrollingFix_PhantomJS_hiddenColumnScroll.png index d2ebad423..f077bb14e 100644 Binary files a/vaadin-spreadsheet/reference/ScrollTBTest-testHiddenColumnHeaderScrollingFix_PhantomJS_hiddenColumnScroll.png and b/vaadin-spreadsheet/reference/ScrollTBTest-testHiddenColumnHeaderScrollingFix_PhantomJS_hiddenColumnScroll.png differ diff --git a/vaadin-spreadsheet/src/main/java/com/vaadin/addon/spreadsheet/ContextMenuManager.java b/vaadin-spreadsheet/src/main/java/com/vaadin/addon/spreadsheet/ContextMenuManager.java index a1cee6581..2641130de 100644 --- a/vaadin-spreadsheet/src/main/java/com/vaadin/addon/spreadsheet/ContextMenuManager.java +++ b/vaadin-spreadsheet/src/main/java/com/vaadin/addon/spreadsheet/ContextMenuManager.java @@ -29,6 +29,7 @@ import com.vaadin.event.Action; import com.vaadin.event.Action.Handler; import com.vaadin.server.KeyMapper; +import com.vaadin.shared.Registration; /** * ContextMenuManager is an utility class for the Spreadsheet component. This @@ -51,6 +52,8 @@ public class ContextMenuManager implements Serializable { private int contextMenuHeaderIndex = -1; + private Registration contextClickRegistration; + /** * Constructs a new ContextMenuManager and ties it to the given Spreadsheet. * @@ -77,6 +80,7 @@ public void addActionHandler(Handler actionHandler) { actionHandlers.add(actionHandler); } } + checkContextClickHandler(); } /** @@ -94,6 +98,7 @@ public void removeActionHandler(Handler actionHandler) { actionMapper = null; } } + checkContextClickHandler(); } /** @@ -106,6 +111,21 @@ public boolean hasActionHandlers() { return actionHandlers != null && actionHandlers.size() > 0; } + private void checkContextClickHandler() { + if (hasActionHandlers()) { + if (contextClickRegistration == null) { + contextClickRegistration = spreadsheet + .addContextClickListener(event -> { + // this is never called, only here to tell the connector to + // watch for context events + }); + } + } else if (contextClickRegistration != null) { + contextClickRegistration.remove(); + contextClickRegistration = null; + } + } + /** * This method is called when a context menu event has happened on any cell * of the target Spreadsheet. diff --git a/vaadin-spreadsheet/src/main/java/com/vaadin/addon/spreadsheet/Spreadsheet.java b/vaadin-spreadsheet/src/main/java/com/vaadin/addon/spreadsheet/Spreadsheet.java index b888bcaa5..9269de765 100644 --- a/vaadin-spreadsheet/src/main/java/com/vaadin/addon/spreadsheet/Spreadsheet.java +++ b/vaadin-spreadsheet/src/main/java/com/vaadin/addon/spreadsheet/Spreadsheet.java @@ -88,7 +88,9 @@ import com.vaadin.addon.spreadsheet.shared.SpreadsheetState; import com.vaadin.event.Action; import com.vaadin.event.Action.Handler; +import com.vaadin.event.ContextClickEvent; import com.vaadin.server.Resource; +import com.vaadin.shared.MouseEventDetails; import com.vaadin.ui.AbstractComponent; import com.vaadin.ui.Component; import com.vaadin.ui.Component.Focusable; diff --git a/vaadin-spreadsheet/src/main/java/com/vaadin/addon/spreadsheet/client/SelectionWidget.java b/vaadin-spreadsheet/src/main/java/com/vaadin/addon/spreadsheet/client/SelectionWidget.java index 8c3fae67a..0be69b13d 100644 --- a/vaadin-spreadsheet/src/main/java/com/vaadin/addon/spreadsheet/client/SelectionWidget.java +++ b/vaadin-spreadsheet/src/main/java/com/vaadin/addon/spreadsheet/client/SelectionWidget.java @@ -824,9 +824,6 @@ public void setPosition(int col1, int col2, int row1, int row2) { setFillMode(false); } - if (!dragging) { - showTouchActions(); - } } public void setPaintPosition(int col1, int col2, int row1, int row2) { @@ -847,128 +844,6 @@ public void setPaintPosition(int col1, int col2, int row1, int row2) { } } - private void showTouchActions() { - if (touchMode) { - // show touch actions in popup - - if (touchActions != null) { - // remove old - touchActions.hide(); - } - - touchActions = new VOverlay(true); - touchActions.setOwner((Widget) sheetWidget.actionHandler); - touchActions.addStyleName("v-contextmenu"); - - final MenuBar m = new MenuBar(); - m.addItem(new SafeHtmlBuilder().appendEscaped("Fill").toSafeHtml(), - new ScheduledCommand() { - - @Override - public void execute() { - setFillMode(true); - touchActions.hide(); - } - }); - - touchActions.add(m); - - Scheduler.get().scheduleDeferred(new ScheduledCommand() { - - @Override - public void execute() { - touchActions - .setPopupPositionAndShow(new PositionCallback() { - - @Override - public void setPosition(int offsetWidth, - int offsetHeight) { - // above top border - int top = 0; - int left = 0; - int bottom = 0; - int width = 0; - int parentTop = 0; - if (topRight != null - && topRight.isVisible()) { - top = topRight.top.getAbsoluteTop(); - left = topRight.top.getAbsoluteLeft(); - width = topRight.top.getClientWidth(); - bottom = topRight.bottom - .getAbsoluteBottom() + 5; - if (topLeft.isVisible()) { - width += topLeft.top - .getClientWidth(); - } - if (bottomRight.isVisible()) { - bottom = bottomRight.bottom - .getAbsoluteBottom() + 5; - } - } else if (topLeft != null - && topLeft.isVisible()) { - top = topLeft.top.getAbsoluteTop(); - left = topLeft.top.getAbsoluteLeft(); - width = topLeft.top.getClientWidth(); - bottom = topLeft.bottom - .getAbsoluteBottom() + 5; - if (bottomLeft.isVisible()) { - bottom = bottomLeft.bottom - .getAbsoluteBottom() + 5; - } - } else if (bottomLeft != null - && bottomLeft.isVisible()) { - top = bottomLeft.top.getAbsoluteTop(); - left = bottomLeft.top.getAbsoluteLeft(); - width = bottomLeft.top.getClientWidth(); - bottom = bottomLeft.bottom - .getAbsoluteBottom() + 5; - if (bottomRight.isVisible()) { - width += bottomRight.top - .getClientWidth(); - } - } else { - top = bottomRight.top.getAbsoluteTop(); - left = bottomRight.top - .getAbsoluteLeft(); - width = bottomRight.top - .getClientWidth(); - bottom = bottomRight.bottom - .getAbsoluteBottom() + 5; - } - if (width > sheetWidget.getElement() - .getClientWidth()) { - width = sheetWidget.getElement() - .getClientWidth(); - } - - if (sheetWidget.hasFrozenRows()) { - parentTop = sheetWidget - .getTopRightPane() - .getAbsoluteTop(); - } else { - parentTop = sheetWidget - .getBottomRightPane() - .getAbsoluteTop(); - } - - top -= offsetHeight + 5; - left += (width / 2) - (offsetWidth / 2); - - if (parentTop > top) { - // put under instead - top = bottom + 5; - } - touchActions.setPopupPosition(left, top); - - // TODO check for room - } - }); - touchActions.show(); - } - }); - } - } - @Override public void setWidth(String width) { @@ -1224,7 +1099,6 @@ private void stopSelectingCells(Event event) { sheetWidget.getSelectedCellRow(), tempRow); dragging = false; - showTouchActions(); } protected void setFillMode(boolean fillMode) { diff --git a/vaadin-spreadsheet/src/main/java/com/vaadin/addon/spreadsheet/client/SheetEventListener.java b/vaadin-spreadsheet/src/main/java/com/vaadin/addon/spreadsheet/client/SheetEventListener.java index 6e292a858..4d21e0ba1 100644 --- a/vaadin-spreadsheet/src/main/java/com/vaadin/addon/spreadsheet/client/SheetEventListener.java +++ b/vaadin-spreadsheet/src/main/java/com/vaadin/addon/spreadsheet/client/SheetEventListener.java @@ -95,11 +95,8 @@ public void onBrowserEvent(Event event) { } break; case Event.ONMOUSEUP: - if (event.getButton() == NativeEvent.BUTTON_RIGHT) { - // Context menu is displayed on mouse up to prevent - // contextmenu event on VContextMenu - widget.onSheetMouseDown(event); - } + // now that context menus are handled with the contextMenuEvent + // this should do nothing. break; case Event.ONDBLCLICK: onSheetDoubleClick(event); diff --git a/vaadin-spreadsheet/src/main/java/com/vaadin/addon/spreadsheet/client/SheetHandler.java b/vaadin-spreadsheet/src/main/java/com/vaadin/addon/spreadsheet/client/SheetHandler.java index 15ed3cd1b..c8574b5b4 100644 --- a/vaadin-spreadsheet/src/main/java/com/vaadin/addon/spreadsheet/client/SheetHandler.java +++ b/vaadin-spreadsheet/src/main/java/com/vaadin/addon/spreadsheet/client/SheetHandler.java @@ -161,6 +161,11 @@ void onScrollViewChanged(int firstRow, int lastRow, int firstColumn, */ void onCellRightClick(NativeEvent nativeEvent, int column, int row); + /** + * if there is a connector iOS context click timer running, cancel it + */ + void cancelContextClickTimer(); + /** * Called on right mouse button click on top of a row header * diff --git a/vaadin-spreadsheet/src/main/java/com/vaadin/addon/spreadsheet/client/SheetWidget.java b/vaadin-spreadsheet/src/main/java/com/vaadin/addon/spreadsheet/client/SheetWidget.java index 8c450ced5..345358124 100644 --- a/vaadin-spreadsheet/src/main/java/com/vaadin/addon/spreadsheet/client/SheetWidget.java +++ b/vaadin-spreadsheet/src/main/java/com/vaadin/addon/spreadsheet/client/SheetWidget.java @@ -1036,13 +1036,18 @@ protected void onSheetMouseMove(Event event) { } protected boolean isEventInCustomEditorCell(Event event) { + final Element target = event.getEventTarget().cast(); + return isEventInCustomEditorCell(target); + } + protected boolean isEventInCustomEditorCell(Element target) { if (customEditorWidget != null) { - final Element target = event.getEventTarget().cast(); final Element customWidgetElement = customEditorWidget.getElement(); - return (customWidgetElement.isOrHasChild(target) || customWidgetElement - .getParentElement() != null - && customWidgetElement.getParentElement().isOrHasChild( - target)); + final Element customEditorParent = customWidgetElement.getParentElement(); + boolean isEventInCustomEditorCell = customWidgetElement.isOrHasChild(target) + || (customEditorParent != null + && customEditorParent.isOrHasChild( + target) ); + return isEventInCustomEditorCell; } return false; } @@ -1186,7 +1191,7 @@ protected void onSheetMouseDown(Event event) { event.preventDefault(); if (event.getButton() == NativeEvent.BUTTON_RIGHT) { Event.releaseCapture(sheet); - actionHandler.onCellRightClick(event, targetCol, targetRow); + // handled by ContextMenuEvent or iOS touch event with timer (SheetInputEventListener) } else { sheet.focus(); // quit input if active @@ -1761,30 +1766,6 @@ private int isHeader(Element target) { } } }); - addDomHandler(new ContextMenuHandler() { - - @Override - public void onContextMenu(ContextMenuEvent event) { - if (actionHandler.hasCustomContextMenu()) { - Element target = event.getNativeEvent().getEventTarget() - .cast(); - String className = target.getAttribute("class"); - int i = jsniUtil.isHeader(className); - if (i == 1 || i == 2) { - int index = jsniUtil.parseHeaderIndex(className); - if (i == 1) { - actionHandler.onRowHeaderRightClick( - event.getNativeEvent(), index); - } else { - actionHandler.onColumnHeaderRightClick( - event.getNativeEvent(), index); - } - } - event.preventDefault(); - event.stopPropagation(); - } - } - }, ContextMenuEvent.getType()); } protected boolean isEditingCell() { @@ -2928,6 +2909,7 @@ private void clearListOfCells(ArrayList row) { * handler (if needed). */ private void onSheetScroll() { + actionHandler.cancelContextClickTimer(); int scrollTop = sheet.getScrollTop(); int scrollLeft = sheet.getScrollLeft(); int vScrollDiff = scrollTop - previousScrollTop; diff --git a/vaadin-spreadsheet/src/main/java/com/vaadin/addon/spreadsheet/client/SpreadsheetConnector.java b/vaadin-spreadsheet/src/main/java/com/vaadin/addon/spreadsheet/client/SpreadsheetConnector.java index c0895293b..d461545c0 100644 --- a/vaadin-spreadsheet/src/main/java/com/vaadin/addon/spreadsheet/client/SpreadsheetConnector.java +++ b/vaadin-spreadsheet/src/main/java/com/vaadin/addon/spreadsheet/client/SpreadsheetConnector.java @@ -28,19 +28,25 @@ import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.Scheduler; import com.google.gwt.core.client.Scheduler.ScheduledCommand; +import com.google.gwt.dom.client.BrowserEvents; +import com.google.gwt.dom.client.Document; +import com.google.gwt.dom.client.Element; +import com.google.gwt.dom.client.EventTarget; import com.google.gwt.dom.client.NativeEvent; import com.google.gwt.event.dom.client.ContextMenuEvent; import com.google.gwt.event.dom.client.ContextMenuHandler; import com.google.gwt.event.shared.HandlerRegistration; -import com.google.gwt.user.client.Window; +import com.google.gwt.user.client.Event; import com.google.gwt.user.client.ui.Image; import com.google.gwt.user.client.ui.Widget; import com.vaadin.addon.spreadsheet.Spreadsheet; import com.vaadin.addon.spreadsheet.client.SpreadsheetWidget.SheetContextMenuHandler; import com.vaadin.addon.spreadsheet.shared.SpreadsheetState; import com.vaadin.client.ApplicationConnection; +import com.vaadin.client.BrowserInfo; import com.vaadin.client.ComponentConnector; import com.vaadin.client.ConnectorHierarchyChangeEvent; +import com.vaadin.client.WidgetUtil; import com.vaadin.client.communication.StateChangeEvent; import com.vaadin.client.ui.AbstractHasComponentsConnector; import com.vaadin.client.ui.Action; @@ -48,6 +54,7 @@ import com.vaadin.client.ui.PostLayoutListener; import com.vaadin.client.ui.layout.ElementResizeEvent; import com.vaadin.client.ui.layout.ElementResizeListener; +import com.vaadin.shared.MouseEventDetails; import com.vaadin.shared.ui.Connect; import com.vaadin.shared.ui.Connect.LoadStyle; @@ -80,6 +87,7 @@ public void showActions( final ArrayList actionDetails) { int left; int top; + // getTouchOrMouseClientX/Y() add in scroll position, don't repeat if (latestCellContextMenuEvent != null) { left = SpreadsheetWidget .getTouchOrMouseClientX(latestCellContextMenuEvent); @@ -91,8 +99,6 @@ public void showActions( top = SpreadsheetWidget .getTouchOrMouseClientY(latestHeaderContextMenuEvent); } - top += Window.getScrollTop(); - left += Window.getScrollLeft(); getConnection().getContextMenu().showAt(new ActionOwner() { @Override @@ -123,7 +129,7 @@ public Action[] getActions() { } }, left, top); } - + @Override public void setSelectedCellAndRange(String name, int col, int row, int c1, int c2, int r1, int r2, boolean scroll) { @@ -511,6 +517,107 @@ public void onConnectorHierarchyChange(ConnectorHierarchyChangeEvent event) { } } + /** + * @see com.vaadin.client.ui.AbstractComponentConnector#sendContextClickEvent(com.vaadin.shared.MouseEventDetails, com.google.gwt.dom.client.EventTarget) + */ + @Override + protected void sendContextClickEvent(MouseEventDetails details, + EventTarget eventTarget) { + + Element target = eventTarget.cast(); + + String className = target.getAttribute("class"); + + // click target is the inner div because IE10 and 9 are not compatible + // with 'pointer-events: none' + if ((BrowserInfo.get().isIE9() || BrowserInfo.get().isIE10()) + && (className == null || className.isEmpty())) { + String parentClassName = target.getParentElement().getAttribute( + "class"); + if (parentClassName.contains("cell")) { + className = parentClassName; + } + } + + SheetWidget sheetWidget = getWidget().getSheetWidget(); + SheetJsniUtil jsniUtil = sheetWidget.getSheetJsniUtil(); + NativeEvent evt = Document.get().createMouseEvent( + BrowserEvents.CONTEXTMENU, + true, + true, + 0, + details.getRelativeX(), + details.getRelativeY(), + details.getClientX(), + details.getClientY(), + details.isCtrlKey(), + details.isAltKey(), + details.isShiftKey(), + details.isMetaKey(), + NativeEvent.BUTTON_RIGHT, + target + ); + + Event event = Event.as(evt); + + int i = jsniUtil.isHeader(className); + if (i == 1 || i == 2) { + int index = jsniUtil.parseHeaderIndex(className); + if (i == 1) { + sheetWidget.actionHandler.onRowHeaderRightClick( + event, index); + } else { + sheetWidget.actionHandler.onColumnHeaderRightClick( + event, index); + } + } else { + + if (className.contains("sheet") || target.getTagName().equals("input") + || className.equals("floater")) { + return; // event target is one of the panes or input + } + + // event we created above doesn't have an actual target, so can't use that + if (sheetWidget.isEventInCustomEditorCell(target)) { + // allow sheet context menu on top of custom editors + sheetWidget.getSheetHandler().onCellRightClick(event, + sheetWidget.getSelectedCellColumn(), + sheetWidget.getSelectedCellRow()); + } else if (className.contains("cell")) { + if (className.equals("cell-comment-triangle")) { + sheetWidget.jsniUtil.parseColRow( + target.getParentElement().getAttribute( + "class")); + } else { + sheetWidget.jsniUtil.parseColRow(className); + } + int targetCol = sheetWidget.jsniUtil.getParsedCol(); + int targetRow = sheetWidget.jsniUtil.getParsedRow(); + + sheetWidget.getSheetHandler() + .onCellRightClick(event, targetCol, targetRow); + } else { + // see if this is a custom component in a cell + // if it had it's own context menu, the event wouldn't get here + final Element ssElement = getWidget().getElement(); + while (target != null && ! ssElement.equals(target)) { + if (target.getClassName().contains(" cell ")) { + className = target.getClassName(); + sheetWidget.jsniUtil.parseColRow(className); + int targetCol = sheetWidget.jsniUtil.getParsedCol(); + int targetRow = sheetWidget.jsniUtil.getParsedRow(); + sheetWidget.getSheetHandler() + .onCellRightClick(event, targetCol, targetRow); + return; + } + target = target.getParentElement(); + } + } + } + + WidgetUtil.clearTextSelection(); + } + @Override public void postLayout() { getWidget().refreshOverlayPositions(); diff --git a/vaadin-spreadsheet/src/main/java/com/vaadin/addon/spreadsheet/client/SpreadsheetWidget.java b/vaadin-spreadsheet/src/main/java/com/vaadin/addon/spreadsheet/client/SpreadsheetWidget.java index a03ee816c..a9670a8c0 100644 --- a/vaadin-spreadsheet/src/main/java/com/vaadin/addon/spreadsheet/client/SpreadsheetWidget.java +++ b/vaadin-spreadsheet/src/main/java/com/vaadin/addon/spreadsheet/client/SpreadsheetWidget.java @@ -46,6 +46,7 @@ import com.vaadin.client.Util; import com.vaadin.client.WidgetUtil; import com.vaadin.client.communication.RpcProxy; +import com.vaadin.client.ui.AbstractComponentConnector; public class SpreadsheetWidget extends Composite implements SheetHandler, FormulaBarHandler, SheetTabSheetHandler, Focusable { @@ -576,6 +577,24 @@ public void onColumnHeaderRightClick(NativeEvent nativeEvent, } } + /** + * Cancel touch timers from sheet scroll and other events as needed + * + * @see com.vaadin.addon.spreadsheet.client.SheetHandler#cancelContextClickTimer() + */ + public void cancelContextClickTimer() { + callContextClickTimerCancel((AbstractComponentConnector) Util.findConnectorFor(this)); + } + + /** + * The method we need is private, but this is GWT, so we access it via JSNI + * @param ssCon need to use the direct class that declares the desired method + * or the GWT compiler complains + */ + private static native void callContextClickTimerCancel(AbstractComponentConnector ssCon) /*-{ + ssCon.@com.vaadin.client.ui.AbstractComponentConnector::cancelTouchTimer()(); + }-*/; + @Override public void onCellClick(int column, int row, String value, boolean shiftKey, boolean metaOrCtrlKey, diff --git a/vaadin-spreadsheet/src/test/java/com/vaadin/addon/spreadsheet/test/AbstractSpreadsheetTestCase.java b/vaadin-spreadsheet/src/test/java/com/vaadin/addon/spreadsheet/test/AbstractSpreadsheetTestCase.java index 2690e58b7..3b7615918 100644 --- a/vaadin-spreadsheet/src/test/java/com/vaadin/addon/spreadsheet/test/AbstractSpreadsheetTestCase.java +++ b/vaadin-spreadsheet/src/test/java/com/vaadin/addon/spreadsheet/test/AbstractSpreadsheetTestCase.java @@ -10,7 +10,9 @@ import org.junit.Assert; import org.junit.Before; import org.openqa.selenium.By; +import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; +import org.openqa.selenium.support.ui.ExpectedCondition; import org.openqa.selenium.support.ui.ExpectedConditions; import com.vaadin.addon.spreadsheet.test.demoapps.SpreadsheetDemoUI; @@ -65,6 +67,16 @@ protected void waitForElementPresent(By locator) { waitUntil(ExpectedConditions.presenceOfElementLocated(locator)); } + protected void waitForContexMenu() { + waitUntil(new ExpectedCondition() { + @Override + public Object apply(WebDriver webDriver) { + return webDriver.findElements(By.className("v-contextmenu")).size() > 0; + } + }); + } + + protected void setLocale(Locale locale) { $(NativeSelectElement.class).id("localeSelect") .selectByText(locale.getDisplayName()); diff --git a/vaadin-spreadsheet/src/test/java/com/vaadin/addon/spreadsheet/test/CommentTest.java b/vaadin-spreadsheet/src/test/java/com/vaadin/addon/spreadsheet/test/CommentTest.java index 35f8d17f6..48d022543 100644 --- a/vaadin-spreadsheet/src/test/java/com/vaadin/addon/spreadsheet/test/CommentTest.java +++ b/vaadin-spreadsheet/src/test/java/com/vaadin/addon/spreadsheet/test/CommentTest.java @@ -56,6 +56,7 @@ public void openFileWithComment_deleteComment_NoException() ContextMenuHelper contextMenu = new ContextMenuHelper(driver); SheetCellElement cell = spreadsheet.getCellAt(3, 3); cell.contextClick(); + waitForContexMenu(); contextMenu.clickItem("Delete comment"); assertNoErrorIndicatorDetected(); } @@ -69,6 +70,7 @@ public void openFileWithComment_showComment_NoException() ContextMenuHelper contextMenu = new ContextMenuHelper(driver); SheetCellElement cell = spreadsheet.getCellAt(3, 3); cell.contextClick(); + waitForContexMenu(); contextMenu.clickItem("Show comment"); assertNoErrorIndicatorDetected(); } diff --git a/vaadin-spreadsheet/src/test/java/com/vaadin/addon/spreadsheet/test/FormulaFormatTest.java b/vaadin-spreadsheet/src/test/java/com/vaadin/addon/spreadsheet/test/FormulaFormatTest.java index e665cf389..ee7e9bf0b 100644 --- a/vaadin-spreadsheet/src/test/java/com/vaadin/addon/spreadsheet/test/FormulaFormatTest.java +++ b/vaadin-spreadsheet/src/test/java/com/vaadin/addon/spreadsheet/test/FormulaFormatTest.java @@ -3,7 +3,6 @@ import java.util.Locale; import org.junit.Test; -import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.support.ui.ExpectedCondition; @@ -233,13 +232,4 @@ private void reduceFontSizeAtCellA1() { executeScript(script); } - private void waitForContexMenu() { - waitUntil(new ExpectedCondition() { - @Override - public Object apply(WebDriver webDriver) { - return webDriver.findElements(By.className("v-contextmenu")).size() > 0; - } - }); - } - } diff --git a/vaadin-spreadsheet/src/test/java/com/vaadin/addon/spreadsheet/test/SheetFilterTableTest.java b/vaadin-spreadsheet/src/test/java/com/vaadin/addon/spreadsheet/test/SheetFilterTableTest.java index 2e2b16f89..05509ab58 100644 --- a/vaadin-spreadsheet/src/test/java/com/vaadin/addon/spreadsheet/test/SheetFilterTableTest.java +++ b/vaadin-spreadsheet/src/test/java/com/vaadin/addon/spreadsheet/test/SheetFilterTableTest.java @@ -41,6 +41,7 @@ public void filter_removeTable_hideFilter() { headerPage.loadTestFixture(TestFixtures.SpreadsheetTable); final SheetCellElement cell = spreadsheet.getCellAt("B2"); cell.contextClick(); + waitForContexMenu(); spreadsheet.getContextMenu().getItem("Delete Table B2:F6").click(); waitUntil(new ExpectedCondition() { @Override diff --git a/vaadin-spreadsheet/src/test/java/com/vaadin/addon/spreadsheet/test/demoapps/TouchUI.java b/vaadin-spreadsheet/src/test/java/com/vaadin/addon/spreadsheet/test/demoapps/TouchUI.java index 5ba72d5be..22c921448 100644 --- a/vaadin-spreadsheet/src/test/java/com/vaadin/addon/spreadsheet/test/demoapps/TouchUI.java +++ b/vaadin-spreadsheet/src/test/java/com/vaadin/addon/spreadsheet/test/demoapps/TouchUI.java @@ -1,6 +1,7 @@ package com.vaadin.addon.spreadsheet.test.demoapps; import com.vaadin.addon.spreadsheet.Spreadsheet; +import com.vaadin.addon.spreadsheet.test.fixtures.ActionFixture; import com.vaadin.annotations.Theme; import com.vaadin.annotations.Viewport; import com.vaadin.annotations.Widgetset; @@ -20,6 +21,8 @@ protected void init(VaadinRequest request) { setContent(ss); ss.setSizeFull(); setSizeFull(); + + new ActionFixture().loadFixture(ss); } } diff --git a/vaadin-spreadsheet/src/test/java/com/vaadin/addon/spreadsheet/test/fixtures/ActionFixture.java b/vaadin-spreadsheet/src/test/java/com/vaadin/addon/spreadsheet/test/fixtures/ActionFixture.java index 470dc0cac..8a3697c5e 100644 --- a/vaadin-spreadsheet/src/test/java/com/vaadin/addon/spreadsheet/test/fixtures/ActionFixture.java +++ b/vaadin-spreadsheet/src/test/java/com/vaadin/addon/spreadsheet/test/fixtures/ActionFixture.java @@ -38,7 +38,13 @@ public Action[] getActions(SelectionChangeEvent selection, } private void doubleValue(Cell cell) { - cell.setCellValue(cell.getNumericCellValue() * 2); + try { + cell.setCellValue(cell.getNumericCellValue() * 2); + } catch (IllegalStateException + | NumberFormatException + | NullPointerException e) { + // ignore + } } });