Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dbeaver/dbeaver#22103 replace autosave focus listener with dispose & tabbing support for datetime #22788

Open
wants to merge 16 commits into
base: devel
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@
import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.ui.controls.resultset.IResultSetPanel;
import org.jkiss.dbeaver.ui.controls.resultset.IResultSetPresentation;
import org.jkiss.dbeaver.ui.controls.resultset.ResultSetViewer;
import org.jkiss.dbeaver.ui.controls.resultset.handler.ResultSetHandlerMain;
import org.jkiss.dbeaver.ui.controls.resultset.spreadsheet.SpreadsheetPresentation;

/**
* ValueViewCommandHandler
Expand All @@ -41,13 +43,21 @@ public Object execute(ExecutionEvent event) throws ExecutionException {
return null;
}
String actionId = event.getCommand().getId();
IResultSetPanel visiblePanel = rsv.getVisiblePanel();
if (visiblePanel instanceof ValueViewerPanel) {
IResultSetPanel resultPanel = rsv.getVisiblePanel();
if (resultPanel instanceof ValueViewerPanel valuePanel) {
switch (actionId) {
case ITextEditorActionDefinitionIds.SMART_ENTER:
//case CoreCommands.CMD_EXECUTE_STATEMENT:
case CMD_SAVE_VALUE:
((ValueViewerPanel) visiblePanel).saveValue();
// 1 close active inline editor
IResultSetPresentation activePresentation = rsv.getActivePresentation();
if (activePresentation instanceof SpreadsheetPresentation spsPresentation) {
spsPresentation.closeInlineEditor();
}
// 2 save value from panel
valuePanel.saveValue();
// 3 refresh panel to show actual
valuePanel.refresh(true);
break;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/
package org.jkiss.dbeaver.ui.controls.resultset.spreadsheet;

import org.eclipse.core.runtime.Platform.OS;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyledText;
Expand Down Expand Up @@ -350,8 +351,11 @@ public void handleEvent(final Event event) {
}
break;
case SWT.MouseDown:
if (event.button == 2) {
// presentation.openValueEditor(true);
if (presentation == null) {
return;
}
if (event.button == 1 && event.count == 1) {
presentation.closeInlineEditor();
}
break;
case LightGrid.Event_ChangeSort:
Expand All @@ -370,6 +374,9 @@ public void handleEvent(final Event event) {
// we don't want to mess current grid state
UIUtils.asyncExec(() -> presentation.navigateLink((GridCell) event.data, event.stateMask));
break;
case SWT.MouseExit:
System.out.println("Spreadsheet.handleEvent()");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

break;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2963,4 +2963,17 @@
}

}

/**
* Close editor control (In line) during close data will be automatically
* applied for cell
*/
public void closeInlineEditor() {
if (activeInlineEditor instanceof BaseValueEditor<?> baseInlineEditor) {
IValueController vController = baseInlineEditor.getValueController();

Check warning on line 2973 in plugins/org.jkiss.dbeaver.ui.editors.data/src/org/jkiss/dbeaver/ui/controls/resultset/spreadsheet/SpreadsheetPresentation.java

View check run for this annotation

Jenkins-CI-integration / CheckStyle Report

plugins/org.jkiss.dbeaver.ui.editors.data/src/org/jkiss/dbeaver/ui/controls/resultset/spreadsheet/SpreadsheetPresentation.java#L2973

Local variable name vController must match pattern ^[a-z]([a-z0-9][a-zA-Z0-9]*)?$.
if (vController instanceof IMultiController mController) {

Check warning on line 2974 in plugins/org.jkiss.dbeaver.ui.editors.data/src/org/jkiss/dbeaver/ui/controls/resultset/spreadsheet/SpreadsheetPresentation.java

View check run for this annotation

Jenkins-CI-integration / CheckStyle Report

plugins/org.jkiss.dbeaver.ui.editors.data/src/org/jkiss/dbeaver/ui/controls/resultset/spreadsheet/SpreadsheetPresentation.java#L2974

Pattern variable name mController must match pattern ^[a-z]([a-z0-9][a-zA-Z0-9]*)?$.
mController.closeInlineEditor();
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,8 @@
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CCombo;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.TraverseEvent;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.*;
import org.eclipse.ui.themes.ITheme;
import org.jkiss.code.NotNull;
Expand Down Expand Up @@ -128,7 +124,9 @@ protected void initInlineControl(final Control inlineControl)
//inlineControl.setFont(valueController.getEditPlaceholder().getFont());
//inlineControl.setFocus();

if (valueController instanceof IMultiController) { // In dialog it also should handle all standard stuff because we have params dialog
// In dialog it also should handle all standard stuff because we have params
// dialog
if (valueController instanceof IMultiController) {
inlineControl.addTraverseListener(e -> {
if (e.detail == SWT.TRAVERSE_RETURN) {
if (!valueController.isReadOnly()) {
Expand All @@ -140,38 +138,38 @@ protected void initInlineControl(final Control inlineControl)
}
e.doit = false;
e.detail = SWT.TRAVERSE_NONE;
} else if (e.detail == SWT.TRAVERSE_ESCAPE) {
} else if (e.detail == SWT.TRAVERSE_ESCAPE) {
((IMultiController) valueController).closeInlineEditor();
if (additionalTraverseActions != null) {
additionalTraverseActions.accept(e);
}
e.doit = false;
e.detail = SWT.TRAVERSE_NONE;
} else if (e.detail == SWT.TRAVERSE_TAB_NEXT || e.detail == SWT.TRAVERSE_TAB_PREVIOUS) {
} else if (e.detail == SWT.TRAVERSE_TAB_NEXT || e.detail == SWT.TRAVERSE_TAB_PREVIOUS) {
saveValue();
((IMultiController) valueController).nextInlineEditor(e.detail == SWT.TRAVERSE_TAB_NEXT);
if (additionalTraverseActions != null) {
additionalTraverseActions.accept(e);
}
e.doit = false;
e.detail = SWT.TRAVERSE_NONE;
}

}
});
if (!UIUtils.isInDialog(inlineControl)) {
if (inlineControl instanceof Composite) {
for (Control childControl : ((Composite) inlineControl).getChildren()) {
if (!childControl.isDisposed()) {
addAutoSaveSupport(childControl);
EditorUtils.trackControlContext(valueController.getValueSite(), childControl, RESULTS_EDIT_CONTEXT_ID);
}
}
} else {
addAutoSaveSupport(inlineControl);
}
} else {
((IMultiController) valueController).closeInlineEditor();
}
if (!UIUtils.isInDialog(inlineControl)) {
if (inlineControl instanceof Composite) {
for (Control childControl : ((Composite) inlineControl).getChildren()) {
if (!childControl.isDisposed()) {
EditorUtils.trackControlContext(
valueController.getValueSite(),
childControl,
RESULTS_EDIT_CONTEXT_ID);
}
}
}
addAutoSaveSupport(inlineControl);
} else {
((IMultiController) valueController).closeInlineEditor();
}
}

if (!UIUtils.isInDialog(inlineControl)) {
Expand All @@ -195,37 +193,22 @@ protected void addInlineListeners(@NotNull Control inlineControl, @NotNull Liste
}

private void addAutoSaveSupport(final Control inlineControl) {
BaseValueEditor<?> editor = this;
// Do not use focus listener in dialogs (because dialog has controls like Ok/Cancel buttons)
inlineControl.addFocusListener(new FocusListener() {
@Override
public void focusGained(FocusEvent e) {
}

@Override
public void focusLost(FocusEvent e) {
// It feels like on Linux editor's control is 'invisible' for GTK and mouse clicks
// 'go through' the control and reach underlying spreadsheet. Workaround:
// check that in reality we clicked on editor by checking that cursor is in control's
// bounds. See [dbeaver#10561].
Rectangle controlBounds = editor.control.getBounds();
Point relativeCursorLocation = editor.control.toControl(e.display.getCursorLocation());
if (controlBounds.contains(relativeCursorLocation)) {
return;
}
// add focus listener on control but not on the composite
// require to handle data save in case of focus lost
inlineControl.addDisposeListener(getAutoSaveListener());
this.setAutoSaveEnabled(true);
}

onFocusLost(valueController::updateSelectionValue);
@NotNull
protected DisposeListener getAutoSaveListener() {
return e -> {
if (!valueController.isReadOnly()) {
saveBeforeClose(value -> valueController.updateValue(value, true));
}
});

// Unfortunately, focusLost events on macOS never reach the listener above.
// However, we rely on them to save the value when the user clicks somewhere on the grid and LightGrid forces focus on itself.
// The solution is to add dispose listener. But here is a catch: when inline control is about to be disposed of, the selection is already
// on some other cell on the grid. Hence, we need to use updateValue() on valueController, not updateSelectionValue().
UIUtils.installMacOSFocusLostSubstitution(inlineControl, () -> onFocusLost(value -> valueController.updateValue(value, true)));
};
}

private void onFocusLost(@NotNull Consumer<Object> valueSaver) {
private void saveBeforeClose(@NotNull Consumer<Object> valueSaver) {
if (!valueController.isReadOnly()) {
saveValue(false, valueSaver);
}
Expand All @@ -244,6 +227,9 @@ protected void saveValue(boolean showError) {

private void saveValue(boolean showError, @NotNull Consumer<Object> valueUpdater) {
try {
if (control.isDisposed()) {
return;
}
Object newValue = extractEditorValue();
if (dirty || control instanceof Combo || control instanceof CCombo || control instanceof List) {
// Combos are always dirty (because drop-down menu sets a selection)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,8 @@
import org.eclipse.swt.SWT;
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.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.events.TraverseEvent;
import org.eclipse.swt.widgets.*;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.DBException;
Expand Down Expand Up @@ -54,7 +52,6 @@ public class DateTimeInlineEditor extends BaseValueEditor<Control> {
private DateEditorMode dateEditorMode;
private CustomTimeEditor timeEditor;


/**
* Action which sets edit mode to string edit
*/
Expand Down Expand Up @@ -147,6 +144,22 @@ public DateTimeInlineEditor(IValueController controller) {
@Override
protected void addInlineListeners(@NotNull Control inlineControl, @NotNull Listener listener) {
super.addInlineListeners(inlineControl, listener);
timeEditor.addTextModeTraverseListener(e -> {
if (!inlineControl.isDisposed()) {
sendTraverseEvent(inlineControl, e);
}
});
timeEditor.addTraverseForwardListener(e -> {
if (!inlineControl.isDisposed() && e.detail == SWT.TRAVERSE_TAB_NEXT) {
sendTraverseEvent(inlineControl, e);
}
});
timeEditor.addTraverseBackwardsListener(e -> {
if (!inlineControl.isDisposed() && e.detail == SWT.TRAVERSE_TAB_PREVIOUS) {
sendTraverseEvent(inlineControl, e);
}
});

timeEditor.addSelectionAdapter(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
Expand All @@ -162,6 +175,13 @@ public void widgetSelected(SelectionEvent e) {
});
}

private static void sendTraverseEvent(@NotNull Control inlineControl, TraverseEvent e) {
e.doit = false;
Event event = new Event();
event.detail = e.detail;
inlineControl.notifyListeners(SWT.Traverse, event);
}

@Override
protected Control createControl(Composite editPlaceholder) {
Object value = valueController.getValue();
Expand All @@ -175,8 +195,9 @@ protected Control createControl(Composite editPlaceholder) {
if (!isCalendarMode()) {
textMode.run();
textMode.setChecked(true);
} else dateEditorMode.setChecked(true);

} else {
dateEditorMode.setChecked(true);
}
primeEditorValue(value);
timeEditor.createDateFormat(valueController.getValueType());
timeEditor.setEditable(!valueController.isReadOnly());
Expand All @@ -192,12 +213,14 @@ private boolean isCalendarMode() {
@Override
public Object extractEditorValue() throws DBCException {
try (DBCSession session = valueController.getExecutionContext().openSession(new VoidProgressMonitor(), DBCExecutionPurpose.UTIL, "Make datetime value from editor")) {
if (!isCalendarMode()) {
if (timeEditor.isTextMode()) {
final String strValue = timeEditor.getValueAsString();
return valueController.getValueHandler().getValueFromObject(session, valueController.getValueType(), strValue, false, true);
return valueController.getValueHandler()
.getValueFromObject(session, valueController.getValueType(), strValue, false, true);
} else {
final Date dateValue = timeEditor.getValueAsDate();
return valueController.getValueHandler().getValueFromObject(session, valueController.getValueType(), dateValue, false, true);
return valueController.getValueHandler()
.getValueFromObject(session, valueController.getValueType(), dateValue, false, true);
}
}
}
Expand Down