diff --git a/plugins/org.jkiss.dbeaver.core/plugin.properties b/plugins/org.jkiss.dbeaver.core/plugin.properties index f6d08b115bcfc9cc7fbccd5fa507b8e1be23d6f4..eddf1e4737213668736d967b004ad5035224fe09 100644 --- a/plugins/org.jkiss.dbeaver.core/plugin.properties +++ b/plugins/org.jkiss.dbeaver.core/plugin.properties @@ -128,8 +128,8 @@ command.org.jkiss.dbeaver.core.compare.objects.description=Compare database obje command.org.jkiss.dbeaver.core.resultset.toggleMode.name=Toggle Grid/Record view command.org.jkiss.dbeaver.core.resultset.toggleMode.description=Toggle Result Set Grid/Record View -command.org.jkiss.dbeaver.core.resultset.togglePreview.name=Toggle value view panel -command.org.jkiss.dbeaver.core.resultset.togglePreview.description=Toggle result set cell value view panel +command.org.jkiss.dbeaver.core.resultset.grid.togglePreview.name=Toggle value view panel +command.org.jkiss.dbeaver.core.resultset.grid.togglePreview.description=Toggle result set cell value view panel command.org.jkiss.dbeaver.core.resultset.row.first.name=First row command.org.jkiss.dbeaver.core.resultset.row.first.description=Move to first row command.org.jkiss.dbeaver.core.resultset.row.previous.name=Previous row diff --git a/plugins/org.jkiss.dbeaver.core/plugin.xml b/plugins/org.jkiss.dbeaver.core/plugin.xml index 9ac8ccc3f218bf333e8c04e8cb0b97f096bf2ca6..d79629504c3cd3751932a918cef0e3ffedd84898 100644 --- a/plugins/org.jkiss.dbeaver.core/plugin.xml +++ b/plugins/org.jkiss.dbeaver.core/plugin.xml @@ -222,7 +222,6 @@ - @@ -234,6 +233,7 @@ + @@ -298,7 +298,7 @@ - + @@ -950,7 +950,9 @@ - + + + @@ -959,6 +961,7 @@ + @@ -988,14 +991,6 @@ - - - - - - - - @@ -1645,7 +1640,6 @@ - @@ -1657,6 +1651,7 @@ + diff --git a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/CollectionElementData.java b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/CollectionElementData.java index 294c75e49c6403f7c7dc22a180958d9b51c7e823..ab1a14f618f8f4f5e101604c6120a69b9deff104 100644 --- a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/CollectionElementData.java +++ b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/CollectionElementData.java @@ -35,7 +35,7 @@ import java.util.List; * Complex value element. * Map pair or array item */ -class CollectionElementData { +public class CollectionElementData { static final Log log = Log.getLog(CollectionElementData.class); @@ -67,4 +67,11 @@ class CollectionElementData { } } + public DBDAttributeBinding getCollectionBinding() { + return collectionBinding; + } + + public DBDAttributeBindingElement[] getElements() { + return elements; + } } diff --git a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/FilterValueEditDialog.java b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/FilterValueEditDialog.java index 0ea38860b6f3ff16e637b743075691e747fec6d7..6db33edcaba9c96d6257c921a5a5836d457d19c1 100644 --- a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/FilterValueEditDialog.java +++ b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/FilterValueEditDialog.java @@ -68,7 +68,7 @@ class FilterValueEditDialog extends BaseDialog { editorPlaceholder.setLayoutData(new GridData(GridData.FILL_BOTH)); editorPlaceholder.setLayout(new FillLayout()); - final ResultSetViewer.ResultSetValueController valueController = new ResultSetViewer.ResultSetValueController( + final ResultSetValueController valueController = new ResultSetValueController( viewer, attr, row, diff --git a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/IResultSetController.java b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/IResultSetController.java index 6641e3cf3ba33a314787265c97f332c37cb0f032..c2cad46e8a2fa8dd76c8637ce6ed36a0f8352342 100644 --- a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/IResultSetController.java +++ b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/IResultSetController.java @@ -21,6 +21,7 @@ package org.jkiss.dbeaver.ui.controls.resultset; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.swt.graphics.Color; import org.eclipse.ui.IWorkbenchPartSite; import org.jkiss.code.NotNull; import org.jkiss.code.Nullable; @@ -35,6 +36,8 @@ import org.jkiss.dbeaver.model.struct.DBSDataContainer; */ public interface IResultSetController { + public static final String MENU_GROUP_EDIT = "edit"; + @NotNull IWorkbenchPartSite getSite(); @@ -49,10 +52,14 @@ public interface IResultSetController { boolean hasData(); + boolean isHasMoreData(); + boolean isReadOnly(); boolean isRecordMode(); + boolean isColumnReadOnly(DBDAttributeBinding attr); + @NotNull IPreferenceStore getPreferenceStore(); @@ -60,13 +67,43 @@ public interface IResultSetController { void rejectChanges(); + /** + * Refreshes data. Reads data from underlying data container + */ + void refreshData(@Nullable Runnable onSuccess); + + /** + * Reads next segment of data + */ + void readNextSegment(); + + /** + * Redraws results and updates all toolbars/edit controls + * @param rowsChanged updates contents + */ + void redrawData(boolean rowsChanged); + void fillContextMenu(@NotNull IMenuManager manager, @Nullable DBDAttributeBinding attr, @Nullable ResultSetRow row); @Nullable ResultSetRow getCurrentRow(); + void setCurrentRow(@Nullable ResultSetRow row); + void navigateAssociation(@NotNull DBRProgressMonitor monitor, @NotNull DBDAttributeBinding attr, @NotNull ResultSetRow row) throws DBException; void updateValueView(); + + void updateEditControls(); + + void fireResultSetChange(); + + void setStatus(String message, boolean error); + + Color getDefaultBackground(); + + Color getDefaultForeground(); + + IResultSetPresentation getActivePresentation(); } diff --git a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/IResultSetPresentation.java b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/IResultSetPresentation.java index 26c8ea6ba4bf85cbb0ecb70d1384d2c9da248e4c..dabb10e38ad26a450bdae20de6a5a4f9c682ee24 100644 --- a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/IResultSetPresentation.java +++ b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/IResultSetPresentation.java @@ -19,29 +19,69 @@ package org.jkiss.dbeaver.ui.controls.resultset; +import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.IToolBarManager; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; +import org.jkiss.code.NotNull; +import org.jkiss.code.Nullable; +import org.jkiss.dbeaver.model.data.DBDAttributeBinding; +import org.jkiss.dbeaver.model.data.DBDDisplayFormat; /** * Result set renderer. * Visualizes result set viewer/editor. * - * May additionally implement ISelectionProvider + * May additionally implement ISelectionProvider, IStatefulControl */ public interface IResultSetPresentation { - void createPresentation(IResultSetController controller, Composite parent); + public enum RowPosition { + FIRST, + PREVIOUS, + NEXT, + LAST + } + + + void createPresentation(@NotNull IResultSetController controller, @NotNull Composite parent); Control getControl(); void refreshData(boolean refreshMetadata); + /** + * Called after results refresh + * @param refreshData data was refreshed + */ + void formatData(boolean refreshData); + + void clearData(); + void updateValueView(); - void fillToolbar(IToolBarManager toolBar); + void fillToolbar(@NotNull IToolBarManager toolBar); + + void fillMenu(@NotNull IMenuManager menu); void changeMode(boolean recordMode); - // ISelectionProvider + void scrollToRow(@NotNull RowPosition position); + + @Nullable + DBDAttributeBinding getCurrentAttribute(); + + @Nullable + Control openValueEditor(final boolean inline); + + @Nullable + String copySelectionToString( + boolean copyHeader, + boolean copyRowNumbers, + boolean cut, + String delimiter, + DBDDisplayFormat format); + + void pasteFromClipboard(); + } diff --git a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/IStatefulControl.java b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/IStatefulControl.java new file mode 100644 index 0000000000000000000000000000000000000000..4b63920fbf137d9cac1d1df827fcf5475699fe95 --- /dev/null +++ b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/IStatefulControl.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2010-2015 Serge Rieder + * serge@jkiss.org + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.jkiss.dbeaver.ui.controls.resultset; + +/** + * Result set provider + */ +public interface IStatefulControl { + + + /** + * Saves presentation state (focus position) + */ + Object saveState(); + + /** + * Restores presentation state (focus position) + */ + void restoreState(Object state); + +} diff --git a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/ResultSetCommandHandler.java b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/ResultSetCommandHandler.java index 85f1c5c5cb6baaa47f2cf52ec5dd94452e122ee6..d9546aef70ff670fc08d378dd5a98b3855d71a65 100644 --- a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/ResultSetCommandHandler.java +++ b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/ResultSetCommandHandler.java @@ -27,7 +27,6 @@ import org.eclipse.ui.handlers.HandlerUtil; import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds; import org.jkiss.code.Nullable; import org.jkiss.dbeaver.model.data.DBDDisplayFormat; -import org.jkiss.dbeaver.ui.controls.resultset.spreadsheet.SpreadsheetCommandHandler; import org.jkiss.dbeaver.ui.editors.MultiPageAbstractEditor; /** @@ -35,7 +34,6 @@ import org.jkiss.dbeaver.ui.editors.MultiPageAbstractEditor; */ public class ResultSetCommandHandler extends AbstractHandler { - public static final String CMD_TOGGLE_PREVIEW = "org.jkiss.dbeaver.core.resultset.togglePreview"; public static final String CMD_TOGGLE_MODE = "org.jkiss.dbeaver.core.resultset.toggleMode"; public static final String CMD_ROW_FIRST = "org.jkiss.dbeaver.core.resultset.row.first"; public static final String CMD_ROW_PREVIOUS = "org.jkiss.dbeaver.core.resultset.row.previous"; @@ -62,20 +60,18 @@ public class ResultSetCommandHandler extends AbstractHandler { resultSet.refresh(); } else if (actionId.equals(CMD_TOGGLE_MODE)) { resultSet.toggleMode(); - } else if (actionId.equals(CMD_TOGGLE_PREVIEW)) { - resultSet.togglePreview(); } else if (actionId.equals(CMD_ROW_PREVIOUS) || actionId.equals(ITextEditorActionDefinitionIds.WORD_PREVIOUS)) { - resultSet.scrollToRow(ResultSetViewer.RowPosition.PREVIOUS); + resultSet.getActivePresentation().scrollToRow(IResultSetPresentation.RowPosition.PREVIOUS); } else if (actionId.equals(CMD_ROW_NEXT) || actionId.equals(ITextEditorActionDefinitionIds.WORD_NEXT)) { - resultSet.scrollToRow(ResultSetViewer.RowPosition.NEXT); + resultSet.getActivePresentation().scrollToRow(IResultSetPresentation.RowPosition.NEXT); } else if (actionId.equals(CMD_ROW_FIRST) || actionId.equals(ITextEditorActionDefinitionIds.SELECT_WORD_PREVIOUS)) { - resultSet.scrollToRow(ResultSetViewer.RowPosition.FIRST); + resultSet.getActivePresentation().scrollToRow(IResultSetPresentation.RowPosition.FIRST); } else if (actionId.equals(CMD_ROW_LAST) || actionId.equals(ITextEditorActionDefinitionIds.SELECT_WORD_NEXT)) { - resultSet.scrollToRow(ResultSetViewer.RowPosition.LAST); + resultSet.getActivePresentation().scrollToRow(IResultSetPresentation.RowPosition.LAST); } else if (actionId.equals(CMD_ROW_EDIT)) { - resultSet.showCellEditor(false); + resultSet.getActivePresentation().openValueEditor(false); } else if (actionId.equals(CMD_ROW_EDIT_INLINE)) { - resultSet.showCellEditor(true); + resultSet.getActivePresentation().openValueEditor(true); } else if (actionId.equals(CMD_ROW_ADD)) { resultSet.addNewRow(false); } else if (actionId.equals(CMD_ROW_COPY)) { @@ -87,13 +83,18 @@ public class ResultSetCommandHandler extends AbstractHandler { } else if (actionId.equals(CMD_REJECT_CHANGES)) { resultSet.rejectChanges(); } else if (actionId.equals(IWorkbenchCommandConstants.EDIT_COPY)) { - resultSet.copySelectionToClipboard(false, false, false, null, DBDDisplayFormat.EDIT); + ResultSetUtils.copyToClipboard( + resultSet.getActivePresentation().copySelectionToString( + false, false, false, null, DBDDisplayFormat.EDIT)); } else if (actionId.equals(IWorkbenchCommandConstants.EDIT_PASTE)) { - resultSet.pasteCellValue(); + resultSet.getActivePresentation().pasteFromClipboard(); } else if (actionId.equals(IWorkbenchCommandConstants.EDIT_CUT)) { - resultSet.copySelectionToClipboard(false, false, true, null, DBDDisplayFormat.EDIT); + ResultSetUtils.copyToClipboard( + resultSet.getActivePresentation().copySelectionToString( + false, false, true, null, DBDDisplayFormat.EDIT) + ); } else if (actionId.equals(ITextEditorActionDefinitionIds.SMART_ENTER)) { - resultSet.showCellEditor(false); + resultSet.getActivePresentation().openValueEditor(false); } diff --git a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/ResultSetCopySpecialHandler.java b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/ResultSetCopySpecialHandler.java index e4cde72cc01d90e75cfdebcc376023584ac0161a..582158a60b644abf065a2440b3509d4490dae716 100644 --- a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/ResultSetCopySpecialHandler.java +++ b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/ResultSetCopySpecialHandler.java @@ -52,12 +52,12 @@ public class ResultSetCopySpecialHandler extends ResultSetCommandHandler impleme if (event.getCommand().getId().equals(ICommandIds.CMD_COPY_SPECIAL)) { ConfigDialog configDialog = new ConfigDialog(HandlerUtil.getActiveShell(event)); if (configDialog.open() == IDialogConstants.OK_ID) { - resultSet.copySelectionToClipboard( + ResultSetUtils.copyToClipboard(resultSet.getActivePresentation().copySelectionToString( configDialog.copyHeader, configDialog.copyRows, false, configDialog.delimiter, - configDialog.format); + configDialog.format)); } } return null; diff --git a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/ResultSetDataPumpJob.java b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/ResultSetDataPumpJob.java index f5625a78f24e309cf642a6a64a58e2a69d44e9f9..d65b0519703b6d50ad97df1dac0a56416feade09 100644 --- a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/ResultSetDataPumpJob.java +++ b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/ResultSetDataPumpJob.java @@ -178,10 +178,10 @@ class ResultSetDataPumpJob extends DataSourceJob { return Status.OK_STATUS; } - private void showProgress(final Composite spreadsheet) { + private void showProgress(final Composite progressPlaceholder) { if (progressOverlay == null) { // Start progress visualization - cancelButton = new Button(spreadsheet, SWT.PUSH); + cancelButton = new Button(progressPlaceholder, SWT.PUSH); cancelButton.setText("Cancel"); GridData gd = new GridData(GridData.FILL_BOTH); gd.verticalIndent = DBIcon.PROGRESS0.getImage().getBounds().height * 2; @@ -221,18 +221,18 @@ class ResultSetDataPumpJob extends DataSourceJob { int statusX = (buttonBounds.x + buttonBounds.width / 2) - statusSize.x / 2; int statusY = buttonBounds.y - imageBounds.height - 10 - statusSize.y; - e.gc.setForeground(spreadsheet.getForeground()); - e.gc.setBackground(spreadsheet.getBackground()); + e.gc.setForeground(progressPlaceholder.getForeground()); + e.gc.setBackground(progressPlaceholder.getBackground()); e.gc.fillRectangle(statusX - 2, statusY - 2, statusSize.x + 4, statusSize.y + 4); e.gc.drawText(status, statusX, statusY, true); } }; - spreadsheet.addPaintListener(painListener); + progressPlaceholder.addPaintListener(painListener); - progressOverlay = new ControlEditor(spreadsheet) { + progressOverlay = new ControlEditor(progressPlaceholder) { @Override public void layout() { - spreadsheet.redraw(); + progressPlaceholder.redraw(); super.layout(); } }; diff --git a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/ResultSetModel.java b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/ResultSetModel.java index f44f95a06ccbe9684ca9d4ba95e68bc8ecd400fd..2d61d7f4ff1cb7ee1d486514f28fbe9e88ba4377 100644 --- a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/ResultSetModel.java +++ b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/ResultSetModel.java @@ -510,7 +510,7 @@ public class ResultSetModel { } } - boolean isColumnReadOnly(@NotNull DBDAttributeBinding column) + public boolean isColumnReadOnly(@NotNull DBDAttributeBinding column) { if (column.getMetaAttribute().isReadOnly()) { return true; @@ -673,7 +673,7 @@ public class ResultSetModel { this.dataFilter.setAnyConstraint(filter.isAnyConstraint()); } - void resetOrdering() + public void resetOrdering() { final boolean hasOrdering = dataFilter.hasOrdering(); // Sort locally diff --git a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/ResultSetPersister.java b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/ResultSetPersister.java index 99725e5c2902ebe79abde11f7f970f252cc5e26c..5513f6d27b9f804554d2a95c2a11836671d40907 100644 --- a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/ResultSetPersister.java +++ b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/ResultSetPersister.java @@ -219,10 +219,10 @@ class ResultSetPersister { } model.refreshChangeCount(); - viewer.refreshSpreadsheet(rowsChanged); + viewer.redrawData(rowsChanged); viewer.fireResultSetChange(); viewer.updateEditControls(); - viewer.previewValue(); + viewer.getActivePresentation().updateValueView(); } // Reflect data changes in viewer @@ -330,7 +330,7 @@ class ResultSetPersister { } if (!viewer.getControl().isDisposed()) { //releaseStatements(); - viewer.refreshSpreadsheet(rowsChanged); + viewer.redrawData(rowsChanged); viewer.updateEditControls(); if (error == null) { viewer.setStatus( diff --git a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/ResultSetPropertyTester.java b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/ResultSetPropertyTester.java index 21f8824dee5ae3cd5346c219726fb0d34984169b..e4c6e729815ef9ef4068d5145f291ba757b5ed1f 100644 --- a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/ResultSetPropertyTester.java +++ b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/ResultSetPropertyTester.java @@ -52,9 +52,9 @@ public class ResultSetPropertyTester extends PropertyTester } else if (PROP_HAS_DATA.equals(property)) { return rsv.getModel().getRowCount() > 0; } else if (PROP_CAN_COPY.equals(property)) { - return rsv.getFocusAttribute() != null && rsv.getFocusRow() != null; + return rsv.getActivePresentation().getCurrentAttribute() != null && rsv.getCurrentRow() != null; } else if (PROP_CAN_PASTE.equals(property) || PROP_CAN_CUT.equals(property)) { - DBDAttributeBinding attr = rsv.getFocusAttribute(); + DBDAttributeBinding attr = rsv.getActivePresentation().getCurrentAttribute(); return attr != null && !rsv.isColumnReadOnly(attr); } else if (PROP_CAN_MOVE.equals(property)) { ResultSetRow currentRow = rsv.getCurrentRow(); @@ -68,7 +68,7 @@ public class ResultSetPropertyTester extends PropertyTester return false; } if ("edit".equals(expectedValue) || "inline".equals(expectedValue)) { - DBDAttributeBinding attr = rsv.getFocusAttribute(); + DBDAttributeBinding attr = rsv.getActivePresentation().getCurrentAttribute(); if (attr == null) { return false; } diff --git a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/ResultSetRow.java b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/ResultSetRow.java index b3e3378336c6eac6c3aaf59665f1a0e5db5cb444..348e31167f707220640a6949155336cf5d36e15b 100644 --- a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/ResultSetRow.java +++ b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/ResultSetRow.java @@ -34,9 +34,9 @@ import java.util.Map; */ public class ResultSetRow { - static final byte STATE_NORMAL = 1; - static final byte STATE_ADDED = 2; - static final byte STATE_REMOVED = 3; + public static final byte STATE_NORMAL = 1; + public static final byte STATE_ADDED = 2; + public static final byte STATE_REMOVED = 3; // Physical row number private int rowNumber; @@ -118,7 +118,7 @@ public class ResultSetRow { } @NotNull - CollectionElementData getCollectionData(DBDAttributeBinding binding, DBDCollection collection) { + public CollectionElementData getCollectionData(DBDAttributeBinding binding, DBDCollection collection) { if (collections == null) { collections = new HashMap(); } diff --git a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/ResultSetUtils.java b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/ResultSetUtils.java index e1e7f2cd4bd64260aa5a69482f43665c381044fe..b995597364e196ab3b1a82e7b0e4174b56738981 100644 --- a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/ResultSetUtils.java +++ b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/ResultSetUtils.java @@ -19,14 +19,18 @@ package org.jkiss.dbeaver.ui.controls.resultset; +import org.eclipse.swt.dnd.Clipboard; +import org.eclipse.swt.dnd.TextTransfer; +import org.eclipse.swt.dnd.Transfer; +import org.eclipse.swt.widgets.Display; import org.jkiss.code.NotNull; +import org.jkiss.code.Nullable; import org.jkiss.dbeaver.DBException; import org.jkiss.dbeaver.core.Log; +import org.jkiss.dbeaver.model.DBPDataSource; import org.jkiss.dbeaver.model.DBUtils; import org.jkiss.dbeaver.model.data.*; -import org.jkiss.dbeaver.model.exec.DBCAttributeMetaData; -import org.jkiss.dbeaver.model.exec.DBCEntityMetaData; -import org.jkiss.dbeaver.model.exec.DBCSession; +import org.jkiss.dbeaver.model.exec.*; import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor; import org.jkiss.dbeaver.model.sql.SQLQuery; import org.jkiss.dbeaver.model.struct.*; @@ -35,6 +39,7 @@ import org.jkiss.dbeaver.model.struct.rdb.DBSTable; import org.jkiss.dbeaver.model.struct.rdb.DBSTableIndex; import org.jkiss.dbeaver.model.virtual.DBVEntity; import org.jkiss.dbeaver.model.virtual.DBVEntityConstraint; +import org.jkiss.dbeaver.runtime.VoidProgressMonitor; import org.jkiss.utils.CommonUtils; import java.util.*; @@ -42,7 +47,7 @@ import java.util.*; /** * Utils */ -class ResultSetUtils +public class ResultSetUtils { static final Log log = Log.getLog(ResultSetUtils.class); @@ -248,4 +253,35 @@ class ResultSetUtils attr1.getTypeID() == attr2.getTypeID() && CommonUtils.equalObjects(attr1.getTypeName(), attr2.getTypeName()); } + + @Nullable + public static Object getColumnValueFromClipboard(DBDAttributeBinding metaColumn) throws DBCException + { + DBPDataSource dataSource = metaColumn.getDataSource(); + DBCSession session = dataSource.openSession(VoidProgressMonitor.INSTANCE, DBCExecutionPurpose.UTIL, "Copy from clipboard"); + Clipboard clipboard = new Clipboard(Display.getCurrent()); + try { + String strValue = (String) clipboard.getContents(TextTransfer.getInstance()); + return metaColumn.getValueHandler().getValueFromObject( + session, metaColumn.getAttribute(), strValue, true); + } finally { + session.close(); + clipboard.dispose(); + } + } + + public static void copyToClipboard(String string) { + if (string.length() > 0) { + Clipboard clipboard = new Clipboard(Display.getCurrent()); + try { + TextTransfer textTransfer = TextTransfer.getInstance(); + clipboard.setContents( + new Object[]{string}, + new Transfer[]{textTransfer}); + } finally { + clipboard.dispose(); + } + } + } + } diff --git a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/ResultSetValueController.java b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/ResultSetValueController.java new file mode 100644 index 0000000000000000000000000000000000000000..280d87b145a3c7427eab7654722f59b4f2ce4ade --- /dev/null +++ b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/ResultSetValueController.java @@ -0,0 +1,213 @@ +/* + * Copyright (C) 2010-2015 Serge Rieder + * serge@jkiss.org + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package org.jkiss.dbeaver.ui.controls.resultset; + +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.ToolBar; +import org.eclipse.ui.IWorkbenchPartSite; +import org.jkiss.code.NotNull; +import org.jkiss.code.Nullable; +import org.jkiss.dbeaver.model.DBPDataSource; +import org.jkiss.dbeaver.model.DBUtils; +import org.jkiss.dbeaver.model.data.*; +import org.jkiss.dbeaver.model.exec.DBCAttributeMetaData; +import org.jkiss.dbeaver.model.struct.DBSDataContainer; +import org.jkiss.dbeaver.model.struct.DBSTypedObject; + +import java.util.Arrays; +import java.util.List; + +/** +* ResultSetValueController +*/ +public class ResultSetValueController implements DBDAttributeController, DBDRowController { + + protected final IResultSetController controller; + protected final EditType editType; + protected final Composite inlinePlaceholder; + protected ResultSetRow curRow; + protected final DBDAttributeBinding binding; + + public ResultSetValueController( + @NotNull IResultSetController controller, + @NotNull DBDAttributeBinding binding, + @NotNull ResultSetRow row, + @NotNull EditType editType, + @Nullable Composite inlinePlaceholder) + { + this.controller = controller; + this.binding = binding; + this.curRow = row; + this.editType = editType; + this.inlinePlaceholder = inlinePlaceholder; + } + + public ResultSetRow getCurRow() { + return curRow; + } + + public void setCurRow(ResultSetRow curRow) + { + this.curRow = curRow; + } + + @Nullable + @Override + public DBPDataSource getDataSource() + { + DBSDataContainer dataContainer = controller.getDataContainer(); + return dataContainer == null ? null : dataContainer.getDataSource(); + } + + @Override + public String getValueName() + { + return binding.getName(); + } + + @Override + public DBSTypedObject getValueType() + { + return binding.getMetaAttribute(); + } + + @NotNull + @Override + public DBDRowController getRowController() { + return this; + } + + @NotNull + @Override + public DBDAttributeBinding getBinding() + { + return binding; + } + + @NotNull + @Override + public String getColumnId() { + DBPDataSource dataSource = getDataSource(); + DBCAttributeMetaData metaAttribute = binding.getMetaAttribute(); + return DBUtils.getSimpleQualifiedName( + dataSource == null ? null : dataSource.getContainer().getName(), + metaAttribute.getEntityName(), + metaAttribute.getName()); + } + + @Override + public Object getValue() + { + return controller.getModel().getCellValue(binding, curRow); + } + + @Override + public void updateValue(@Nullable Object value) + { + if (controller.getModel().updateCellValue(binding, curRow, value)) { + // Update controls + controller.getSite().getShell().getDisplay().syncExec(new Runnable() { + @Override + public void run() { + controller.updateValueView(); + } + }); + } + controller.fireResultSetChange(); + } + + @Nullable + @Override + public DBDRowIdentifier getRowIdentifier() + { + return binding.getRowIdentifier(); + } + + @Override + public DBDValueHandler getValueHandler() + { + return binding.getValueHandler(); + } + + @Override + public EditType getEditType() + { + return editType; + } + + @Override + public boolean isReadOnly() + { + return controller.isColumnReadOnly(binding); + } + + @Override + public IWorkbenchPartSite getValueSite() + { + return controller.getSite(); + } + + @Nullable + @Override + public Composite getEditPlaceholder() + { + return inlinePlaceholder; + } + + @Nullable + @Override + public ToolBar getEditToolBar() + { + return null; + } + + @Override + public void closeInlineEditor() + { + } + + @Override + public void nextInlineEditor(boolean next) { + } + + @Override + public void unregisterEditor(DBDValueEditorStandalone editor) { + } + + @Override + public void showMessage(String message, boolean error) + { + controller.setStatus(message, error); + } + + @NotNull + @Override + public List getRowAttributes() + { + return Arrays.asList(controller.getModel().getColumns()); + } + + @Nullable + @Override + public Object getAttributeValue(DBDAttributeBinding attribute) + { + return controller.getModel().getCellValue(attribute, curRow); + } + +} diff --git a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/ResultSetViewer.java b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/ResultSetViewer.java index a04930c3b28d4d1f770869608f8f05054de66659..60a135d182354c5145cf11ab39e9acc394281bb3 100644 --- a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/ResultSetViewer.java +++ b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/ResultSetViewer.java @@ -20,8 +20,6 @@ package org.jkiss.dbeaver.ui.controls.resultset; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.IJobChangeEvent; import org.eclipse.core.runtime.jobs.JobChangeAdapter; import org.eclipse.jface.action.*; @@ -29,18 +27,15 @@ import org.eclipse.jface.dialogs.ControlEnableState; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.resource.ImageDescriptor; -import org.eclipse.jface.text.IFindReplaceTarget; -import org.eclipse.jface.util.IPropertyChangeListener; -import org.eclipse.jface.util.PropertyChangeEvent; -import org.eclipse.jface.viewers.*; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionProvider; +import org.eclipse.jface.viewers.Viewer; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.SWT; -import org.eclipse.swt.custom.SashForm; -import org.eclipse.swt.dnd.TextTransfer; -import org.eclipse.swt.dnd.Transfer; import org.eclipse.swt.events.*; -import org.eclipse.swt.graphics.*; -import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; @@ -49,12 +44,6 @@ import org.eclipse.ui.IWorkbenchCommandConstants; import org.eclipse.ui.IWorkbenchPartSite; import org.eclipse.ui.commands.ICommandService; import org.eclipse.ui.menus.CommandContributionItem; -import org.eclipse.ui.progress.UIJob; -import org.eclipse.ui.themes.ITheme; -import org.eclipse.ui.themes.IThemeManager; -import org.eclipse.ui.views.properties.IPropertySheetPage; -import org.eclipse.ui.views.properties.IPropertySource; -import org.eclipse.ui.views.properties.IPropertySourceProvider; import org.jkiss.code.NotNull; import org.jkiss.code.Nullable; import org.jkiss.dbeaver.DBException; @@ -64,7 +53,6 @@ import org.jkiss.dbeaver.core.DBeaverCore; import org.jkiss.dbeaver.core.DBeaverUI; import org.jkiss.dbeaver.core.Log; import org.jkiss.dbeaver.ext.IDataSourceProvider; -import org.jkiss.dbeaver.model.DBPDataKind; import org.jkiss.dbeaver.model.DBPDataSource; import org.jkiss.dbeaver.model.DBUtils; import org.jkiss.dbeaver.model.data.*; @@ -83,12 +71,6 @@ import org.jkiss.dbeaver.tools.transfer.database.DatabaseTransferProducer; import org.jkiss.dbeaver.tools.transfer.wizard.DataTransferWizard; import org.jkiss.dbeaver.ui.*; import org.jkiss.dbeaver.ui.controls.CImageCombo; -import org.jkiss.dbeaver.ui.controls.PropertyPageStandard; -import org.jkiss.dbeaver.ui.controls.lightgrid.GridCell; -import org.jkiss.dbeaver.ui.controls.lightgrid.GridPos; -import org.jkiss.dbeaver.ui.controls.lightgrid.IGridContentProvider; -import org.jkiss.dbeaver.ui.controls.lightgrid.IGridLabelProvider; -import org.jkiss.dbeaver.ui.controls.resultset.spreadsheet.Spreadsheet; import org.jkiss.dbeaver.ui.controls.resultset.spreadsheet.SpreadsheetPresentation; import org.jkiss.dbeaver.ui.dialogs.ActiveWizardDialog; import org.jkiss.dbeaver.ui.dialogs.ConfirmationDialog; @@ -96,8 +78,6 @@ import org.jkiss.dbeaver.ui.dialogs.EditTextDialog; import org.jkiss.dbeaver.ui.dialogs.sql.ViewSQLDialog; import org.jkiss.dbeaver.ui.dialogs.struct.EditConstraintDialog; import org.jkiss.dbeaver.ui.preferences.PrefPageDatabaseGeneral; -import org.jkiss.dbeaver.ui.properties.PropertyCollector; -import org.jkiss.dbeaver.utils.ContentUtils; import org.jkiss.utils.CommonUtils; import java.lang.reflect.InvocationTargetException; @@ -121,16 +101,6 @@ public class ResultSetViewer extends Viewer { static final Log log = Log.getLog(ResultSetViewer.class); - private static final String VIEW_PANEL_VISIBLE = "viewPanelVisible"; - private static final String VIEW_PANEL_RATIO = "viewPanelRatio"; - - public enum RowPosition { - FIRST, - PREVIOUS, - NEXT, - LAST - } - public static class StateItem { DBSDataContainer dataContainer; DBDDataFilter filter; @@ -165,44 +135,20 @@ public class ResultSetViewer extends Viewer private IResultSetPresentation activePresentation; private List presentations; - private final SashForm resultsSash; - private final Spreadsheet spreadsheet; - private final ViewValuePanel previewPane; - private ResultSetValueController panelValueController; - @NotNull private final IResultSetContainer resultSetProvider; @NotNull private final ResultSetDataReceiver dataReceiver; - @NotNull - private final IThemeManager themeManager; - private final IPropertyChangeListener themeChangeListener; private ToolBarManager toolBarManager; // Current row/col number @Nullable private ResultSetRow curRow; - @Nullable - private DBDAttributeBinding curAttribute; // Mode private boolean recordMode; - private int columnOrder = SWT.NONE; - private final Map openEditors = new HashMap(); private final List listeners = new ArrayList(); - // UI modifiers - private final Color colorRed; - private Color backgroundAdded; - private Color backgroundDeleted; - private Color backgroundModified; - private Color backgroundNormal; - private Color backgroundOdd; - private Color backgroundReadOnly; - private Color foregroundDefault; - private Color foregroundNull; - private final Font boldFont; - private volatile ResultSetDataPumpJob dataPumpJob; private final ResultSetModel model = new ResultSetModel(); @@ -210,14 +156,13 @@ public class ResultSetViewer extends Viewer private final List stateHistory = new ArrayList(); private int historyPosition = -1; - private boolean showOddRows = true; - private boolean showCelIcons = true; - private ToolItem filtersApplyButton; private ToolItem filtersClearButton; private ToolItem historyBackButton; private ToolItem historyForwardButton; + private final Color colorRed; + public ResultSetViewer(@NotNull Composite parent, @NotNull IWorkbenchPartSite site, @NotNull IResultSetContainer resultSetProvider) { super(); @@ -228,108 +173,22 @@ public class ResultSetViewer extends Viewer this.dataReceiver = new ResultSetDataReceiver(this); this.colorRed = Display.getDefault().getSystemColor(SWT.COLOR_RED); - this.boldFont = UIUtils.makeBoldFont(parent.getFont()); - this.foregroundNull = getSite().getShell().getDisplay().getSystemColor(SWT.COLOR_GRAY); this.viewerPanel = UIUtils.createPlaceholder(parent, 1); UIUtils.setHelp(this.viewerPanel, IHelpContextIds.CTX_RESULT_SET_VIEWER); createFiltersPanel(); this.activePresentation = new SpreadsheetPresentation(); - - { - resultsSash = new SashForm(viewerPanel, SWT.HORIZONTAL | SWT.SMOOTH); - resultsSash.setBackgroundMode(SWT.INHERIT_FORCE); - resultsSash.setLayoutData(new GridData(GridData.FILL_BOTH)); - resultsSash.setSashWidth(5); - //resultsSash.setBackground(resultsSash.getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND)); - - this.spreadsheet = new Spreadsheet( - resultsSash, - SWT.MULTI | SWT.VIRTUAL | SWT.H_SCROLL | SWT.V_SCROLL, - site, - (SpreadsheetPresentation) this.activePresentation, - new ContentProvider(), - new GridLabelProvider()); - this.spreadsheet.setLayoutData(new GridData(GridData.FILL_BOTH)); - - this.previewPane = new ViewValuePanel(resultsSash) { - @Override - protected void hidePanel() - { - togglePreview(); - } - }; - - final IPreferenceStore preferences = getPreferenceStore(); - int ratio = preferences.getInt(VIEW_PANEL_RATIO); - boolean viewPanelVisible = preferences.getBoolean(VIEW_PANEL_VISIBLE); - if (ratio <= 0) { - ratio = 750; - } - resultsSash.setWeights(new int[]{ratio, 1000 - ratio}); - if (!viewPanelVisible) { - resultsSash.setMaximizedControl(spreadsheet); - } - previewPane.addListener(SWT.Resize, new Listener() { - @Override - public void handleEvent(Event event) - { - DBPDataSource dataSource = getDataSource(); - if (dataSource != null) { - if (!resultsSash.isDisposed()) { - int[] weights = resultsSash.getWeights(); - int ratio = weights[0]; - preferences.setValue(VIEW_PANEL_RATIO, ratio); - } - } - } - }); - } - this.activePresentation.createPresentation(this, viewerPanel); createStatusBar(viewerPanel); - this.themeManager = site.getWorkbenchWindow().getWorkbench().getThemeManager(); - this.themeChangeListener = new IPropertyChangeListener() { - @Override - public void propertyChange(PropertyChangeEvent event) { - if (event.getProperty().startsWith(ThemeConstants.RESULTS_PROP_PREFIX)) { - applyThemeSettings(); - } - } - }; - this.themeManager.addPropertyChangeListener(themeChangeListener); this.viewerPanel.addDisposeListener(new DisposeListener() { @Override - public void widgetDisposed(DisposeEvent e) - { + public void widgetDisposed(DisposeEvent e) { dispose(); } }); - this.spreadsheet.addCursorChangeListener(new Listener() { - @Override - public void handleEvent(Event event) - { - if (event.detail != SWT.DRAG && event.detail != SWT.DROP_DOWN) { - updateGridCursor((GridCell)event.data); - } - } - }); - applyThemeSettings(); - - spreadsheet.addFocusListener(new FocusListener() { - @Override - public void focusGained(FocusEvent e) { - updateToolbar(); - } - - @Override - public void focusLost(FocusEvent e) { - updateToolbar(); - } - }); changeMode(false); } @@ -516,7 +375,7 @@ public class ResultSetViewer extends Viewer DBDDataFilter newFilter = model.createDataFilter(); newFilter.setWhere(condition); setDataFilter(newFilter, true); - spreadsheet.setFocus(); + viewerPanel.setFocus(); } public void updateFiltersText() @@ -594,18 +453,10 @@ public class ResultSetViewer extends Viewer { if (!model.getDataFilter().equalFilters(dataFilter)) { if (model.setDataFilter(dataFilter)) { - refreshSpreadsheet(true); + redrawData(true); } if (refreshData) { - reorderResultSet(true, new Runnable() { - @Override - public void run() - { - if (!recordMode) { - spreadsheet.refreshData(false); - } - } - }); + activePresentation.formatData(true); } else { updateFiltersText(); } @@ -625,6 +476,21 @@ public class ResultSetViewer extends Viewer return DBeaverCore.getGlobalPreferenceStore(); } + @Override + public Color getDefaultBackground() { + return filtersText.getBackground(); + } + + @Override + public Color getDefaultForeground() { + return filtersText.getForeground(); + } + + @Override + public IResultSetPresentation getActivePresentation() { + return activePresentation; + } + @Nullable @Override public DBPDataSource getDataSource() @@ -637,37 +503,8 @@ public class ResultSetViewer extends Viewer @Override public Object getAdapter(Class adapter) { - if (adapter == IPropertySheetPage.class) { - // Show cell properties - PropertyPageStandard page = new PropertyPageStandard(); - page.setPropertySourceProvider(new IPropertySourceProvider() { - @Nullable - @Override - public IPropertySource getPropertySource(Object object) - { - if (object instanceof GridCell) { - GridCell cell = (GridCell) object; - final DBDAttributeBinding attr = (DBDAttributeBinding)(recordMode ? cell.row : cell.col); - final ResultSetRow row = (ResultSetRow)(recordMode ? cell.col : cell.row); - final ResultSetValueController valueController = new ResultSetValueController( - ResultSetViewer.this, - attr, - row, - DBDValueController.EditType.NONE, - null); - PropertyCollector props = new PropertyCollector(valueController.binding.getAttribute(), false); - props.collectProperties(); - valueController.getValueHandler().contributeProperties(props, valueController); - return props; - } - return null; - } - }); - return page; - } else if (adapter == IFindReplaceTarget.class) { - if (activePresentation instanceof IFindReplaceTarget) { - return activePresentation; - } + if (adapter.isAssignableFrom(activePresentation.getClass())) { + return activePresentation; } // Try to get it from adapter if (activePresentation instanceof IAdaptable) { @@ -690,44 +527,16 @@ public class ResultSetViewer extends Viewer } } - private void updateGridCursor(GridCell cell) - { - boolean changed; - Object newCol = cell == null ? null : cell.col; - Object newRow = cell == null ? null : cell.row; - if (!recordMode) { - changed = curRow != newRow || curAttribute != newCol; - if (newRow instanceof ResultSetRow && newCol instanceof DBDAttributeBinding) { - curRow = (ResultSetRow) newRow; - curAttribute = (DBDAttributeBinding) newCol; - } - } else { - changed = curAttribute != newRow; - if (newRow instanceof DBDAttributeBinding) { - curAttribute = (DBDAttributeBinding) newRow; - } - } - if (curState != null && curRow != null) { - curState.rowNumber = curRow.getVisualNumber(); - } - if (changed) { - ResultSetPropertyTester.firePropertyChange(ResultSetPropertyTester.PROP_CAN_MOVE); - ResultSetPropertyTester.firePropertyChange(ResultSetPropertyTester.PROP_EDITABLE); - updateValueView(); - } - } - private void updateRecordMode() { - DBDAttributeBinding oldAttr = this.curAttribute; - this.initResultSet(); - this.curAttribute = oldAttr; - if (curRow != null && oldAttr != null) { - spreadsheet.setCursor(new GridCell(curRow, oldAttr), false); - } + //Object state = savePresentationState(); + //this.redrawData(false); + activePresentation.refreshData(true); + this.updateStatusMessage(); + //restorePresentationState(state); } - void updateEditControls() + public void updateEditControls() { ResultSetPropertyTester.firePropertyChange(ResultSetPropertyTester.PROP_EDITABLE); ResultSetPropertyTester.firePropertyChange(ResultSetPropertyTester.PROP_CHANGED); @@ -749,9 +558,9 @@ public class ResultSetViewer extends Viewer } } - void refreshSpreadsheet(boolean rowsChanged) + public void redrawData(boolean rowsChanged) { - if (spreadsheet.isDisposed()) { + if (viewerPanel.isDisposed()) { return; } if (rowsChanged) { @@ -759,20 +568,17 @@ public class ResultSetViewer extends Viewer if (curRow == null || curRow.getVisualNumber() >= rowCount) { curRow = rowCount == 0 ? null : model.getRow(rowCount - 1); } - GridCell curCell = spreadsheet.getCursorCell(); // Set cursor on new row if (!recordMode) { - this.initResultSet(); - if (curCell != null) { - spreadsheet.setCursor(curCell, false); - } + activePresentation.refreshData(false); + this.updateFiltersText(); + this.updateStatusMessage(); } else { - updateRecordMode(); + this.updateRecordMode(); } - } else { - this.spreadsheet.redrawGrid(); + activePresentation.refreshData(false); } } @@ -833,7 +639,7 @@ public class ResultSetViewer extends Viewer toolBarManager.add(refreshAction); toolBarManager.add(new Separator()); toolBarManager.add(ActionUtils.makeCommandContribution(site, ResultSetCommandHandler.CMD_TOGGLE_MODE, CommandContributionItem.STYLE_CHECK)); - toolBarManager.add(ActionUtils.makeCommandContribution(site, ResultSetCommandHandler.CMD_TOGGLE_PREVIEW, CommandContributionItem.STYLE_CHECK)); + activePresentation.fillToolbar(toolBarManager); toolBarManager.add(new ConfigAction()); toolBarManager.createControl(statusBar); @@ -841,12 +647,6 @@ public class ResultSetViewer extends Viewer //updateEditControls(); } - @NotNull - public Spreadsheet getSpreadsheet() - { - return spreadsheet; - } - @Nullable public DBSDataContainer getDataContainer() { @@ -864,6 +664,7 @@ public class ResultSetViewer extends Viewer public void toggleMode() { changeMode(!recordMode); + // Refresh elements ICommandService commandService = (ICommandService) site.getService(ICommandService.class); if (commandService != null) { @@ -873,83 +674,15 @@ public class ResultSetViewer extends Viewer private void changeMode(boolean recordMode) { - ResultSetRow oldRow = this.curRow; - DBDAttributeBinding oldAttribute = this.curAttribute; - int rowCount = model.getRowCount(); - if (rowCount > 0) { - // Fix row number if needed - if (oldRow == null) { - oldRow = this.curRow = model.getRow(0); - } else if (oldRow.getVisualNumber() >= rowCount) { - oldRow = this.curRow = model.getRow(rowCount - 1); - } - } - if (oldAttribute == null && model.getVisibleColumnCount() > 0) { - oldAttribute = model.getVisibleColumn(0); - } + //Object state = savePresentationState(); this.recordMode = recordMode; + //redrawData(false); + activePresentation.refreshData(true); activePresentation.changeMode(recordMode); - - this.columnOrder = recordMode ? SWT.DEFAULT : SWT.NONE; - if (!this.recordMode) { - this.initResultSet(); - } else { - this.updateRecordMode(); - } - if (oldRow != null && oldAttribute != null) { - if (!recordMode) { - spreadsheet.setCursor(new GridCell(oldAttribute, oldRow), false); - } else { - spreadsheet.setCursor(new GridCell(oldRow, oldAttribute), false); - } - } - spreadsheet.layout(true, true); - previewValue(); - } - - //////////////////////////////////////////////////////////// - // Value preview - - public boolean isPreviewVisible() - { - return resultsSash.getMaximizedControl() == null; - } - - public void togglePreview() - { - if (resultsSash.getMaximizedControl() == null) { - resultsSash.setMaximizedControl(spreadsheet); - } else { - resultsSash.setMaximizedControl(null); - previewValue(); - } - getPreferenceStore().setValue(VIEW_PANEL_VISIBLE, isPreviewVisible()); - - // Refresh elements - ICommandService commandService = (ICommandService) site.getService(ICommandService.class); - if (commandService != null) { - commandService.refreshElements(ResultSetCommandHandler.CMD_TOGGLE_PREVIEW, null); - } - } - - void previewValue() - { - DBDAttributeBinding attr = getFocusAttribute(); - ResultSetRow row = getFocusRow(); - if (!isPreviewVisible() || attr == null || row == null) { - return; - } - if (panelValueController == null || panelValueController.binding != attr) { - panelValueController = new ResultSetValueController( - this, - attr, - row, - DBDValueController.EditType.PANEL, - previewPane.getViewPlaceholder()); - } else { - panelValueController.setCurRow(row); + if (!recordMode) { + updateStatusMessage(); } - previewPane.viewValue(panelValueController); + //restorePresentationState(state); } //////////////////////////////////////////////////////////// @@ -957,12 +690,8 @@ public class ResultSetViewer extends Viewer private void dispose() { - closeEditors(); clearData(); - themeManager.removePropertyChangeListener(themeChangeListener); - - UIUtils.dispose(this.boldFont); if (toolBarManager != null) { try { toolBarManager.dispose(); @@ -973,73 +702,7 @@ public class ResultSetViewer extends Viewer } } - private void applyThemeSettings() - { - ITheme currentTheme = themeManager.getCurrentTheme(); - Font rsFont = currentTheme.getFontRegistry().get(ThemeConstants.FONT_SQL_RESULT_SET); - if (rsFont != null) { - this.spreadsheet.setFont(rsFont); - } - Color previewBack = currentTheme.getColorRegistry().get(ThemeConstants.COLOR_SQL_RESULT_SET_PREVIEW_BACK); - if (previewBack != null) { - this.previewPane.getViewPlaceholder().setBackground(previewBack); - for (Control control : this.previewPane.getViewPlaceholder().getChildren()) { - control.setBackground(previewBack); - } - } - this.backgroundAdded = currentTheme.getColorRegistry().get(ThemeConstants.COLOR_SQL_RESULT_CELL_NEW_BACK); - this.backgroundDeleted = currentTheme.getColorRegistry().get(ThemeConstants.COLOR_SQL_RESULT_CELL_DELETED_BACK); - this.backgroundModified = currentTheme.getColorRegistry().get(ThemeConstants.COLOR_SQL_RESULT_CELL_MODIFIED_BACK); - this.backgroundOdd = currentTheme.getColorRegistry().get(ThemeConstants.COLOR_SQL_RESULT_CELL_ODD_BACK); - this.backgroundReadOnly = currentTheme.getColorRegistry().get(ThemeConstants.COLOR_SQL_RESULT_CELL_READ_ONLY); - - this.spreadsheet.recalculateSizes(); - } - - void scrollToRow(RowPosition position) - { - switch (position) { - case FIRST: - if (recordMode) { - if (model.getRowCount() > 0) { - curRow = model.getRow(0); - } else { - curRow = null; - } - updateRecordMode(); - } else { - spreadsheet.shiftCursor(0, -spreadsheet.getItemCount(), false); - } - break; - case PREVIOUS: - if (recordMode && curRow != null && curRow.getVisualNumber() > 0) { - curRow = model.getRow(curRow.getVisualNumber() - 1); - updateRecordMode(); - } else { - spreadsheet.shiftCursor(0, -1, false); - } - break; - case NEXT: - if (recordMode && curRow != null && curRow.getVisualNumber() < model.getRowCount() - 1) { - curRow = model.getRow(curRow.getVisualNumber() + 1); - updateRecordMode(); - } else { - spreadsheet.shiftCursor(0, 1, false); - } - break; - case LAST: - if (recordMode && model.getRowCount() > 0) { - curRow = model.getRow(model.getRowCount() - 1); - updateRecordMode(); - } else { - spreadsheet.shiftCursor(0, spreadsheet.getItemCount(), false); - } - break; - } - updateToolbar(); - } - - boolean isColumnReadOnly(DBDAttributeBinding column) + public boolean isColumnReadOnly(DBDAttributeBinding column) { if (isReadOnly()) { return true; @@ -1051,6 +714,20 @@ public class ResultSetViewer extends Viewer return !newRow; } + private Object savePresentationState() { + if (activePresentation instanceof IStatefulControl) { + return ((IStatefulControl) activePresentation).saveState(); + } else { + return null; + } + } + + private void restorePresentationState(Object state) { + if (activePresentation instanceof IStatefulControl) { + ((IStatefulControl) activePresentation).restoreState(state); + } + } + /////////////////////////////////////// // History @@ -1107,20 +784,15 @@ public class ResultSetViewer extends Viewer return curRow; } - @Nullable - public DBDAttributeBinding getFocusAttribute() - { - return recordMode ? - (DBDAttributeBinding) spreadsheet.getFocusRowElement() : - (DBDAttributeBinding) spreadsheet.getFocusColumnElement(); - } - - @Nullable - public ResultSetRow getFocusRow() - { - return recordMode ? - (ResultSetRow) spreadsheet.getFocusColumnElement() : - (ResultSetRow) spreadsheet.getFocusRowElement(); + @Override + public void setCurrentRow(@Nullable ResultSetRow curRow) { + this.curRow = curRow; + if (curState != null && curRow != null) { + curState.rowNumber = curRow.getVisualNumber(); + } + if (recordMode) { + updateRecordMode(); + } } /////////////////////////////////////// @@ -1181,20 +853,16 @@ public class ResultSetViewer extends Viewer { model.setMetaData(columns); if (model.isMetadataChanged()) { - this.panelValueController = null; - this.curAttribute = null; - //getSpreadsheet().set + activePresentation.clearData(); } } public void setData(List rows) { - if (spreadsheet.isDisposed()) { + if (viewerPanel.isDisposed()) { return; } boolean metaChanged = model.isMetadataChanged(); - // Clear previous data - this.closeEditors(); this.curRow = null; this.model.setData(rows); @@ -1209,49 +877,22 @@ public class ResultSetViewer extends Viewer // ResultSetPropertyTester.firePropertyChange(ResultSetPropertyTester.PROP_CAN_TOGGLE); } } - - this.initResultSet(); - } else { - this.refreshSpreadsheet(true); } - updateEditControls(); + this.redrawData(true); + this.updateEditControls(); } public void appendData(List rows) { model.appendData(rows); - //refreshSpreadsheet(true); - spreadsheet.refreshData(false); + //redrawData(true); + activePresentation.refreshData(false); setStatus(NLS.bind(CoreMessages.controls_resultset_viewer_status_rows_size, model.getRowCount(), rows.size()) + getExecutionTimeMessage()); updateEditControls(); } - private void closeEditors() { - List editors = new ArrayList(openEditors.values()); - for (DBDValueEditorStandalone editor : editors) { - editor.closeValueEditor(); - } - if (!openEditors.isEmpty()) { - log.warn("Some value editors are still registered at result set: " + openEditors.size()); - } - openEditors.clear(); - } - - private void initResultSet() - { - spreadsheet.setRedraw(false); - try { - spreadsheet.refreshData(true); - } finally { - spreadsheet.setRedraw(true); - } - - this.updateFiltersText(); - this.updateStatusMessage(); - } - @Override public int promptToSaveOnClose() { @@ -1259,7 +900,7 @@ public class ResultSetViewer extends Viewer return ISaveablePart2.YES; } int result = ConfirmationDialog.showConfirmDialog( - spreadsheet.getShell(), + viewerPanel.getShell(), DBeaverPreferences.CONFIRM_RS_EDIT_CLOSE, ConfirmationDialog.QUESTION_WITH_CANCEL); if (result == IDialogConstants.YES_ID) { @@ -1307,6 +948,11 @@ public class ResultSetViewer extends Viewer return model.hasData(); } + @Override + public boolean isHasMoreData() { + return dataReceiver.isHasMoreData(); + } + @Override public boolean isReadOnly() { @@ -1337,131 +983,6 @@ public class ResultSetViewer extends Viewer return dataPumpJob != null; } - @Nullable - public Control showCellEditor(final boolean inline) - { - // The control that will be the editor must be a child of the Table - DBDAttributeBinding attr = getFocusAttribute(); - ResultSetRow row = getFocusRow(); - if (attr == null || row == null) { - return null; - } - - if (!inline) { - for (ResultSetValueController valueController : openEditors.keySet()) { - if (attr == valueController.binding && row == valueController.curRow) { - openEditors.get(valueController).showValueEditor(); - return null; - } - } - } - final int handlerFeatures = attr.getValueHandler().getFeatures(); - if (handlerFeatures == DBDValueHandler.FEATURE_NONE) { - return null; - } - if (inline && - (handlerFeatures & DBDValueHandler.FEATURE_INLINE_EDITOR) == 0 && - (handlerFeatures & DBDValueHandler.FEATURE_VIEWER) != 0) - { - // Inline editor isn't supported but panel viewer is - // Enable panel - if (!isPreviewVisible()) { - togglePreview(); - } - return null; - } - if (isColumnReadOnly(attr) && inline) { - // No inline editors for readonly columns - return null; - } - - Composite placeholder = null; - if (inline) { - if (isReadOnly()) { - return null; - } - spreadsheet.cancelInlineEditor(); - - placeholder = new Composite(spreadsheet, SWT.NONE); - placeholder.setFont(spreadsheet.getFont()); - placeholder.setLayout(new FillLayout()); - - GridData gd = new GridData(GridData.FILL_BOTH); - gd.horizontalIndent = 0; - gd.verticalIndent = 0; - gd.grabExcessHorizontalSpace = true; - gd.grabExcessVerticalSpace = true; - placeholder.setLayoutData(gd); - } - - ResultSetValueController valueController = new ResultSetValueController( - this, - attr, - row, - inline ? DBDValueController.EditType.INLINE : DBDValueController.EditType.EDITOR, - placeholder); - final DBDValueEditor editor; - try { - editor = attr.getValueHandler().createEditor(valueController); - } - catch (Exception e) { - UIUtils.showErrorDialog(site.getShell(), "Cannot edit value", null, e); - return null; - } - if (editor != null) { - editor.createControl(); - } - if (editor instanceof DBDValueEditorStandalone) { - valueController.registerEditor((DBDValueEditorStandalone)editor); - // show dialog in separate job to avoid block - new UIJob("Open separate editor") { - @Override - public IStatus runInUIThread(IProgressMonitor monitor) - { - ((DBDValueEditorStandalone)editor).showValueEditor(); - return Status.OK_STATUS; - } - }.schedule(); - //((DBDValueEditorStandalone)editor).showValueEditor(); - } else { - // Set editable value - if (editor != null) { - try { - editor.primeEditorValue(valueController.getValue()); - } catch (DBException e) { - log.error(e); - } - } - } - if (inline) { - if (editor != null) { - spreadsheet.showCellEditor(placeholder); - return editor.getControl(); - } else { - // No editor was created so just drop placeholder - placeholder.dispose(); - // Probably we can just show preview panel - if ((handlerFeatures & DBDValueHandler.FEATURE_VIEWER) != 0) { - // Inline editor isn't supported but panel viewer is - // Enable panel - if (!isPreviewVisible()) { - togglePreview(); - } - return null; - } - } - } - return null; - } - - public void resetCellValue(@NotNull Object colElement, @NotNull Object rowElement, boolean delete) - { - final DBDAttributeBinding attr = (DBDAttributeBinding)(recordMode ? rowElement : colElement); - final ResultSetRow row = (ResultSetRow)(recordMode ? colElement : rowElement); - model.resetCellValue(attr, row); - updateValueView(); - } - /////////////////////////////////////////////////////// // Context menu & filters @@ -1499,18 +1020,7 @@ public class ResultSetViewer extends Viewer } }); } - if (row.isChanged()) { - Action resetValueAction = new Action(CoreMessages.controls_resultset_viewer_action_reset_value) - { - @Override - public void run() - { - resetCellValue(attr, row, false); - } - }; - resetValueAction.setAccelerator(SWT.ESC); - manager.add(resetValueAction); - } + manager.add(new GroupMarker(MENU_GROUP_EDIT)); } // Menus from value handler @@ -1593,127 +1103,14 @@ public class ResultSetViewer extends Viewer filtersMenu.add(new FilterResetColumnAction(column)); } } - { - final List selectedColumns = getSpreadsheet().getColumnSelection(); - if (!recordMode && !selectedColumns.isEmpty()) { - String hideTitle; - if (selectedColumns.size() == 1) { - DBDAttributeBinding columnToHide = (DBDAttributeBinding) selectedColumns.get(0); - hideTitle = "Hide column '" + columnToHide.getName() + "'"; - } else { - hideTitle = "Hide selected columns (" + selectedColumns.size() + ")"; - } - filtersMenu.add(new Action(hideTitle) { - @Override - public void run() - { - if (selectedColumns.size() >= model.getVisibleColumnCount()) { - UIUtils.showMessageBox(getControl().getShell(), "Hide columns", "Can't hide all result columns, at least one column must be visible", SWT.ERROR); - } else { - int[] columnIndexes = new int[selectedColumns.size()]; - for (int i = 0, selectedColumnsSize = selectedColumns.size(); i < selectedColumnsSize; i++) { - columnIndexes[i] = model.getVisibleColumnIndex((DBDAttributeBinding) selectedColumns.get(i)); - } - Arrays.sort(columnIndexes); - for (int i = columnIndexes.length; i > 0; i--) { - model.setColumnVisibility(model.getVisibleColumn(columnIndexes[i - 1]), false); - } - refreshSpreadsheet(true); - } - } - }); - } - } filtersMenu.add(new Separator()); filtersMenu.add(new ToggleServerSideOrderingAction()); filtersMenu.add(new ShowFiltersAction()); } - public void changeSorting(Object columnElement, final int state) - { - if (columnElement == null) { - columnOrder = columnOrder == SWT.DEFAULT ? SWT.DOWN : (columnOrder == SWT.DOWN ? SWT.UP : SWT.DEFAULT); - spreadsheet.refreshData(false); - spreadsheet.redrawGrid(); - return; - } - DBDDataFilter dataFilter = model.getDataFilter(); - boolean ctrlPressed = (state & SWT.CTRL) == SWT.CTRL; - boolean altPressed = (state & SWT.ALT) == SWT.ALT; - if (ctrlPressed) { - dataFilter.resetOrderBy(); - } - DBDAttributeBinding metaColumn = (DBDAttributeBinding)columnElement; - DBDAttributeConstraint constraint = dataFilter.getConstraint(metaColumn); - assert constraint != null; - //int newSort; - if (constraint.getOrderPosition() == 0) { - if (isServerSideFiltering() && supportsDataFilter()) { - if (!ConfirmationDialog.confirmActionWithParams( - spreadsheet.getShell(), - DBeaverPreferences.CONFIRM_ORDER_RESULTSET, - metaColumn.getName())) - { - return; - } - } - constraint.setOrderPosition(dataFilter.getMaxOrderingPosition() + 1); - constraint.setOrderDescending(altPressed); - } else if (!constraint.isOrderDescending()) { - constraint.setOrderDescending(true); - } else { - for (DBDAttributeConstraint con2 : dataFilter.getConstraints()) { - if (con2.getOrderPosition() > constraint.getOrderPosition()) { - con2.setOrderPosition(con2.getOrderPosition() - 1); - } - } - constraint.setOrderPosition(0); - constraint.setOrderDescending(false); - } - - // Reorder - reorderResultSet(false, new Runnable() { - @Override - public void run() - { - if (!recordMode) { - spreadsheet.refreshData(false); - } - } - }); - } - - public void navigateLink(@NotNull GridCell cell, int state) { - final DBDAttributeBinding attr = (DBDAttributeBinding)(recordMode ? cell.row : cell.col); - final ResultSetRow row = (ResultSetRow)(recordMode ? cell.col : cell.row); - - Object value = model.getCellValue(attr, row); - if (DBUtils.isNullValue(value)) { - log.warn("Can't navigate to NULL value"); - return; - } - - try { - DBeaverUI.runInProgressService(new DBRRunnableWithProgress() { - @Override - public void run(DBRProgressMonitor monitor) throws InvocationTargetException, InterruptedException { - try { - navigateAssociation(monitor, attr, row); - } catch (DBException e) { - throw new InvocationTargetException(e); - } - } - }); - } catch (InvocationTargetException e) { - UIUtils.showErrorDialog(site.getShell(), "Cannot navigate to the reference", null, e.getTargetException()); - } catch (InterruptedException e) { - // ignore - } - } - - @Override - public void navigateAssociation(@NotNull DBRProgressMonitor monitor, @NotNull DBDAttributeBinding attr, @NotNull ResultSetRow row) - throws DBException + @Override + public void navigateAssociation(@NotNull DBRProgressMonitor monitor, @NotNull DBDAttributeBinding attr, @NotNull ResultSetRow row) + throws DBException { DBSEntityAssociation association = null; List referrers = attr.getReferrers(); @@ -1767,11 +1164,8 @@ public class ResultSetViewer extends Viewer @Override public void updateValueView() { - updateEditControls(); - spreadsheet.redrawGrid(); - previewValue(); - activePresentation.updateValueView(); + updateEditControls(); } @Override @@ -1807,7 +1201,7 @@ public class ResultSetViewer extends Viewer } @Override - @NotNull + @Nullable public IResultSetSelection getSelection() { if (activePresentation instanceof ISelectionProvider) { @@ -1860,11 +1254,6 @@ public class ResultSetViewer extends Viewer } } - // Cache preferences - IPreferenceStore preferenceStore = getPreferenceStore(); - showOddRows = preferenceStore.getBoolean(DBeaverPreferences.RESULT_SET_SHOW_ODD_ROWS); - showCelIcons = preferenceStore.getBoolean(DBeaverPreferences.RESULT_SET_SHOW_CELL_ICONS); - // Pump data ResultSetRow oldRow = curRow; @@ -1878,9 +1267,7 @@ public class ResultSetViewer extends Viewer @Override public void run() { - if (!supportsDataFilter() && !model.getDataFilter().hasOrdering()) { - reorderLocally(); - } + activePresentation.formatData(true); } }); } @@ -1899,43 +1286,19 @@ public class ResultSetViewer extends Viewer } } - private boolean isServerSideFiltering() - { - return - getPreferenceStore().getBoolean(DBeaverPreferences.RESULT_SET_ORDER_SERVER_SIDE) && - (dataReceiver.isHasMoreData() || !CommonUtils.isEmpty(model.getDataFilter().getOrder())); - } - - private void reorderResultSet(boolean force, @Nullable Runnable onSuccess) - { - if (force || isServerSideFiltering() && supportsDataFilter()) { - DBSDataContainer dataContainer = getDataContainer(); - if (resultSetProvider.isReadyToRun() && dataContainer != null && dataPumpJob == null) { - int segmentSize = getSegmentMaxRows(); - if (curRow != null && curRow.getVisualNumber() >= segmentSize && segmentSize > 0) { - segmentSize = (curRow.getVisualNumber() / segmentSize + 1) * segmentSize; - } - runDataPump(dataContainer, null, 0, segmentSize, -1, onSuccess); - } - return; - } - - try { - reorderLocally(); - } finally { - if (onSuccess != null) { - onSuccess.run(); + @Override + public void refreshData(@Nullable Runnable onSuccess) { + DBSDataContainer dataContainer = getDataContainer(); + if (resultSetProvider.isReadyToRun() && dataContainer != null && dataPumpJob == null) { + int segmentSize = getSegmentMaxRows(); + if (curRow != null && curRow.getVisualNumber() >= segmentSize && segmentSize > 0) { + segmentSize = (curRow.getVisualNumber() / segmentSize + 1) * segmentSize; } + runDataPump(dataContainer, null, 0, segmentSize, -1, onSuccess); } } - private void reorderLocally() - { - rejectChanges(); - model.resetOrdering(); - } - - synchronized void readNextSegment() + public synchronized void readNextSegment() { if (!dataReceiver.isHasMoreData()) { return; @@ -1969,11 +1332,15 @@ public class ResultSetViewer extends Viewer // Read data final DBDDataFilter useDataFilter = dataFilter != null ? dataFilter : (dataContainer == getDataContainer() ? model.getDataFilter() : null); + Composite progressControl = viewerPanel; + if (activePresentation.getControl() instanceof Composite) { + progressControl = (Composite) activePresentation.getControl(); + } dataPumpJob = new ResultSetDataPumpJob( dataContainer, useDataFilter, getDataReceiver(), - getSpreadsheet()); + progressControl); dataPumpJob.addJobChangeListener(new JobChangeAdapter() { @Override public void aboutToRun(IJobChangeEvent event) { @@ -2010,6 +1377,7 @@ public class ResultSetViewer extends Viewer "Query execution failed", error); } else if (focusRow >= 0 && focusRow < model.getRowCount() && model.getVisibleColumnCount() > 0) { + Object presentationState = savePresentationState(); // Seems to be refresh // Restore original position curRow = model.getRow(focusRow); @@ -2019,19 +1387,11 @@ public class ResultSetViewer extends Viewer } else { updateStatusMessage(); } - if (curAttribute != null && curRow != null) { - GridCell newPos; - if (!recordMode) { - newPos = new GridCell(curAttribute, curRow); - } else { - newPos = new GridCell(curRow, curAttribute); - } - spreadsheet.setCursor(newPos, false); - } - previewValue(); + restorePresentationState(presentationState); + activePresentation.updateValueView(); } else { - curAttribute = null; - spreadsheet.redraw(); + activePresentation.clearData(); + activePresentation.refreshData(true); } if (error == null) { @@ -2063,10 +1423,9 @@ public class ResultSetViewer extends Viewer private void clearData() { - model.clearData(); + this.model.clearData(); this.curRow = null; - this.curAttribute = null; - this.columnOrder = SWT.NONE; + this.activePresentation.clearData(); } @Override @@ -2113,143 +1472,10 @@ public class ResultSetViewer extends Viewer new ResultSetPersister(this).rejectChanges(); } - public void copySelectionToClipboard( - boolean copyHeader, - boolean copyRowNumbers, - boolean cut, - String delimiter, - DBDDisplayFormat format) - { - if (delimiter == null) { - delimiter = "\t"; - } - String lineSeparator = ContentUtils.getDefaultLineSeparator(); - List selectedColumns = spreadsheet.getColumnSelection(); - IGridLabelProvider labelProvider = spreadsheet.getLabelProvider(); - StringBuilder tdt = new StringBuilder(); - if (copyHeader) { - if (copyRowNumbers) { - tdt.append("#"); - } - for (Object column : selectedColumns) { - if (tdt.length() > 0) { - tdt.append(delimiter); - } - tdt.append(labelProvider.getText(column)); - } - tdt.append(lineSeparator); - } - - List selectedCells = spreadsheet.getCellSelection(); - - GridCell prevCell = null; - for (GridCell cell : selectedCells) { - if (prevCell == null || cell.row != prevCell.row) { - // Next row - if (prevCell != null && prevCell.col != cell.col) { - // Fill empty row tail - int prevColIndex = selectedColumns.indexOf(prevCell.col); - for (int i = prevColIndex; i < selectedColumns.size() - 1; i++) { - tdt.append(delimiter); - } - } - if (prevCell != null) { - tdt.append(lineSeparator); - } - if (copyRowNumbers) { - tdt.append(labelProvider.getText(cell.row)).append(delimiter); - } - } - if (prevCell != null && prevCell.col != cell.col) { - int prevColIndex = selectedColumns.indexOf(prevCell.col); - int curColIndex = selectedColumns.indexOf(cell.col); - for (int i = prevColIndex; i < curColIndex; i++) { - tdt.append(delimiter); - } - } - - DBDAttributeBinding column = (DBDAttributeBinding)(!recordMode ? cell.col : cell.row); - ResultSetRow row = (ResultSetRow) (!recordMode ? cell.row : cell.col); - Object value = model.getCellValue(column, row); - String cellText = column.getValueHandler().getValueDisplayString( - column.getAttribute(), - value, - format); - tdt.append(cellText); - - if (cut) { - DBDValueController valueController = new ResultSetValueController( - this, column, row, DBDValueController.EditType.NONE, null); - if (!valueController.isReadOnly()) { - valueController.updateValue(DBUtils.makeNullValue(valueController)); - } - } - - prevCell = cell; - } - - if (tdt.length() > 0) { - TextTransfer textTransfer = TextTransfer.getInstance(); - getSpreadsheet().getClipboard().setContents( - new Object[]{tdt.toString()}, - new Transfer[]{textTransfer}); - } - } - - public void pasteCellValue() - { - DBDAttributeBinding attr = getFocusAttribute(); - ResultSetRow row = getFocusRow(); - if (attr == null || row == null) { - return; - } - if (isColumnReadOnly(attr)) { - // No inline editors for readonly columns - return; - } - try { - Object newValue = getColumnValueFromClipboard(attr); - if (newValue == null) { - return; - } - new ResultSetValueController( - this, - attr, - row, - DBDValueController.EditType.NONE, - null).updateValue(newValue); - } - catch (Exception e) { - UIUtils.showErrorDialog(site.getShell(), "Cannot replace cell value", null, e); - } - } - - @Nullable - private Object getColumnValueFromClipboard(DBDAttributeBinding metaColumn) throws DBCException - { - DBPDataSource dataSource = getDataSource(); - if (dataSource == null) { - return null; - } - DBCSession session = dataSource.openSession(VoidProgressMonitor.INSTANCE, DBCExecutionPurpose.UTIL, "Copy from clipboard"); - try { - String strValue = (String) getSpreadsheet().getClipboard().getContents(TextTransfer.getInstance()); - return metaColumn.getValueHandler().getValueFromObject( - session, metaColumn.getAttribute(), strValue, true); - } finally { - session.close(); - } - } void addNewRow(final boolean copyCurrent) { - GridPos curPos = spreadsheet.getCursorPosition(); - int rowNum; - if (recordMode) { - rowNum = curRow == null ? 0 : curRow.getVisualNumber(); - } else { - rowNum = curPos.row; - } + int rowNum = curRow == null ? 0 : curRow.getVisualNumber(); if (rowNum >= model.getRowCount()) { rowNum = model.getRowCount() - 1; } @@ -2305,7 +1531,7 @@ public class ResultSetViewer extends Viewer session.close(); } model.addNewRow(rowNum, cells); - refreshSpreadsheet(true); + redrawData(true); updateEditControls(); fireResultSetChange(); } @@ -2316,8 +1542,9 @@ public class ResultSetViewer extends Viewer if (recordMode) { rowsToDelete.add(curRow); } else { - for (GridCell cell : spreadsheet.getCellSelection()) { - rowsToDelete.add((ResultSetRow) cell.row); + IResultSetSelection selection = getSelection(); + if (selection != null && !selection.isEmpty()) { + rowsToDelete.addAll(selection.getSelectedRows()); } } if (rowsToDelete.isEmpty()) { @@ -2332,16 +1559,12 @@ public class ResultSetViewer extends Viewer } lastRowNum = row.getVisualNumber(); } + redrawData(rowsRemoved > 0); // Move one row down (if we are in grid mode) - if (!recordMode && lastRowNum < spreadsheet.getItemCount() - 1 && curAttribute != null) { - GridCell newPos = new GridCell(curAttribute, model.getRow(lastRowNum - rowsRemoved + 1)); - spreadsheet.setCursor(newPos, false); - } - if (rowsRemoved > 0) { - refreshSpreadsheet(true); - } else { - spreadsheet.redrawGrid(); + if (!recordMode && lastRowNum < model.getRowCount() - 1) { + activePresentation.scrollToRow(IResultSetPresentation.RowPosition.NEXT); } + updateEditControls(); fireResultSetChange(); } @@ -2436,7 +1659,7 @@ public class ResultSetViewer extends Viewer } } - void fireResultSetChange() { + public void fireResultSetChange() { synchronized (listeners) { if (!listeners.isEmpty()) { for (IResultSetListener listener : listeners) { @@ -2446,521 +1669,6 @@ public class ResultSetViewer extends Viewer } } - ///////////////////////////// - // Value controller - - static class ResultSetValueController implements DBDAttributeController, DBDRowController { - - private final ResultSetViewer viewer; - private final EditType editType; - private final Composite inlinePlaceholder; - private ResultSetRow curRow; - private final DBDAttributeBinding binding; - - ResultSetValueController( - @NotNull ResultSetViewer viewer, - @NotNull DBDAttributeBinding binding, - @NotNull ResultSetRow row, - @NotNull EditType editType, - @Nullable Composite inlinePlaceholder) - { - this.viewer = viewer; - this.binding = binding; - this.curRow = row; - this.editType = editType; - this.inlinePlaceholder = inlinePlaceholder; - } - - void setCurRow(ResultSetRow curRow) - { - this.curRow = curRow; - } - - @Nullable - @Override - public DBPDataSource getDataSource() - { - return viewer.getDataSource(); - } - - @Override - public String getValueName() - { - return binding.getName(); - } - - @Override - public DBSTypedObject getValueType() - { - return binding.getMetaAttribute(); - } - - @NotNull - @Override - public DBDRowController getRowController() { - return this; - } - - @NotNull - @Override - public DBDAttributeBinding getBinding() - { - return binding; - } - - @NotNull - @Override - public String getColumnId() { - DBPDataSource dataSource = getDataSource(); - DBCAttributeMetaData metaAttribute = binding.getMetaAttribute(); - return DBUtils.getSimpleQualifiedName( - dataSource == null ? null : dataSource.getContainer().getName(), - metaAttribute.getEntityName(), - metaAttribute.getName()); - } - - @Override - public Object getValue() - { - return viewer.spreadsheet.getContentProvider().getCellValue(curRow, binding, false); - } - - @Override - public void updateValue(@Nullable Object value) - { - if (viewer.model.updateCellValue(binding, curRow, value)) { - // Update controls - viewer.site.getShell().getDisplay().syncExec(new Runnable() { - @Override - public void run() { - viewer.updateValueView(); - } - }); - } - viewer.fireResultSetChange(); - } - - @Nullable - @Override - public DBDRowIdentifier getRowIdentifier() - { - return binding.getRowIdentifier(); - } - - @Override - public DBDValueHandler getValueHandler() - { - return binding.getValueHandler(); - } - - @Override - public EditType getEditType() - { - return editType; - } - - @Override - public boolean isReadOnly() - { - return viewer.isColumnReadOnly(binding); - } - - @Override - public IWorkbenchPartSite getValueSite() - { - return viewer.site; - } - - @Nullable - @Override - public Composite getEditPlaceholder() - { - return inlinePlaceholder; - } - - @Nullable - @Override - public ToolBar getEditToolBar() - { - return viewer.isPreviewVisible() ? viewer.previewPane.getToolBar() : null; - } - - @Override - public void closeInlineEditor() - { - viewer.spreadsheet.cancelInlineEditor(); - } - - @Override - public void nextInlineEditor(boolean next) { - viewer.spreadsheet.cancelInlineEditor(); - int colOffset = next ? 1 : -1; - int rowOffset = 0; - //final int rowCount = spreadsheet.getItemCount(); - final int colCount = viewer.spreadsheet.getColumnCount(); - final GridPos curPosition = viewer.spreadsheet.getCursorPosition(); - if (colOffset > 0 && curPosition.col + colOffset >= colCount) { - colOffset = -colCount; - rowOffset = 1; - } else if (colOffset < 0 && curPosition.col + colOffset < 0) { - colOffset = colCount; - rowOffset = -1; - } - viewer.spreadsheet.shiftCursor(colOffset, rowOffset, false); - viewer.showCellEditor(true); - } - - public void registerEditor(DBDValueEditorStandalone editor) { - viewer.openEditors.put(this, editor); - } - - @Override - public void unregisterEditor(DBDValueEditorStandalone editor) { - viewer.openEditors.remove(this); - } - - @Override - public void showMessage(String message, boolean error) - { - viewer.setStatus(message, error); - } - - @NotNull - @Override - public List getRowAttributes() - { - return Arrays.asList(viewer.model.getColumns()); - } - - @Nullable - @Override - public Object getAttributeValue(DBDAttributeBinding attribute) - { - return viewer.model.getCellValue(attribute, curRow); - } - - } - - private class ContentProvider implements IGridContentProvider { - - @NotNull - @Override - public Object[] getElements(boolean horizontal) { - if (horizontal) { - // columns - if (!recordMode) { - return model.getVisibleColumns().toArray(); - } else { - return curRow == null ? new Object[0] : new Object[] {curRow}; - } - } else { - // rows - if (!recordMode) { - return model.getAllRows().toArray(); - } else { - DBDAttributeBinding[] columns = model.getVisibleColumns().toArray(new DBDAttributeBinding[model.getVisibleColumnCount()]); - if (columnOrder != SWT.NONE && columnOrder != SWT.DEFAULT) { - Arrays.sort(columns, new Comparator() { - @Override - public int compare(DBDAttributeBinding o1, DBDAttributeBinding o2) { - return o1.getName().compareTo(o2.getName()) * (columnOrder == SWT.DOWN ? 1 : -1); - } - }); - } - return columns; - } - } - } - - @Nullable - @Override - public Object[] getChildren(Object element) { - if (element instanceof DBDAttributeBinding) { - DBDAttributeBinding binding = (DBDAttributeBinding) element; - switch (binding.getDataKind()) { - case ARRAY: - if (recordMode) { - if (curRow != null) { - Object value = model.getCellValue(binding, curRow); - if (value instanceof DBDCollection) { - return curRow.getCollectionData( - binding, - ((DBDCollection)value)).elements; - } - } - return null; - } - case STRUCT: - case ANY: - if (binding.getNestedBindings() != null) { - return binding.getNestedBindings().toArray(); - } - break; - } - } - - return null; - } - - @Override - public int getSortOrder(@Nullable Object column) - { - if (column instanceof DBDAttributeBinding) { - DBDAttributeBinding binding = (DBDAttributeBinding) column; - if (!binding.hasNestedBindings()) { - DBDAttributeConstraint co = model.getDataFilter().getConstraint(binding); - if (co != null && co.getOrderPosition() > 0) { - return co.isOrderDescending() ? SWT.UP : SWT.DOWN; - } - return SWT.DEFAULT; - } - } else if (column == null && recordMode) { - // Columns order in record mode - return columnOrder; - } - return SWT.NONE; - } - - @Override - public ElementState getDefaultState(@NotNull Object element) { - if (element instanceof DBDAttributeBinding) { - DBDAttributeBinding binding = (DBDAttributeBinding) element; - switch (binding.getAttribute().getDataKind()) { - case STRUCT: - return ElementState.EXPANDED; - case ARRAY: - if (curRow != null) { - Object cellValue = model.getCellValue(binding, curRow); - if (cellValue instanceof DBDCollection && ((DBDCollection) cellValue).getItemCount() < 3) { - return ElementState.EXPANDED; - } - } - return ElementState.COLLAPSED; - default: - break; - } - } - return ElementState.NONE; - } - - @Override - public int getCellState(Object colElement, Object rowElement) { - int state = STATE_NONE; - DBDAttributeBinding attr = (DBDAttributeBinding)(recordMode ? rowElement : colElement); - ResultSetRow row = (ResultSetRow)(recordMode ? colElement : rowElement); - Object value = model.getCellValue(attr, row); - if (!CommonUtils.isEmpty(attr.getReferrers()) && !DBUtils.isNullValue(value)) { - state |= STATE_LINK; - } - return state; - } - - @Override - public void dispose() - { - } - - @Override - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) - { - } - - @Nullable - @Override - public Object getCellValue(Object colElement, Object rowElement, boolean formatString) - { - DBDAttributeBinding attr = (DBDAttributeBinding)(rowElement instanceof DBDAttributeBinding ? rowElement : colElement); - ResultSetRow row = (ResultSetRow)(colElement instanceof ResultSetRow ? colElement : rowElement); - int rowNum = row.getVisualNumber(); - Object value = model.getCellValue(attr, row); - - if (rowNum > 0 && rowNum == model.getRowCount() - 1 && (recordMode || spreadsheet.isRowVisible(rowNum)) && dataReceiver.isHasMoreData()) { - readNextSegment(); - } - - if (formatString) { - if (recordMode) { - if (attr.getDataKind() == DBPDataKind.ARRAY && value instanceof DBDCollection) { - return "[" + ((DBDCollection) value).getItemCount() + "]"; - } else if (attr.getDataKind() == DBPDataKind.STRUCT && value instanceof DBDStructure) { - return "[" + ((DBDStructure) value).getDataType().getName() + "]"; - } - } - return attr.getValueHandler().getValueDisplayString( - attr.getAttribute(), - value, - DBDDisplayFormat.UI); - } else { - return value; - } - } - - @Nullable - @Override - public Image getCellImage(Object colElement, Object rowElement) - { - if (!showCelIcons) { - return null; - } - DBDAttributeBinding attr = (DBDAttributeBinding)(recordMode ? rowElement : colElement); - if ((attr.getValueHandler().getFeatures() & DBDValueHandler.FEATURE_SHOW_ICON) != 0) { - return DBUtils.getTypeImage(attr.getMetaAttribute()); - } else { - return null; - } - } - - @NotNull - @Override - public String getCellText(Object colElement, Object rowElement) - { - return String.valueOf(getCellValue(colElement, rowElement, true)); - } - - @Nullable - @Override - public Color getCellForeground(Object colElement, Object rowElement) - { - Object value = getCellValue(colElement, rowElement, false); - if (DBUtils.isNullValue(value)) { - return foregroundNull; - } else { - if (foregroundDefault == null) { - foregroundDefault = filtersText.getForeground(); - } - return foregroundDefault; - } - } - - @Nullable - @Override - public Color getCellBackground(Object colElement, Object rowElement) - { - ResultSetRow row = (ResultSetRow) (!recordMode ? rowElement : colElement); - DBDAttributeBinding attribute = (DBDAttributeBinding)(!recordMode ? colElement : rowElement); - boolean odd = row.getVisualNumber() % 2 == 0; - - if (row.getState() == ResultSetRow.STATE_ADDED) { - return backgroundAdded; - } - if (row.getState() == ResultSetRow.STATE_REMOVED) { - return backgroundDeleted; - } - if (row.changes != null && row.changes.containsKey(attribute)) { - return backgroundModified; - } - if ((attribute.getValueHandler().getFeatures() & DBDValueHandler.FEATURE_COMPOSITE) != 0) { - return backgroundReadOnly; - } - if (!recordMode && odd && showOddRows) { - return backgroundOdd; - } - - if (backgroundNormal == null) { - backgroundNormal = filtersText.getBackground(); - } - return backgroundNormal; - } - - @Override - public void resetColors() { - backgroundNormal = null; - foregroundDefault = null; - } - } - - private class GridLabelProvider implements IGridLabelProvider { - @Nullable - @Override - public Image getImage(Object element) - { - if (element instanceof DBDAttributeBinding/* && (!isRecordMode() || !model.isDynamicMetadata())*/) { - return DBUtils.getTypeImage(((DBDAttributeBinding) element).getMetaAttribute()); - } - return null; - } - - @Nullable - @Override - public Color getForeground(Object element) { - if (element == null) { - if (foregroundDefault == null) { - foregroundDefault = filtersText.getForeground(); - } - return foregroundDefault; - } - return null; - } - - @Nullable - @Override - public Color getBackground(Object element) { - if (backgroundNormal == null) { - backgroundNormal = filtersText.getBackground(); - } - if (element == null) { - return backgroundNormal; - } - -/* - ResultSetRow row = (ResultSetRow) (!recordMode ? element : curRow); - boolean odd = row != null && row.getVisualNumber() % 2 == 0; - if (!recordMode && odd && showOddRows) { - return backgroundOdd; - } - return backgroundNormal; -*/ - return null; - } - - @NotNull - @Override - public String getText(Object element) - { - if (element instanceof DBDAttributeBinding) { - DBDAttributeBinding attributeBinding = (DBDAttributeBinding) element; - if (CommonUtils.isEmpty(attributeBinding.getLabel())) { - return attributeBinding.getName(); - } else { - return attributeBinding.getLabel(); - } - } else { - if (!recordMode) { - return String.valueOf(((ResultSetRow)element).getVisualNumber() + 1); - } else { - return CoreMessages.controls_resultset_viewer_value; - } - } - } - - @Nullable - @Override - public Font getFont(Object element) - { - if (element instanceof DBDAttributeBinding) { - DBDAttributeBinding attributeBinding = (DBDAttributeBinding) element; - DBDAttributeConstraint constraint = model.getDataFilter().getConstraint(attributeBinding); - if (constraint != null && constraint.hasFilter()) { - return boldFont; - } - } - return null; - } - - @Nullable - @Override - public String getTooltip(Object element) - { - if (element instanceof DBDAttributeBinding) { - DBDAttributeBinding attributeBinding = (DBDAttributeBinding) element; - String name = attributeBinding.getName(); - String typeName = DBUtils.getFullTypeName(attributeBinding.getAttribute()); - return name + ": " + typeName; - } - return null; - } - } - private class ConfigAction extends Action implements IMenuCreator { public ConfigAction() { @@ -2977,7 +1685,7 @@ public class ResultSetViewer extends Viewer @Override public void runWithEvent(Event event) { - Menu menu = getMenu(getSpreadsheet()); + Menu menu = getMenu(activePresentation.getControl()); if (menu != null && event.widget instanceof ToolItem) { Rectangle bounds = ((ToolItem) event.widget).getBounds(); Point point = ((ToolItem) event.widget).getParent().toDisplay(bounds.x, bounds.y + bounds.height); @@ -3003,7 +1711,7 @@ public class ResultSetViewer extends Viewer menuManager.add(new DictionaryEditAction()); menuManager.add(new Separator()); menuManager.add(ActionUtils.makeCommandContribution(site, ResultSetCommandHandler.CMD_TOGGLE_MODE, CommandContributionItem.STYLE_CHECK)); - menuManager.add(ActionUtils.makeCommandContribution(site, ResultSetCommandHandler.CMD_TOGGLE_PREVIEW, CommandContributionItem.STYLE_CHECK)); + activePresentation.fillMenu(menuManager); menuManager.add(new Separator()); menuManager.add(new Action("Preferences") { @Override @@ -3073,8 +1781,8 @@ public class ResultSetViewer extends Viewer @Override Object getValue(ResultSetViewer viewer, DBDAttributeBinding column, DBCLogicalOperator operator, boolean useDefault) { - final DBDAttributeBinding attr = viewer.getFocusAttribute(); - final ResultSetRow row = viewer.getFocusRow(); + final DBDAttributeBinding attr = column; + final ResultSetRow row = viewer.getCurrentRow(); if (attr == null || row == null) { return null; } @@ -3092,7 +1800,7 @@ public class ResultSetViewer extends Viewer if (useDefault) { return ".."; } else { - ResultSetRow focusRow = viewer.getFocusRow(); + ResultSetRow focusRow = viewer.getCurrentRow(); if (focusRow == null) { return null; } @@ -3110,7 +1818,7 @@ public class ResultSetViewer extends Viewer Object getValue(ResultSetViewer viewer, DBDAttributeBinding column, DBCLogicalOperator operator, boolean useDefault) { try { - return viewer.getColumnValueFromClipboard(column); + return ResultSetUtils.getColumnValueFromClipboard(column); } catch (DBCException e) { log.debug("Error copying from clipboard", e); return null; @@ -3319,4 +2027,5 @@ public class ResultSetViewer extends Viewer return combo; } } + } diff --git a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/spreadsheet/Spreadsheet.java b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/spreadsheet/Spreadsheet.java index 7e6a200d4bf23125151ae7ad335c3910f47b8453..a70c27cf4e50f35fa88114a42a1298baa70e8df6 100644 --- a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/spreadsheet/Spreadsheet.java +++ b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/spreadsheet/Spreadsheet.java @@ -59,7 +59,7 @@ public class Spreadsheet extends LightGrid implements Listener { @NotNull private final IWorkbenchPartSite site; @NotNull - private final SpreadsheetPresentation spreadsheetController; + private final SpreadsheetPresentation presentation; @NotNull private final IGridContentProvider contentProvider; @NotNull @@ -71,7 +71,7 @@ public class Spreadsheet extends LightGrid implements Listener { @NotNull final Composite parent, final int style, @NotNull final IWorkbenchPartSite site, - @NotNull final SpreadsheetPresentation spreadsheetController, + @NotNull final SpreadsheetPresentation presentation, @NotNull final IGridContentProvider contentProvider, @NotNull final IGridLabelProvider labelProvider) { @@ -84,7 +84,7 @@ public class Spreadsheet extends LightGrid implements Listener { this.setLayout(layout); this.site = site; - this.spreadsheetController = spreadsheetController; + this.presentation = presentation; this.contentProvider = contentProvider; this.labelProvider = labelProvider; @@ -125,6 +125,11 @@ public class Spreadsheet extends LightGrid implements Listener { } } + @NotNull + public SpreadsheetPresentation getPresentation() { + return presentation; + } + public Clipboard getClipboard() { return clipboard; @@ -234,7 +239,7 @@ public class Spreadsheet extends LightGrid implements Listener { (event.keyCode >= 'a' && event.keyCode <= 'z') || (event.keyCode >= '0' && event.keyCode <= '9')) { - final Control editorControl = spreadsheetController.showCellEditor(true); + final Control editorControl = presentation.openValueEditor(true); if (editorControl != null && event.keyCode != SWT.CR) { // Forward the same key event to just created control final Event fwdEvent = new Event(); @@ -254,7 +259,7 @@ public class Spreadsheet extends LightGrid implements Listener { Object col = getFocusColumnElement(); Object row = getFocusRowElement(); if (col != null && row != null) { - spreadsheetController.resetCellValue(col, row, false); + presentation.resetCellValue(col, row, false); } } break; @@ -263,27 +268,27 @@ public class Spreadsheet extends LightGrid implements Listener { GridPos focusPos = super.getFocusPos(); if (pos != null && focusPos != null && pos.equals(super.getFocusPos())) { DoubleClickBehavior doubleClickBehavior = DoubleClickBehavior.valueOf( - spreadsheetController.getPreferenceStore().getString(DBeaverPreferences.RESULT_SET_DOUBLE_CLICK)); + presentation.getPreferenceStore().getString(DBeaverPreferences.RESULT_SET_DOUBLE_CLICK)); switch (doubleClickBehavior) { case NONE: return; case EDITOR: - spreadsheetController.showCellEditor(false); + presentation.openValueEditor(false); break; case INLINE_EDITOR: - spreadsheetController.showCellEditor(true); + presentation.openValueEditor(true); break; } } break; case SWT.MouseDown: if (event.button == 2) { - spreadsheetController.showCellEditor(true); + presentation.openValueEditor(true); } break; case LightGrid.Event_ChangeSort: - spreadsheetController.changeSorting(event.data, event.stateMask); + presentation.changeSorting(event.data, event.stateMask); break; case LightGrid.Event_NavigateLink: // Perform navigation async because it may change grid content and @@ -291,7 +296,7 @@ public class Spreadsheet extends LightGrid implements Listener { getDisplay().asyncExec(new Runnable() { @Override public void run() { - spreadsheetController.navigateLink((GridCell) event.data, event.stateMask); + presentation.navigateLink((GridCell) event.data, event.stateMask); } }); break; @@ -302,6 +307,7 @@ public class Spreadsheet extends LightGrid implements Listener { public void refreshData(boolean refreshColumns) { cancelInlineEditor(); super.refreshData(refreshColumns); + super.redraw(); } private void hookContextMenu() @@ -316,7 +322,7 @@ public class Spreadsheet extends LightGrid implements Listener { // Let controller to provide it's own menu items GridPos focusPos = getFocusPos(); - spreadsheetController.fillContextMenu( + presentation.fillContextMenu( focusPos.col >= 0 && focusPos.col < columnElements.length ? columnElements[focusPos.col] : null, focusPos.row >= 0 && focusPos.row < rowElements.length ? rowElements[focusPos.row] : null, manager); diff --git a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/spreadsheet/SpreadsheetCommandHandler.java b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/spreadsheet/SpreadsheetCommandHandler.java index c0a612a90ec5ba0a9df05f0103195a1d89680059..adaaed83ba12f74cf433d7607329368139a49f2f 100644 --- a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/spreadsheet/SpreadsheetCommandHandler.java +++ b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/spreadsheet/SpreadsheetCommandHandler.java @@ -35,6 +35,8 @@ import org.jkiss.code.Nullable; */ public class SpreadsheetCommandHandler extends AbstractHandler { + public static final String CMD_TOGGLE_PREVIEW = "org.jkiss.dbeaver.core.resultset.grid.togglePreview"; + public static Spreadsheet getActiveSpreadsheet(ExecutionEvent event) { Object control = HandlerUtil.getVariable(event, ISources.ACTIVE_FOCUS_CONTROL_NAME); @@ -57,7 +59,11 @@ public class SpreadsheetCommandHandler extends AbstractHandler { if (actionId.equals(IWorkbenchCommandConstants.EDIT_SELECT_ALL)) { spreadsheet.selectAll(); return null; + } else if (actionId.equals(CMD_TOGGLE_PREVIEW)) { + spreadsheet.getPresentation().togglePreview(); + return null; } + Event keyEvent = new Event(); keyEvent.doit = true; if (actionId.equals(ITextEditorActionDefinitionIds.LINE_START)) { diff --git a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/spreadsheet/SpreadsheetPresentation.java b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/spreadsheet/SpreadsheetPresentation.java index 336d89c9d96756813c97f99311d2827e632e4e31..6c0104895a19642669474eb3d78d9788b89c4e26 100644 --- a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/spreadsheet/SpreadsheetPresentation.java +++ b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/spreadsheet/SpreadsheetPresentation.java @@ -20,40 +20,113 @@ package org.jkiss.dbeaver.ui.controls.resultset.spreadsheet; import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.IToolBarManager; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.text.IFindReplaceTarget; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.jface.viewers.*; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.SashForm; +import org.eclipse.swt.events.*; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.*; +import org.eclipse.ui.commands.ICommandService; +import org.eclipse.ui.menus.CommandContributionItem; +import org.eclipse.ui.progress.UIJob; +import org.eclipse.ui.themes.ITheme; +import org.eclipse.ui.themes.IThemeManager; +import org.eclipse.ui.views.properties.IPropertySheetPage; +import org.eclipse.ui.views.properties.IPropertySource; +import org.eclipse.ui.views.properties.IPropertySourceProvider; import org.jkiss.code.NotNull; import org.jkiss.code.Nullable; +import org.jkiss.dbeaver.DBException; +import org.jkiss.dbeaver.DBeaverPreferences; +import org.jkiss.dbeaver.core.CoreMessages; +import org.jkiss.dbeaver.core.DBeaverUI; import org.jkiss.dbeaver.core.Log; -import org.jkiss.dbeaver.model.data.DBDAttributeBinding; +import org.jkiss.dbeaver.model.DBPDataKind; +import org.jkiss.dbeaver.model.DBPDataSource; +import org.jkiss.dbeaver.model.DBUtils; +import org.jkiss.dbeaver.model.data.*; +import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor; +import org.jkiss.dbeaver.model.runtime.DBRRunnableWithProgress; +import org.jkiss.dbeaver.model.struct.DBSDataContainer; +import org.jkiss.dbeaver.ui.ActionUtils; +import org.jkiss.dbeaver.ui.UIUtils; +import org.jkiss.dbeaver.ui.controls.PropertyPageStandard; import org.jkiss.dbeaver.ui.controls.lightgrid.GridCell; import org.jkiss.dbeaver.ui.controls.lightgrid.GridPos; +import org.jkiss.dbeaver.ui.controls.lightgrid.IGridContentProvider; +import org.jkiss.dbeaver.ui.controls.lightgrid.IGridLabelProvider; import org.jkiss.dbeaver.ui.controls.resultset.*; +import org.jkiss.dbeaver.ui.dialogs.ConfirmationDialog; +import org.jkiss.dbeaver.ui.properties.PropertyCollector; +import org.jkiss.dbeaver.utils.ContentUtils; +import org.jkiss.utils.CommonUtils; +import java.lang.reflect.InvocationTargetException; import java.util.*; +import java.util.List; /** * Spreadsheet presentation. * Visualizes results as grid. */ -public class SpreadsheetPresentation implements IResultSetPresentation, ISelectionProvider, IAdaptable { +public class SpreadsheetPresentation implements IResultSetPresentation, ISelectionProvider, IStatefulControl, IAdaptable { static final Log log = Log.getLog(SpreadsheetPresentation.class); + private static final String VIEW_PANEL_VISIBLE = "viewPanelVisible"; + private static final String VIEW_PANEL_RATIO = "viewPanelRatio"; + private IResultSetController controller; + + private SashForm resultsSash; private Spreadsheet spreadsheet; + private ViewValuePanel previewPane; + private SpreadsheetValueController panelValueController; + + @Nullable + private DBDAttributeBinding curAttribute; + private int columnOrder = SWT.NONE; + + private final Map openEditors = new HashMap(); + private SpreadsheetFindReplaceTarget findReplaceTarget; private final List selectionChangedListenerList = new ArrayList(); + // UI modifiers + @NotNull + private IThemeManager themeManager; + private IPropertyChangeListener themeChangeListener; + + private Color backgroundAdded; + private Color backgroundDeleted; + private Color backgroundModified; + private Color backgroundNormal; + private Color backgroundOdd; + private Color backgroundReadOnly; + private Color foregroundDefault; + private Color foregroundNull; + private Font boldFont; + + private boolean showOddRows = true; + private boolean showCelIcons = true; + public SpreadsheetPresentation() { findReplaceTarget = new SpreadsheetFindReplaceTarget(this); + } public IResultSetController getController() { @@ -64,10 +137,68 @@ public class SpreadsheetPresentation implements IResultSetPresentation, ISelecti return spreadsheet; } + @Nullable + DBPDataSource getDataSource() { + DBSDataContainer dataContainer = controller.getDataContainer(); + return dataContainer == null ? null : dataContainer.getDataSource(); + } + @Override - public void createPresentation(IResultSetController controller, Composite parent) { + public void createPresentation(@NotNull IResultSetController controller, @NotNull Composite parent) { + this.boldFont = UIUtils.makeBoldFont(parent.getFont()); + this.foregroundNull = parent.getShell().getDisplay().getSystemColor(SWT.COLOR_GRAY); + this.controller = controller; - this.spreadsheet = ((ResultSetViewer)controller).getSpreadsheet(); + + { + resultsSash = new SashForm(parent, SWT.HORIZONTAL | SWT.SMOOTH); + resultsSash.setBackgroundMode(SWT.INHERIT_FORCE); + resultsSash.setLayoutData(new GridData(GridData.FILL_BOTH)); + resultsSash.setSashWidth(5); + //resultsSash.setBackground(resultsSash.getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND)); + + this.spreadsheet = new Spreadsheet( + resultsSash, + SWT.MULTI | SWT.VIRTUAL | SWT.H_SCROLL | SWT.V_SCROLL, + controller.getSite(), + this, + new ContentProvider(), + new GridLabelProvider()); + this.spreadsheet.setLayoutData(new GridData(GridData.FILL_BOTH)); + + this.previewPane = new ViewValuePanel(resultsSash) { + @Override + protected void hidePanel() + { + togglePreview(); + } + }; + + final IPreferenceStore preferences = getPreferenceStore(); + int ratio = preferences.getInt(VIEW_PANEL_RATIO); + boolean viewPanelVisible = preferences.getBoolean(VIEW_PANEL_VISIBLE); + if (ratio <= 0) { + ratio = 750; + } + resultsSash.setWeights(new int[]{ratio, 1000 - ratio}); + if (!viewPanelVisible) { + resultsSash.setMaximizedControl(spreadsheet); + } + previewPane.addListener(SWT.Resize, new Listener() { + @Override + public void handleEvent(Event event) + { + DBPDataSource dataSource = getDataSource(); + if (dataSource != null) { + if (!resultsSash.isDisposed()) { + int[] weights = resultsSash.getWeights(); + int ratio = weights[0]; + preferences.setValue(VIEW_PANEL_RATIO, ratio); + } + } + } + }); + } this.spreadsheet.addSelectionListener(new SelectionAdapter() { @Override @@ -76,7 +207,253 @@ public class SpreadsheetPresentation implements IResultSetPresentation, ISelecti fireSelectionChanged(new SpreadsheetSelectionImpl()); } }); + this.spreadsheet.addCursorChangeListener(new Listener() { + @Override + public void handleEvent(Event event) { + if (event.detail != SWT.DRAG && event.detail != SWT.DROP_DOWN) { + updateGridCursor((GridCell) event.data); + } + } + }); + + spreadsheet.addFocusListener(new FocusListener() { + @Override + public void focusGained(FocusEvent e) { + SpreadsheetPresentation.this.controller.updateEditControls(); + } + + @Override + public void focusLost(FocusEvent e) { + SpreadsheetPresentation.this.controller.updateEditControls(); + } + }); + + this.themeManager = controller.getSite().getWorkbenchWindow().getWorkbench().getThemeManager(); + this.themeChangeListener = new IPropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent event) { + if (event.getProperty().startsWith(ThemeConstants.RESULTS_PROP_PREFIX)) { + applyThemeSettings(); + } + } + }; + this.themeManager.addPropertyChangeListener(themeChangeListener); + + applyThemeSettings(); + + this.spreadsheet.addDisposeListener(new DisposeListener() { + @Override + public void widgetDisposed(DisposeEvent e) { + dispose(); + } + }); + } + + private void dispose() + { + closeEditors(); + clearData(); + + themeManager.removePropertyChangeListener(themeChangeListener); + + UIUtils.dispose(this.boldFont); + } + + public void scrollToRow(@NotNull RowPosition position) + { + boolean recordMode = controller.isRecordMode(); + ResultSetRow curRow = controller.getCurrentRow(); + ResultSetModel model = controller.getModel(); + switch (position) { + case FIRST: + if (recordMode) { + if (model.getRowCount() > 0) { + controller.setCurrentRow(model.getRow(0)); + } else { + controller.setCurrentRow(null); + } + } else { + spreadsheet.shiftCursor(0, -spreadsheet.getItemCount(), false); + } + break; + case PREVIOUS: + if (recordMode && curRow != null && curRow.getVisualNumber() > 0) { + controller.setCurrentRow(model.getRow(curRow.getVisualNumber() - 1)); + } else { + spreadsheet.shiftCursor(0, -1, false); + } + break; + case NEXT: + if (recordMode && curRow != null && curRow.getVisualNumber() < model.getRowCount() - 1) { + controller.setCurrentRow(model.getRow(curRow.getVisualNumber() + 1)); + } else { + spreadsheet.shiftCursor(0, 1, false); + } + break; + case LAST: + if (recordMode && model.getRowCount() > 0) { + controller.setCurrentRow(model.getRow(model.getRowCount() - 1)); + } else { + spreadsheet.shiftCursor(0, spreadsheet.getItemCount(), false); + } + break; + } + controller.updateEditControls(); + } + + @Nullable + @Override + public DBDAttributeBinding getCurrentAttribute() { + return curAttribute; + } + + @Override + public Object saveState() { + return curAttribute; + } + + @Override + public void restoreState(Object state) { + this.curAttribute = (DBDAttributeBinding) state; + ResultSetRow curRow = controller.getCurrentRow(); + if (curRow != null && this.curAttribute != null) { + spreadsheet.setCursor(new GridCell(curRow, this.curAttribute), false); + } + } + + private void updateGridCursor(GridCell cell) + { + boolean changed; + Object newCol = cell == null ? null : cell.col; + Object newRow = cell == null ? null : cell.row; + ResultSetRow curRow = controller.getCurrentRow(); + if (!controller.isRecordMode()) { + changed = curRow != newRow || curAttribute != newCol; + if (newRow instanceof ResultSetRow && newCol instanceof DBDAttributeBinding) { + curRow = (ResultSetRow) newRow; + curAttribute = (DBDAttributeBinding) newCol; + } + controller.setCurrentRow(curRow); + } else { + changed = curAttribute != newRow; + if (newRow instanceof DBDAttributeBinding) { + curAttribute = (DBDAttributeBinding) newRow; + } + } + if (changed) { + ResultSetPropertyTester.firePropertyChange(ResultSetPropertyTester.PROP_CAN_MOVE); + ResultSetPropertyTester.firePropertyChange(ResultSetPropertyTester.PROP_EDITABLE); + updateValueView(); + } + } + + @Nullable + public String copySelectionToString( + boolean copyHeader, + boolean copyRowNumbers, + boolean cut, + String delimiter, + DBDDisplayFormat format) + { + if (delimiter == null) { + delimiter = "\t"; + } + String lineSeparator = ContentUtils.getDefaultLineSeparator(); + List selectedColumns = spreadsheet.getColumnSelection(); + IGridLabelProvider labelProvider = spreadsheet.getLabelProvider(); + StringBuilder tdt = new StringBuilder(); + if (copyHeader) { + if (copyRowNumbers) { + tdt.append("#"); + } + for (Object column : selectedColumns) { + if (tdt.length() > 0) { + tdt.append(delimiter); + } + tdt.append(labelProvider.getText(column)); + } + tdt.append(lineSeparator); + } + + List selectedCells = spreadsheet.getCellSelection(); + + GridCell prevCell = null; + for (GridCell cell : selectedCells) { + if (prevCell == null || cell.row != prevCell.row) { + // Next row + if (prevCell != null && prevCell.col != cell.col) { + // Fill empty row tail + int prevColIndex = selectedColumns.indexOf(prevCell.col); + for (int i = prevColIndex; i < selectedColumns.size() - 1; i++) { + tdt.append(delimiter); + } + } + if (prevCell != null) { + tdt.append(lineSeparator); + } + if (copyRowNumbers) { + tdt.append(labelProvider.getText(cell.row)).append(delimiter); + } + } + if (prevCell != null && prevCell.col != cell.col) { + int prevColIndex = selectedColumns.indexOf(prevCell.col); + int curColIndex = selectedColumns.indexOf(cell.col); + for (int i = prevColIndex; i < curColIndex; i++) { + tdt.append(delimiter); + } + } + + boolean recordMode = controller.isRecordMode(); + DBDAttributeBinding column = (DBDAttributeBinding)(!recordMode ? cell.col : cell.row); + ResultSetRow row = (ResultSetRow) (!recordMode ? cell.row : cell.col); + Object value = controller.getModel().getCellValue(column, row); + String cellText = column.getValueHandler().getValueDisplayString( + column.getAttribute(), + value, + format); + tdt.append(cellText); + + if (cut) { + DBDValueController valueController = new SpreadsheetValueController( + controller, column, row, DBDValueController.EditType.NONE, null); + if (!valueController.isReadOnly()) { + valueController.updateValue(DBUtils.makeNullValue(valueController)); + } + } + + prevCell = cell; + } + + return tdt.toString(); + } + + public void pasteFromClipboard() + { + DBDAttributeBinding attr = getFocusAttribute(); + ResultSetRow row = controller.getCurrentRow(); + if (attr == null || row == null) { + return; + } + if (controller.isColumnReadOnly(attr)) { + // No inline editors for readonly columns + return; + } + try { + Object newValue = ResultSetUtils.getColumnValueFromClipboard(attr); + if (newValue == null) { + return; + } + new SpreadsheetValueController( + controller, + attr, + row, + DBDValueController.EditType.NONE, + null).updateValue(newValue); + } + catch (Exception e) { + UIUtils.showErrorDialog(spreadsheet.getShell(), "Cannot replace cell value", null, e); + } } @Override @@ -86,61 +463,522 @@ public class SpreadsheetPresentation implements IResultSetPresentation, ISelecti @Override public void refreshData(boolean refreshMetadata) { + // Cache preferences + IPreferenceStore preferenceStore = getPreferenceStore(); + showOddRows = preferenceStore.getBoolean(DBeaverPreferences.RESULT_SET_SHOW_ODD_ROWS); + showCelIcons = preferenceStore.getBoolean(DBeaverPreferences.RESULT_SET_SHOW_CELL_ICONS); + spreadsheet.refreshData(refreshMetadata); } @Override - public void updateValueView() { + public void formatData(boolean refreshData) { + if (refreshData) { + reorderResultSet(true, new Runnable() { + @Override + public void run() + { + spreadsheet.refreshData(false); + } + }); + } else if (!supportsDataFilter() && !controller.getModel().getDataFilter().hasOrdering()) { + reorderLocally(); + } + } + @Override + public void clearData() { + this.curAttribute = null; + this.columnOrder = SWT.NONE; } @Override - public void fillToolbar(IToolBarManager toolBar) { + public void updateValueView() { + spreadsheet.redrawGrid(); + previewValue(); + } + @Override + public void fillToolbar(@NotNull IToolBarManager toolBar) { + toolBar.add(ActionUtils.makeCommandContribution( + controller.getSite(), + SpreadsheetCommandHandler.CMD_TOGGLE_PREVIEW, + CommandContributionItem.STYLE_CHECK)); + } + + @Override + public void fillMenu(@NotNull IMenuManager menu) { + menu.add(ActionUtils.makeCommandContribution( + controller.getSite(), + SpreadsheetCommandHandler.CMD_TOGGLE_PREVIEW, + CommandContributionItem.STYLE_CHECK)); } @Override public void changeMode(boolean recordMode) { + ResultSetRow oldRow = controller.getCurrentRow(); + DBDAttributeBinding oldAttribute = this.curAttribute; + int rowCount = controller.getModel().getRowCount(); + if (rowCount > 0) { + // Fix row number if needed + if (oldRow == null) { + oldRow = controller.getModel().getRow(0); + } else if (oldRow.getVisualNumber() >= rowCount) { + oldRow = controller.getModel().getRow(rowCount - 1); + } + } + if (oldAttribute == null && controller.getModel().getVisibleColumnCount() > 0) { + oldAttribute = controller.getModel().getVisibleColumn(0); + } + this.columnOrder = recordMode ? SWT.DEFAULT : SWT.NONE; + if (oldRow != null && oldAttribute != null) { + if (!recordMode) { + spreadsheet.setCursor(new GridCell(oldAttribute, oldRow), false); + } else { + spreadsheet.setCursor(new GridCell(oldRow, oldAttribute), false); + } + } + spreadsheet.layout(true, true); + previewValue(); + controller.setCurrentRow(oldRow); } public void fillContextMenu(@Nullable Object colObject, @Nullable Object rowObject, @NotNull IMenuManager manager) { final DBDAttributeBinding attr = (DBDAttributeBinding)(controller.isRecordMode() ? rowObject : colObject); final ResultSetRow row = (ResultSetRow)(controller.isRecordMode() ? colObject : rowObject); controller.fillContextMenu(manager, attr, row); + + if (attr != null && row != null && row.isChanged()) { + IMenuManager editMenu = manager.findMenuUsingPath(IResultSetController.MENU_GROUP_EDIT); + if (editMenu != null) { + { + Action resetValueAction = new Action(CoreMessages.controls_resultset_viewer_action_reset_value) { + @Override + public void run() { + resetCellValue(attr, row, false); + } + }; + resetValueAction.setAccelerator(SWT.ESC); + editMenu.add(resetValueAction); + } + + { + final List selectedColumns = spreadsheet.getColumnSelection(); + if (!controller.isRecordMode() && !selectedColumns.isEmpty()) { + String hideTitle; + if (selectedColumns.size() == 1) { + DBDAttributeBinding columnToHide = (DBDAttributeBinding) selectedColumns.get(0); + hideTitle = "Hide column '" + columnToHide.getName() + "'"; + } else { + hideTitle = "Hide selected columns (" + selectedColumns.size() + ")"; + } + editMenu.add(new Action(hideTitle) { + @Override + public void run() + { + ResultSetModel model = controller.getModel(); + if (selectedColumns.size() >= model.getVisibleColumnCount()) { + UIUtils.showMessageBox(getControl().getShell(), "Hide columns", "Can't hide all result columns, at least one column must be visible", SWT.ERROR); + } else { + int[] columnIndexes = new int[selectedColumns.size()]; + for (int i = 0, selectedColumnsSize = selectedColumns.size(); i < selectedColumnsSize; i++) { + columnIndexes[i] = model.getVisibleColumnIndex((DBDAttributeBinding) selectedColumns.get(i)); + } + Arrays.sort(columnIndexes); + for (int i = columnIndexes.length; i > 0; i--) { + model.setColumnVisibility(model.getVisibleColumn(columnIndexes[i - 1]), false); + } + controller.redrawData(true); + } + } + }); + } + } + } + } } - public Control showCellEditor(boolean inline) { - return ((ResultSetViewer)controller).showCellEditor(inline); + //////////////////////////////////////////////////////////// + // Value preview + + public boolean isPreviewVisible() + { + return resultsSash.getMaximizedControl() == null; + } + + public void togglePreview() + { + if (resultsSash.getMaximizedControl() == null) { + resultsSash.setMaximizedControl(spreadsheet); + } else { + resultsSash.setMaximizedControl(null); + previewValue(); + } + getPreferenceStore().setValue(VIEW_PANEL_VISIBLE, isPreviewVisible()); + + // Refresh elements + ICommandService commandService = (ICommandService) controller.getSite().getService(ICommandService.class); + if (commandService != null) { + commandService.refreshElements(SpreadsheetCommandHandler.CMD_TOGGLE_PREVIEW, null); + } } - public void resetCellValue(@NotNull Object col, @NotNull Object row, boolean delete) { - ((ResultSetViewer)controller).resetCellValue(col, row, delete); + void previewValue() + { + DBDAttributeBinding attr = getFocusAttribute(); + ResultSetRow row = getFocusRow(); + if (!isPreviewVisible() || attr == null || row == null) { + return; + } + if (panelValueController == null || panelValueController.getBinding() != attr) { + panelValueController = new SpreadsheetValueController( + controller, + attr, + row, + DBDValueController.EditType.PANEL, + previewPane.getViewPlaceholder()); + } else { + panelValueController.setCurRow(row); + } + previewPane.viewValue(panelValueController); } - public void changeSorting(Object columnElement, int state) { - ((ResultSetViewer)controller).changeSorting(columnElement, state); + ///////////////////////////////////////////////// + // Edit + + private void closeEditors() { + List editors = new ArrayList(openEditors.values()); + for (DBDValueEditorStandalone editor : editors) { + editor.closeValueEditor(); + } + if (!openEditors.isEmpty()) { + log.warn("Some value editors are still registered at result set: " + openEditors.size()); + } + openEditors.clear(); } + @Nullable + public Control openValueEditor(final boolean inline) + { + // The control that will be the editor must be a child of the Table + DBDAttributeBinding attr = getFocusAttribute(); + ResultSetRow row = getFocusRow(); + if (attr == null || row == null) { + return null; + } + + if (!inline) { + for (SpreadsheetValueController valueController : openEditors.keySet()) { + if (attr == valueController.getBinding() && row == valueController.getCurRow()) { + openEditors.get(valueController).showValueEditor(); + return null; + } + } + } + final int handlerFeatures = attr.getValueHandler().getFeatures(); + if (handlerFeatures == DBDValueHandler.FEATURE_NONE) { + return null; + } + if (inline && + (handlerFeatures & DBDValueHandler.FEATURE_INLINE_EDITOR) == 0 && + (handlerFeatures & DBDValueHandler.FEATURE_VIEWER) != 0) + { + // Inline editor isn't supported but panel viewer is + // Enable panel + if (!isPreviewVisible()) { + togglePreview(); + } + return null; + } + if (controller.isColumnReadOnly(attr) && inline) { + // No inline editors for readonly columns + return null; + } + + Composite placeholder = null; + if (inline) { + if (controller.isReadOnly()) { + return null; + } + spreadsheet.cancelInlineEditor(); + + placeholder = new Composite(spreadsheet, SWT.NONE); + placeholder.setFont(spreadsheet.getFont()); + placeholder.setLayout(new FillLayout()); + + GridData gd = new GridData(GridData.FILL_BOTH); + gd.horizontalIndent = 0; + gd.verticalIndent = 0; + gd.grabExcessHorizontalSpace = true; + gd.grabExcessVerticalSpace = true; + placeholder.setLayoutData(gd); + } + + SpreadsheetValueController valueController = new SpreadsheetValueController( + controller, + attr, + row, + inline ? DBDValueController.EditType.INLINE : DBDValueController.EditType.EDITOR, + placeholder); + final DBDValueEditor editor; + try { + editor = attr.getValueHandler().createEditor(valueController); + } + catch (Exception e) { + UIUtils.showErrorDialog(spreadsheet.getShell(), "Cannot edit value", null, e); + return null; + } + if (editor != null) { + editor.createControl(); + } + if (editor instanceof DBDValueEditorStandalone) { + valueController.registerEditor((DBDValueEditorStandalone)editor); + // show dialog in separate job to avoid block + new UIJob("Open separate editor") { + @Override + public IStatus runInUIThread(IProgressMonitor monitor) + { + ((DBDValueEditorStandalone)editor).showValueEditor(); + return Status.OK_STATUS; + } + }.schedule(); + //((DBDValueEditorStandalone)editor).showValueEditor(); + } else { + // Set editable value + if (editor != null) { + try { + editor.primeEditorValue(valueController.getValue()); + } catch (DBException e) { + log.error(e); + } + } + } + if (inline) { + if (editor != null) { + spreadsheet.showCellEditor(placeholder); + return editor.getControl(); + } else { + // No editor was created so just drop placeholder + placeholder.dispose(); + // Probably we can just show preview panel + if ((handlerFeatures & DBDValueHandler.FEATURE_VIEWER) != 0) { + // Inline editor isn't supported but panel viewer is + // Enable panel + if (!isPreviewVisible()) { + togglePreview(); + } + return null; + } + } + } + return null; + } + + public void resetCellValue(@NotNull Object colElement, @NotNull Object rowElement, boolean delete) + { + boolean recordMode = controller.isRecordMode(); + final DBDAttributeBinding attr = (DBDAttributeBinding)(recordMode ? rowElement : colElement); + final ResultSetRow row = (ResultSetRow)(recordMode ? colElement : rowElement); + controller.getModel().resetCellValue(attr, row); + updateValueView(); + } + + /////////////////////////////////////////////// + // Links + public void navigateLink(@NotNull GridCell cell, int state) { - ((ResultSetViewer)controller).navigateLink(cell, state); + boolean recordMode = controller.isRecordMode(); + final DBDAttributeBinding attr = (DBDAttributeBinding)(recordMode ? cell.row : cell.col); + final ResultSetRow row = (ResultSetRow)(recordMode ? cell.col : cell.row); + + Object value = controller.getModel().getCellValue(attr, row); + if (DBUtils.isNullValue(value)) { + log.warn("Can't navigate to NULL value"); + return; + } + + try { + DBeaverUI.runInProgressService(new DBRRunnableWithProgress() { + @Override + public void run(DBRProgressMonitor monitor) throws InvocationTargetException, InterruptedException { + try { + controller.navigateAssociation(monitor, attr, row); + } catch (DBException e) { + throw new InvocationTargetException(e); + } + } + }); + } catch (InvocationTargetException e) { + UIUtils.showErrorDialog(spreadsheet.getShell(), "Cannot navigate to the reference", null, e.getTargetException()); + } catch (InterruptedException e) { + // ignore + } + } + + /////////////////////////////////////////////// + // Themes + + private void applyThemeSettings() + { + ITheme currentTheme = themeManager.getCurrentTheme(); + Font rsFont = currentTheme.getFontRegistry().get(ThemeConstants.FONT_SQL_RESULT_SET); + if (rsFont != null) { + this.spreadsheet.setFont(rsFont); + } + Color previewBack = currentTheme.getColorRegistry().get(ThemeConstants.COLOR_SQL_RESULT_SET_PREVIEW_BACK); + if (previewBack != null) { + this.previewPane.getViewPlaceholder().setBackground(previewBack); + for (Control control : this.previewPane.getViewPlaceholder().getChildren()) { + control.setBackground(previewBack); + } + } + this.backgroundAdded = currentTheme.getColorRegistry().get(ThemeConstants.COLOR_SQL_RESULT_CELL_NEW_BACK); + this.backgroundDeleted = currentTheme.getColorRegistry().get(ThemeConstants.COLOR_SQL_RESULT_CELL_DELETED_BACK); + this.backgroundModified = currentTheme.getColorRegistry().get(ThemeConstants.COLOR_SQL_RESULT_CELL_MODIFIED_BACK); + this.backgroundOdd = currentTheme.getColorRegistry().get(ThemeConstants.COLOR_SQL_RESULT_CELL_ODD_BACK); + this.backgroundReadOnly = currentTheme.getColorRegistry().get(ThemeConstants.COLOR_SQL_RESULT_CELL_READ_ONLY); + + this.spreadsheet.recalculateSizes(); } + /////////////////////////////////////////////// + // Ordering + + private boolean supportsDataFilter() + { + DBSDataContainer dataContainer = controller.getDataContainer(); + return dataContainer != null && + (dataContainer.getSupportedFeatures() & DBSDataContainer.DATA_FILTER) == DBSDataContainer.DATA_FILTER; + } + + private boolean isServerSideFiltering() + { + return + getPreferenceStore().getBoolean(DBeaverPreferences.RESULT_SET_ORDER_SERVER_SIDE) && + (controller.isHasMoreData() || !CommonUtils.isEmpty(controller.getModel().getDataFilter().getOrder())); + } + + private void reorderResultSet(boolean force, @Nullable Runnable onSuccess) + { + if (force || isServerSideFiltering() && supportsDataFilter()) { + controller.refreshData(onSuccess); + return; + } + + try { + reorderLocally(); + } finally { + if (onSuccess != null) { + onSuccess.run(); + } + } + } + + private void reorderLocally() + { + controller.rejectChanges(); + controller.getModel().resetOrdering(); + } + + public void changeSorting(Object columnElement, final int state) + { + if (columnElement == null) { + columnOrder = columnOrder == SWT.DEFAULT ? SWT.DOWN : (columnOrder == SWT.DOWN ? SWT.UP : SWT.DEFAULT); + spreadsheet.refreshData(false); + spreadsheet.redrawGrid(); + return; + } + DBDDataFilter dataFilter = controller.getModel().getDataFilter(); + boolean ctrlPressed = (state & SWT.CTRL) == SWT.CTRL; + boolean altPressed = (state & SWT.ALT) == SWT.ALT; + if (ctrlPressed) { + dataFilter.resetOrderBy(); + } + DBDAttributeBinding metaColumn = (DBDAttributeBinding)columnElement; + DBDAttributeConstraint constraint = dataFilter.getConstraint(metaColumn); + assert constraint != null; + //int newSort; + if (constraint.getOrderPosition() == 0) { + if (isServerSideFiltering() && supportsDataFilter()) { + if (!ConfirmationDialog.confirmActionWithParams( + spreadsheet.getShell(), + DBeaverPreferences.CONFIRM_ORDER_RESULTSET, + metaColumn.getName())) + { + return; + } + } + constraint.setOrderPosition(dataFilter.getMaxOrderingPosition() + 1); + constraint.setOrderDescending(altPressed); + } else if (!constraint.isOrderDescending()) { + constraint.setOrderDescending(true); + } else { + for (DBDAttributeConstraint con2 : dataFilter.getConstraints()) { + if (con2.getOrderPosition() > constraint.getOrderPosition()) { + con2.setOrderPosition(con2.getOrderPosition() - 1); + } + } + constraint.setOrderPosition(0); + constraint.setOrderDescending(false); + } + + // Reorder + reorderResultSet(false, new Runnable() { + @Override + public void run() + { + if (!controller.isRecordMode()) { + spreadsheet.refreshData(false); + } + } + }); + } + + + /////////////////////////////////////////////// + // Misc + public IPreferenceStore getPreferenceStore() { return controller.getPreferenceStore(); } @Override public Object getAdapter(Class adapter) { - if (adapter == IFindReplaceTarget.class) { + if (adapter == IPropertySheetPage.class) { + // Show cell properties + PropertyPageStandard page = new PropertyPageStandard(); + page.setPropertySourceProvider(new IPropertySourceProvider() { + @Nullable + @Override + public IPropertySource getPropertySource(Object object) + { + if (object instanceof GridCell) { + GridCell cell = (GridCell) object; + boolean recordMode = controller.isRecordMode(); + final DBDAttributeBinding attr = (DBDAttributeBinding)(recordMode ? cell.row : cell.col); + final ResultSetRow row = (ResultSetRow)(recordMode ? cell.col : cell.row); + final SpreadsheetValueController valueController = new SpreadsheetValueController( + controller, + attr, + row, + DBDValueController.EditType.NONE, + null); + PropertyCollector props = new PropertyCollector(valueController.getBinding().getAttribute(), false); + props.collectProperties(); + valueController.getValueHandler().contributeProperties(props, valueController); + return props; + } + return null; + } + }); + return page; + } else if (adapter == IFindReplaceTarget.class) { return findReplaceTarget; } return null; } - /////////////////////////////////////////////// - // Misc - @Nullable public DBDAttributeBinding getFocusAttribute() { @@ -273,4 +1111,391 @@ public class SpreadsheetPresentation implements IResultSetPresentation, ISelecti } } } + + private class ContentProvider implements IGridContentProvider { + + @NotNull + @Override + public Object[] getElements(boolean horizontal) { + boolean recordMode = controller.isRecordMode(); + ResultSetModel model = controller.getModel(); + if (horizontal) { + // columns + if (!recordMode) { + return model.getVisibleColumns().toArray(); + } else { + Object curRow = controller.getCurrentRow(); + return curRow == null ? new Object[0] : new Object[] {curRow}; + } + } else { + // rows + if (!recordMode) { + return model.getAllRows().toArray(); + } else { + DBDAttributeBinding[] columns = model.getVisibleColumns().toArray(new DBDAttributeBinding[model.getVisibleColumnCount()]); + if (columnOrder != SWT.NONE && columnOrder != SWT.DEFAULT) { + Arrays.sort(columns, new Comparator() { + @Override + public int compare(DBDAttributeBinding o1, DBDAttributeBinding o2) { + return o1.getName().compareTo(o2.getName()) * (columnOrder == SWT.DOWN ? 1 : -1); + } + }); + } + return columns; + } + } + } + + @Nullable + @Override + public Object[] getChildren(Object element) { + if (element instanceof DBDAttributeBinding) { + DBDAttributeBinding binding = (DBDAttributeBinding) element; + switch (binding.getDataKind()) { + case ARRAY: + if (controller.isRecordMode()) { + ResultSetRow curRow = controller.getCurrentRow(); + if (curRow != null) { + Object value = controller.getModel().getCellValue(binding, curRow); + if (value instanceof DBDCollection) { + return curRow.getCollectionData( + binding, + ((DBDCollection)value)).getElements(); + } + } + return null; + } + case STRUCT: + case ANY: + if (binding.getNestedBindings() != null) { + return binding.getNestedBindings().toArray(); + } + break; + } + } + + return null; + } + + @Override + public int getSortOrder(@Nullable Object column) + { + if (column instanceof DBDAttributeBinding) { + DBDAttributeBinding binding = (DBDAttributeBinding) column; + if (!binding.hasNestedBindings()) { + DBDAttributeConstraint co = controller.getModel().getDataFilter().getConstraint(binding); + if (co != null && co.getOrderPosition() > 0) { + return co.isOrderDescending() ? SWT.UP : SWT.DOWN; + } + return SWT.DEFAULT; + } + } else if (column == null && controller.isRecordMode()) { + // Columns order in record mode + return columnOrder; + } + return SWT.NONE; + } + + @Override + public ElementState getDefaultState(@NotNull Object element) { + if (element instanceof DBDAttributeBinding) { + DBDAttributeBinding binding = (DBDAttributeBinding) element; + switch (binding.getAttribute().getDataKind()) { + case STRUCT: + return ElementState.EXPANDED; + case ARRAY: + ResultSetRow curRow = controller.getCurrentRow(); + if (curRow != null) { + Object cellValue = controller.getModel().getCellValue(binding, curRow); + if (cellValue instanceof DBDCollection && ((DBDCollection) cellValue).getItemCount() < 3) { + return ElementState.EXPANDED; + } + } + return ElementState.COLLAPSED; + default: + break; + } + } + return ElementState.NONE; + } + + @Override + public int getCellState(Object colElement, Object rowElement) { + int state = STATE_NONE; + boolean recordMode = controller.isRecordMode(); + DBDAttributeBinding attr = (DBDAttributeBinding)(recordMode ? rowElement : colElement); + ResultSetRow row = (ResultSetRow)(recordMode ? colElement : rowElement); + Object value = controller.getModel().getCellValue(attr, row); + if (!CommonUtils.isEmpty(attr.getReferrers()) && !DBUtils.isNullValue(value)) { + state |= STATE_LINK; + } + return state; + } + + @Override + public void dispose() + { + } + + @Override + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) + { + } + + @Nullable + @Override + public Object getCellValue(Object colElement, Object rowElement, boolean formatString) + { + DBDAttributeBinding attr = (DBDAttributeBinding)(rowElement instanceof DBDAttributeBinding ? rowElement : colElement); + ResultSetRow row = (ResultSetRow)(colElement instanceof ResultSetRow ? colElement : rowElement); + int rowNum = row.getVisualNumber(); + Object value = controller.getModel().getCellValue(attr, row); + + boolean recordMode = controller.isRecordMode(); + if (rowNum > 0 && rowNum == controller.getModel().getRowCount() - 1 && (recordMode || spreadsheet.isRowVisible(rowNum)) && controller.isHasMoreData()) { + controller.readNextSegment(); + } + + if (formatString) { + if (recordMode) { + if (attr.getDataKind() == DBPDataKind.ARRAY && value instanceof DBDCollection) { + return "[" + ((DBDCollection) value).getItemCount() + "]"; + } else if (attr.getDataKind() == DBPDataKind.STRUCT && value instanceof DBDStructure) { + return "[" + ((DBDStructure) value).getDataType().getName() + "]"; + } + } + return attr.getValueHandler().getValueDisplayString( + attr.getAttribute(), + value, + DBDDisplayFormat.UI); + } else { + return value; + } + } + + @Nullable + @Override + public Image getCellImage(Object colElement, Object rowElement) + { + if (!showCelIcons) { + return null; + } + DBDAttributeBinding attr = (DBDAttributeBinding)(controller.isRecordMode() ? rowElement : colElement); + if ((attr.getValueHandler().getFeatures() & DBDValueHandler.FEATURE_SHOW_ICON) != 0) { + return DBUtils.getTypeImage(attr.getMetaAttribute()); + } else { + return null; + } + } + + @NotNull + @Override + public String getCellText(Object colElement, Object rowElement) + { + return String.valueOf(getCellValue(colElement, rowElement, true)); + } + + @Nullable + @Override + public Color getCellForeground(Object colElement, Object rowElement) + { + Object value = getCellValue(colElement, rowElement, false); + if (DBUtils.isNullValue(value)) { + return foregroundNull; + } else { + if (foregroundDefault == null) { + foregroundDefault = controller.getDefaultForeground(); + } + return foregroundDefault; + } + } + + @Nullable + @Override + public Color getCellBackground(Object colElement, Object rowElement) + { + boolean recordMode = controller.isRecordMode(); + ResultSetRow row = (ResultSetRow) (!recordMode ? rowElement : colElement); + DBDAttributeBinding attribute = (DBDAttributeBinding)(!recordMode ? colElement : rowElement); + boolean odd = row.getVisualNumber() % 2 == 0; + + if (row.getState() == ResultSetRow.STATE_ADDED) { + return backgroundAdded; + } + if (row.getState() == ResultSetRow.STATE_REMOVED) { + return backgroundDeleted; + } + if (row.changes != null && row.changes.containsKey(attribute)) { + return backgroundModified; + } + if ((attribute.getValueHandler().getFeatures() & DBDValueHandler.FEATURE_COMPOSITE) != 0) { + return backgroundReadOnly; + } + if (!recordMode && odd && showOddRows) { + return backgroundOdd; + } + + if (backgroundNormal == null) { + backgroundNormal = controller.getDefaultBackground(); + } + return backgroundNormal; + } + + @Override + public void resetColors() { + backgroundNormal = null; + foregroundDefault = null; + } + } + + private class GridLabelProvider implements IGridLabelProvider { + @Nullable + @Override + public Image getImage(Object element) + { + if (element instanceof DBDAttributeBinding/* && (!isRecordMode() || !model.isDynamicMetadata())*/) { + return DBUtils.getTypeImage(((DBDAttributeBinding) element).getMetaAttribute()); + } + return null; + } + + @Nullable + @Override + public Color getForeground(Object element) { + if (element == null) { + if (foregroundDefault == null) { + foregroundDefault = controller.getDefaultForeground(); + } + return foregroundDefault; + } + return null; + } + + @Nullable + @Override + public Color getBackground(Object element) { + if (backgroundNormal == null) { + backgroundNormal = controller.getDefaultBackground(); + } + if (element == null) { + return backgroundNormal; + } + +/* + ResultSetRow row = (ResultSetRow) (!recordMode ? element : curRow); + boolean odd = row != null && row.getVisualNumber() % 2 == 0; + if (!recordMode && odd && showOddRows) { + return backgroundOdd; + } + return backgroundNormal; +*/ + return null; + } + + @NotNull + @Override + public String getText(Object element) + { + if (element instanceof DBDAttributeBinding) { + DBDAttributeBinding attributeBinding = (DBDAttributeBinding) element; + if (CommonUtils.isEmpty(attributeBinding.getLabel())) { + return attributeBinding.getName(); + } else { + return attributeBinding.getLabel(); + } + } else { + if (!controller.isRecordMode()) { + return String.valueOf(((ResultSetRow)element).getVisualNumber() + 1); + } else { + return CoreMessages.controls_resultset_viewer_value; + } + } + } + + @Nullable + @Override + public Font getFont(Object element) + { + if (element instanceof DBDAttributeBinding) { + DBDAttributeBinding attributeBinding = (DBDAttributeBinding) element; + DBDAttributeConstraint constraint = controller.getModel().getDataFilter().getConstraint(attributeBinding); + if (constraint != null && constraint.hasFilter()) { + return boldFont; + } + } + return null; + } + + @Nullable + @Override + public String getTooltip(Object element) + { + if (element instanceof DBDAttributeBinding) { + DBDAttributeBinding attributeBinding = (DBDAttributeBinding) element; + String name = attributeBinding.getName(); + String typeName = DBUtils.getFullTypeName(attributeBinding.getAttribute()); + return name + ": " + typeName; + } + return null; + } + } + + ///////////////////////////// + // Value controller + + public class SpreadsheetValueController extends ResultSetValueController { + + public SpreadsheetValueController(@NotNull IResultSetController controller, @NotNull DBDAttributeBinding binding, @NotNull ResultSetRow row, @NotNull EditType editType, @Nullable Composite inlinePlaceholder) { + super(controller, binding, row, editType, inlinePlaceholder); + } + + @Override + public Object getValue() + { + return spreadsheet.getContentProvider().getCellValue(curRow, binding, false); + } + + @Nullable + @Override + public ToolBar getEditToolBar() + { + return isPreviewVisible() ? previewPane.getToolBar() : null; + } + + @Override + public void closeInlineEditor() + { + spreadsheet.cancelInlineEditor(); + } + + @Override + public void nextInlineEditor(boolean next) { + spreadsheet.cancelInlineEditor(); + int colOffset = next ? 1 : -1; + int rowOffset = 0; + //final int rowCount = spreadsheet.getItemCount(); + final int colCount = spreadsheet.getColumnCount(); + final GridPos curPosition = spreadsheet.getCursorPosition(); + if (colOffset > 0 && curPosition.col + colOffset >= colCount) { + colOffset = -colCount; + rowOffset = 1; + } else if (colOffset < 0 && curPosition.col + colOffset < 0) { + colOffset = colCount; + rowOffset = -1; + } + spreadsheet.shiftCursor(colOffset, rowOffset, false); + openValueEditor(true); + } + + public void registerEditor(DBDValueEditorStandalone editor) { + openEditors.put(this, editor); + } + + @Override + public void unregisterEditor(DBDValueEditorStandalone editor) { + openEditors.remove(this); + } + + } + } diff --git a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/ResultSetModeTogglePreviewHandler.java b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/spreadsheet/SpreadsheetTogglePreviewHandler.java similarity index 75% rename from plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/ResultSetModeTogglePreviewHandler.java rename to plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/spreadsheet/SpreadsheetTogglePreviewHandler.java index 0c12fb805ee8ee099d93fe4331af0e4a5d73827b..0c80a30c7f11be127ff666d5d7d9c826beb0d931 100644 --- a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/ResultSetModeTogglePreviewHandler.java +++ b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/spreadsheet/SpreadsheetTogglePreviewHandler.java @@ -16,18 +16,21 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -package org.jkiss.dbeaver.ui.controls.resultset; +package org.jkiss.dbeaver.ui.controls.resultset.spreadsheet; import org.eclipse.ui.IWorkbenchPartSite; import org.eclipse.ui.commands.IElementUpdater; import org.eclipse.ui.menus.UIElement; +import org.jkiss.dbeaver.ui.controls.resultset.IResultSetContainer; +import org.jkiss.dbeaver.ui.controls.resultset.IResultSetPresentation; +import org.jkiss.dbeaver.ui.controls.resultset.ResultSetViewer; import java.util.Map; /** * ResultSetModeTogglePreviewHandler */ -public class ResultSetModeTogglePreviewHandler extends ResultSetCommandHandler implements IElementUpdater { +public class SpreadsheetTogglePreviewHandler extends SpreadsheetCommandHandler implements IElementUpdater { @Override public void updateElement(UIElement element, Map parameters) @@ -37,7 +40,8 @@ public class ResultSetModeTogglePreviewHandler extends ResultSetCommandHandler i if (partSite.getPart() instanceof IResultSetContainer) { ResultSetViewer rsv = ((IResultSetContainer) partSite.getPart()).getResultSetViewer(); if (rsv != null) { - if (rsv.isPreviewVisible()) { + IResultSetPresentation presentation = rsv.getActivePresentation(); + if (presentation instanceof SpreadsheetPresentation && ((SpreadsheetPresentation) presentation).isPreviewVisible()) { element.setText("Hide value view panel"); element.setChecked(true); } else { diff --git a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/ThemeConstants.java b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/spreadsheet/ThemeConstants.java similarity index 95% rename from plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/ThemeConstants.java rename to plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/spreadsheet/ThemeConstants.java index 6407fc9408bdb619860ef7ba0eedfe0339dc0b94..9ff35676422cb9e7f9fcc06577ca44d6c2b6a05d 100644 --- a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/ThemeConstants.java +++ b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/spreadsheet/ThemeConstants.java @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -package org.jkiss.dbeaver.ui.controls.resultset; +package org.jkiss.dbeaver.ui.controls.resultset.spreadsheet; /** * ThemeConstants diff --git a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/ViewValuePanel.java b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/spreadsheet/ViewValuePanel.java similarity index 96% rename from plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/ViewValuePanel.java rename to plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/spreadsheet/ViewValuePanel.java index 3f9df9089fed4a6c02423a6bf9af556a6db5a9b9..71907f4e9a7a1f00a2fab8cfef0f2f903c342423 100644 --- a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/ViewValuePanel.java +++ b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/spreadsheet/ViewValuePanel.java @@ -16,7 +16,7 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -package org.jkiss.dbeaver.ui.controls.resultset; +package org.jkiss.dbeaver.ui.controls.resultset.spreadsheet; import org.eclipse.swt.events.TraverseEvent; import org.eclipse.swt.events.TraverseListener; diff --git a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/view/EmptyPresentation.java b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/view/EmptyPresentation.java index e4e4d0084a7170c066c8e4911cfcae3fd14c6d48..791fb453fd9acba8aaec3b8479a34d49732e1e7b 100644 --- a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/view/EmptyPresentation.java +++ b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/view/EmptyPresentation.java @@ -19,10 +19,15 @@ package org.jkiss.dbeaver.ui.controls.resultset.view; +import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.IToolBarManager; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; +import org.jkiss.code.NotNull; +import org.jkiss.code.Nullable; +import org.jkiss.dbeaver.model.data.DBDAttributeBinding; +import org.jkiss.dbeaver.model.data.DBDDisplayFormat; import org.jkiss.dbeaver.ui.controls.resultset.IResultSetController; import org.jkiss.dbeaver.ui.controls.resultset.IResultSetPresentation; @@ -35,7 +40,7 @@ public class EmptyPresentation implements IResultSetPresentation { private Composite placeholder; @Override - public void createPresentation(IResultSetController controller, Composite parent) { + public void createPresentation(@NotNull IResultSetController controller, @NotNull Composite parent) { placeholder = new Composite(parent, SWT.NONE); } @@ -49,13 +54,28 @@ public class EmptyPresentation implements IResultSetPresentation { } + @Override + public void formatData(boolean refreshData) { + + } + + @Override + public void clearData() { + + } + @Override public void updateValueView() { } @Override - public void fillToolbar(IToolBarManager toolBar) { + public void fillToolbar(@NotNull IToolBarManager toolBar) { + + } + + @Override + public void fillMenu(@NotNull IMenuManager menu) { } @@ -64,4 +84,32 @@ public class EmptyPresentation implements IResultSetPresentation { } + @Override + public void scrollToRow(@NotNull RowPosition position) { + + } + + @Nullable + @Override + public DBDAttributeBinding getCurrentAttribute() { + return null; + } + + @Nullable + @Override + public Control openValueEditor(boolean inline) { + return null; + } + + @Nullable + @Override + public String copySelectionToString(boolean copyHeader, boolean copyRowNumbers, boolean cut, String delimiter, DBDDisplayFormat format) { + return null; + } + + @Override + public void pasteFromClipboard() { + + } + } diff --git a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/view/StatisticsPresentation.java b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/view/StatisticsPresentation.java index 9994057b1ef91dd6f7a82ec128fe7c796c045347..d5b3842f2e1704f7319a66665f17fcf2c3d04da4 100644 --- a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/view/StatisticsPresentation.java +++ b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/controls/resultset/view/StatisticsPresentation.java @@ -19,11 +19,16 @@ package org.jkiss.dbeaver.ui.controls.resultset.view; +import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.IToolBarManager; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; +import org.jkiss.code.NotNull; +import org.jkiss.code.Nullable; +import org.jkiss.dbeaver.model.data.DBDAttributeBinding; +import org.jkiss.dbeaver.model.data.DBDDisplayFormat; import org.jkiss.dbeaver.ui.controls.resultset.IResultSetController; import org.jkiss.dbeaver.ui.controls.resultset.IResultSetPresentation; @@ -36,7 +41,7 @@ public class StatisticsPresentation implements IResultSetPresentation { private TableViewer tableViewer; @Override - public void createPresentation(IResultSetController controller, Composite parent) { + public void createPresentation(@NotNull IResultSetController controller, @NotNull Composite parent) { tableViewer = new TableViewer(parent, SWT.MULTI | SWT.FULL_SELECTION); } @@ -50,13 +55,28 @@ public class StatisticsPresentation implements IResultSetPresentation { tableViewer.refresh(); } + @Override + public void formatData(boolean refreshData) { + + } + + @Override + public void clearData() { + + } + @Override public void updateValueView() { } @Override - public void fillToolbar(IToolBarManager toolBar) { + public void fillToolbar(@NotNull IToolBarManager toolBar) { + + } + + @Override + public void fillMenu(@NotNull IMenuManager menu) { } @@ -65,4 +85,32 @@ public class StatisticsPresentation implements IResultSetPresentation { } + @Override + public void scrollToRow(@NotNull RowPosition position) { + + } + + @Nullable + @Override + public DBDAttributeBinding getCurrentAttribute() { + return null; + } + + @Nullable + @Override + public Control openValueEditor(boolean inline) { + return null; + } + + @Nullable + @Override + public String copySelectionToString(boolean copyHeader, boolean copyRowNumbers, boolean cut, String delimiter, DBDDisplayFormat format) { + return null; + } + + @Override + public void pasteFromClipboard() { + + } + } diff --git a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/editors/data/DatabaseDataEditor.java b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/editors/data/DatabaseDataEditor.java index 71179a7abeaba9c814cbbc67c7d167ab746c7776..d9e10bcbf038b1ea8ac664bda3777cc6d5142071 100644 --- a/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/editors/data/DatabaseDataEditor.java +++ b/plugins/org.jkiss.dbeaver.core/src/org/jkiss/dbeaver/ui/editors/data/DatabaseDataEditor.java @@ -132,7 +132,7 @@ public class DatabaseDataEditor extends AbstractDatabaseObjectEditor