提交 31c63e76 编写于 作者: J jurgen

RSV refactoring.

Presentations support
上级 c3f2c949
......@@ -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
......
......@@ -222,7 +222,6 @@
<command id="org.jkiss.dbeaver.core.compare.objects" name="%command.org.jkiss.dbeaver.core.compare.objects.name" description="%command.org.jkiss.dbeaver.core.compare.objects.description" categoryId="org.jkiss.dbeaver.core.util"/>
<command id="org.jkiss.dbeaver.core.resultset.toggleMode" name="%command.org.jkiss.dbeaver.core.resultset.toggleMode.name" description="%command.org.jkiss.dbeaver.core.resultset.toggleMode.description" categoryId="org.jkiss.dbeaver.core.rs"/>
<command id="org.jkiss.dbeaver.core.resultset.togglePreview" name="%command.org.jkiss.dbeaver.core.resultset.togglePreview.name" description="%command.org.jkiss.dbeaver.core.resultset.togglePreview.description" categoryId="org.jkiss.dbeaver.core.rs"/>
<command id="org.jkiss.dbeaver.core.resultset.row.first" name="%command.org.jkiss.dbeaver.core.resultset.row.first.name" description="%command.org.jkiss.dbeaver.core.resultset.row.first.description" categoryId="org.jkiss.dbeaver.core.rs"/>
<command id="org.jkiss.dbeaver.core.resultset.row.previous" name="%command.org.jkiss.dbeaver.core.resultset.row.previous.name" description="%command.org.jkiss.dbeaver.core.resultset.row.previous.description" categoryId="org.jkiss.dbeaver.core.rs"/>
<command id="org.jkiss.dbeaver.core.resultset.row.next" name="%command.org.jkiss.dbeaver.core.resultset.row.next.name" description="%command.org.jkiss.dbeaver.core.resultset.row.next.description" categoryId="org.jkiss.dbeaver.core.rs"/>
......@@ -234,6 +233,7 @@
<command id="org.jkiss.dbeaver.core.resultset.row.delete" name="%command.org.jkiss.dbeaver.core.resultset.row.delete.name" description="%command.org.jkiss.dbeaver.core.resultset.row.delete.description" categoryId="org.jkiss.dbeaver.core.rs"/>
<command id="org.jkiss.dbeaver.core.resultset.applyChanges" name="%command.org.jkiss.dbeaver.core.resultset.applyChanges.name" description="%command.org.jkiss.dbeaver.core.resultset.applyChanges.description" categoryId="org.jkiss.dbeaver.core.rs"/>
<command id="org.jkiss.dbeaver.core.resultset.rejectChanges" name="%command.org.jkiss.dbeaver.core.resultset.rejectChanges.name" description="%command.org.jkiss.dbeaver.core.resultset.rejectChanges.description" categoryId="org.jkiss.dbeaver.core.rs"/>
<command id="org.jkiss.dbeaver.core.resultset.grid.togglePreview" name="%command.org.jkiss.dbeaver.core.resultset.grid.togglePreview.name" description="%command.org.jkiss.dbeaver.core.resultset.grid.togglePreview.description" categoryId="org.jkiss.dbeaver.core.rs"/>
<command id="org.jkiss.dbeaver.core.edit.copy.special" name="%command.org.jkiss.dbeaver.core.edit.copy.special.name" description="%command.org.jkiss.dbeaver.core.edit.copy.special.description" categoryId="org.jkiss.dbeaver.core.util"/>
......@@ -298,7 +298,7 @@
<image commandId="org.jkiss.dbeaver.core.resultset.applyChanges" icon="icons/sql/accept.png"/>
<image commandId="org.jkiss.dbeaver.core.resultset.rejectChanges" icon="icons/sql/cancel.png"/>
<image commandId="org.jkiss.dbeaver.core.resultset.toggleMode" icon="icons/sql/grid.png"/>
<image commandId="org.jkiss.dbeaver.core.resultset.togglePreview" icon="icons/sql/details.png"/>
<image commandId="org.jkiss.dbeaver.core.resultset.grid.togglePreview" icon="icons/sql/details.png"/>
<image commandId="org.jkiss.dbeaver.core.qm.filter" icon="icons/misc/filter.png"/>
<image commandId="org.jkiss.dbeaver.core.qm.clear" icon="IMG_ETOOL_CLEAR"/>
......@@ -950,7 +950,9 @@
<activeWhen><reference definitionId="org.jkiss.dbeaver.core.ui.spreadsheet.control"/></activeWhen>
</handler>
<handler commandId="org.jkiss.dbeaver.core.resultset.grid.togglePreview" class="org.jkiss.dbeaver.ui.controls.resultset.spreadsheet.SpreadsheetTogglePreviewHandler">
<activeWhen><reference definitionId="org.jkiss.dbeaver.core.ui.resultset.part"/></activeWhen>
</handler>
<handler commandId="org.eclipse.ui.edit.selectAll" class="org.jkiss.dbeaver.ui.controls.resultset.spreadsheet.SpreadsheetCommandHandler">
<activeWhen><reference definitionId="org.jkiss.dbeaver.core.ui.spreadsheet.control"/></activeWhen>
<enabledWhen>
......@@ -959,6 +961,7 @@
</with>
</enabledWhen>
</handler>
<handler commandId="org.eclipse.ui.edit.copy" class="org.jkiss.dbeaver.ui.controls.resultset.ResultSetCommandHandler">
<activeWhen><reference definitionId="org.jkiss.dbeaver.core.ui.spreadsheet.control"/></activeWhen>
<enabledWhen>
......@@ -988,14 +991,6 @@
</with>
</enabledWhen>
</handler>
<handler commandId="org.jkiss.dbeaver.core.resultset.togglePreview" class="org.jkiss.dbeaver.ui.controls.resultset.ResultSetModeTogglePreviewHandler">
<activeWhen><reference definitionId="org.jkiss.dbeaver.core.ui.resultset.part"/></activeWhen>
<enabledWhen>
<with variable="activePart">
<test property="org.jkiss.dbeaver.core.resultset.canToggle"/>
</with>
</enabledWhen>
</handler>
<handler commandId="org.jkiss.dbeaver.core.resultset.row.first" class="org.jkiss.dbeaver.ui.controls.resultset.ResultSetCommandHandler">
<activeWhen><reference definitionId="org.jkiss.dbeaver.core.ui.resultset.part"/></activeWhen>
<enabledWhen>
......@@ -1645,7 +1640,6 @@
<extension point="org.eclipse.ui.bindings">
<key commandId="org.jkiss.dbeaver.core.resultset.toggleMode" schemeId="org.eclipse.ui.defaultAcceleratorConfiguration" sequence="TAB"/>
<key commandId="org.jkiss.dbeaver.core.resultset.togglePreview" schemeId="org.eclipse.ui.defaultAcceleratorConfiguration" sequence="F7"/>
<key commandId="org.jkiss.dbeaver.core.resultset.row.first" schemeId="org.eclipse.ui.defaultAcceleratorConfiguration" sequence="CTRL+SHIFT+ARROW_LEFT"/>
<key commandId="org.jkiss.dbeaver.core.resultset.row.previous" schemeId="org.eclipse.ui.defaultAcceleratorConfiguration" sequence="CTRL+ARROW_LEFT"/>
<key commandId="org.jkiss.dbeaver.core.resultset.row.next" schemeId="org.eclipse.ui.defaultAcceleratorConfiguration" sequence="CTRL+ARROW_RIGHT"/>
......@@ -1657,6 +1651,7 @@
<key commandId="org.jkiss.dbeaver.core.resultset.row.delete" schemeId="org.eclipse.ui.defaultAcceleratorConfiguration" sequence="ALT+DELETE"/>
<key commandId="org.jkiss.dbeaver.core.resultset.applyChanges" schemeId="org.eclipse.ui.defaultAcceleratorConfiguration" sequence="CTRL+ALT+S"/>
<key commandId="org.jkiss.dbeaver.core.resultset.rejectChanges" schemeId="org.eclipse.ui.defaultAcceleratorConfiguration" sequence="CTRL+ALT+R"/>
<key commandId="org.jkiss.dbeaver.core.resultset.grid.togglePreview" schemeId="org.eclipse.ui.defaultAcceleratorConfiguration" sequence="F7"/>
<key commandId="org.jkiss.dbeaver.core.edit.copy.special" schemeId="org.eclipse.ui.defaultAcceleratorConfiguration" sequence="CTRL+SHIFT+C"/>
<key commandId="org.jkiss.dbeaver.core.navigator.bookmark.add" schemeId="org.eclipse.ui.defaultAcceleratorConfiguration" sequence="CTRL+D"/>
......
......@@ -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;
}
}
......@@ -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,
......
......@@ -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();
}
......@@ -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();
}
/*
* 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);
}
......@@ -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);
}
......
......@@ -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;
......
......@@ -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();
}
};
......
......@@ -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
......
......@@ -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(
......
......@@ -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;
}
......
......@@ -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<DBDValue, CollectionElementData>();
}
......
......@@ -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();
}
}
}
}
/*
* 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<DBDAttributeBinding> getRowAttributes()
{
return Arrays.asList(controller.getModel().getColumns());
}
@Nullable
@Override
public Object getAttributeValue(DBDAttributeBinding attribute)
{
return controller.getModel().getCellValue(attribute, curRow);
}
}
......@@ -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<ResultSetPresentationDescriptor> 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<ResultSetValueController, DBDValueEditorStandalone> openEditors = new HashMap<ResultSetValueController, DBDValueEditorStandalone>();
private final List<IResultSetListener> listeners = new ArrayList<IResultSetListener>();
// 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<StateItem> stateHistory = new ArrayList<StateItem>();
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<Object[]> 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<Object[]> 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<DBDValueEditorStandalone> editors = new ArrayList<DBDValueEditorStandalone>(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<Object> 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<DBSEntityReferrer> 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<Object> 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<GridCell> 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<DBDAttributeBinding> 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<DBDAttributeBinding>() {
@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;
}
}
}
......@@ -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);
......
......@@ -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)) {
......
......@@ -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<SpreadsheetValueController, DBDValueEditorStandalone> openEditors = new HashMap<SpreadsheetValueController, DBDValueEditorStandalone>();
private SpreadsheetFindReplaceTarget findReplaceTarget;
private final List<ISelectionChangedListener> selectionChangedListenerList = new ArrayList<ISelectionChangedListener>();
// 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<Object> 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<GridCell> 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<Object> 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<DBDValueEditorStandalone> editors = new ArrayList<DBDValueEditorStandalone>(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<DBDAttributeBinding>() {
@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);
}
}
}
......@@ -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 {
......
......@@ -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
......
......@@ -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;
......
......@@ -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() {
}
}
......@@ -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() {
}
}
......@@ -132,7 +132,7 @@ public class DatabaseDataEditor extends AbstractDatabaseObjectEditor<DBSDataCont
{
createResultSetView();
if (resultSetView != null) {
resultSetView.getSpreadsheet().setFocus();
resultSetView.getActivePresentation().getControl().setFocus();
}
// Register find/replace action
......
......@@ -334,7 +334,7 @@ public class SQLEditor extends SQLEditorBase
curQueryProcessor = resultsProvider.queryProcessor;
ResultSetViewer rsv = resultsProvider.getResultSetViewer();
if (rsv != null) {
rsv.getSpreadsheet().setFocus();
rsv.getActivePresentation().getControl().setFocus();
}
} else if (data == outputViewer) {
((CTabItem) e.item).setImage(IMG_OUTPUT);
......@@ -347,8 +347,8 @@ public class SQLEditor extends SQLEditorBase
public void keyTraversed(TraverseEvent e) {
if (e.detail == SWT.TRAVERSE_PAGE_NEXT) {
ResultSetViewer viewer = getResultSetViewer();
if (viewer != null && viewer.getSpreadsheet().isVisible()) {
viewer.getSpreadsheet().setFocus();
if (viewer != null && viewer.getActivePresentation().getControl().isVisible()) {
viewer.getActivePresentation().getControl().setFocus();
e.doit = false;
e.detail = SWT.TRAVERSE_NONE;
}
......@@ -1165,10 +1165,10 @@ public class SQLEditor extends SQLEditorBase
this.resultSetNumber = resultSetNumber;
viewer = new ResultSetViewer(resultTabs, getSite(), this);
selectionProvider.trackProvider(viewer.getSpreadsheet(), viewer);
selectionProvider.trackProvider(viewer.getActivePresentation().getControl(), viewer);
// Find/replace target activation
viewer.getSpreadsheet().addFocusListener(new FocusAdapter() {
viewer.getActivePresentation().getControl().addFocusListener(new FocusAdapter() {
@Override
public void focusGained(FocusEvent e)
{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册