/* * DBeaver - Universal Database Manager * Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jkiss.dbeaver.ui.data.editors; import org.eclipse.jface.action.IContributionManager; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CCombo; import org.eclipse.swt.events.FocusEvent; import org.eclipse.swt.events.FocusListener; import org.eclipse.swt.events.TraverseEvent; import org.eclipse.swt.events.TraverseListener; import org.eclipse.swt.widgets.*; import org.eclipse.ui.contexts.IContextActivation; import org.eclipse.ui.contexts.IContextService; import org.jkiss.code.NotNull; import org.jkiss.dbeaver.DBException; import org.jkiss.dbeaver.DBeaverPreferences; import org.jkiss.dbeaver.core.DBeaverCore; import org.jkiss.dbeaver.model.exec.DBCException; import org.jkiss.dbeaver.ui.UIUtils; import org.jkiss.dbeaver.ui.data.IMultiController; import org.jkiss.dbeaver.ui.data.IValueController; import org.jkiss.dbeaver.ui.data.IValueEditor; /** * BaseValueEditor */ public abstract class BaseValueEditor<T extends Control> implements IValueEditor { private static final String RESULTS_EDIT_CONTEXT_ID = "org.jkiss.dbeaver.ui.context.resultset.edit"; protected final IValueController valueController; protected T control; protected boolean dirty; protected boolean autoSaveEnabled; protected BaseValueEditor(final IValueController valueController) { this.valueController = valueController; } public void createControl() { this.control = createControl(valueController.getEditPlaceholder()); if (this.control != null) { initInlineControl(this.control); } } @Override public Control getControl() { return control; } @Override public void contributeActions(@NotNull IContributionManager manager, @NotNull IValueController controller) throws DBCException { } protected abstract T createControl(Composite editPlaceholder); protected void initInlineControl(final Control inlineControl) { boolean isInline = (valueController.getEditType() == IValueController.EditType.INLINE); if (isInline && UIUtils.isInDialog(inlineControl)) { //isInline = false; } UIUtils.enableHostEditorKeyBindingsSupport(valueController.getValueSite(), inlineControl); // if (!isInline) { // inlineControl.setBackground(valueController.getEditPlaceholder().getBackground()); // } final IContextService contextService = valueController.getValueSite().getService(IContextService.class); inlineControl.addFocusListener(new FocusListener() { private IContextActivation activationEditor; @Override public void focusGained(FocusEvent e) { if (contextService != null) { activationEditor = contextService.activateContext(RESULTS_EDIT_CONTEXT_ID); } } @Override public void focusLost(FocusEvent e) { contextService.deactivateContext(activationEditor); activationEditor = null; } }); if (isInline) { 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 inlineControl.addTraverseListener(new TraverseListener() { @Override public void keyTraversed(TraverseEvent e) { if (e.detail == SWT.TRAVERSE_RETURN) { saveValue(); ((IMultiController) valueController).closeInlineEditor(); e.doit = false; e.detail = SWT.TRAVERSE_NONE; } else if (e.detail == SWT.TRAVERSE_ESCAPE) { ((IMultiController) valueController).closeInlineEditor(); e.doit = false; e.detail = SWT.TRAVERSE_NONE; } else if (e.detail == SWT.TRAVERSE_TAB_NEXT || e.detail == SWT.TRAVERSE_TAB_PREVIOUS) { saveValue(); ((IMultiController) valueController).nextInlineEditor(e.detail == SWT.TRAVERSE_TAB_NEXT); e.doit = false; e.detail = SWT.TRAVERSE_NONE; } } }); if (!UIUtils.isInDialog(inlineControl)) { addAutoSaveSupport(inlineControl); } } } final ControlModifyListener modifyListener = new ControlModifyListener(); control.addListener(SWT.Modify, modifyListener); control.addListener(SWT.Selection, modifyListener); } private void addAutoSaveSupport(final Control inlineControl) { // 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) { // Check new focus control in async mode // (because right now focus is still on edit control) if (!valueController.isReadOnly()) { saveValue(); } if (valueController instanceof IMultiController) { ((IMultiController) valueController).closeInlineEditor(); } } }); } private void saveValue() { try { 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) valueController.updateValue(newValue, true); } } catch (DBException e) { ((IMultiController) valueController).closeInlineEditor(); UIUtils.showErrorDialog(null, "Value save", "Can't save edited value", e); } } @Override public boolean isDirty() { return dirty; } public void setDirty(boolean dirty) { this.dirty = dirty; } public boolean isAutoSaveEnabled() { return autoSaveEnabled; } public void setAutoSaveEnabled(boolean autoSaveEnabled) { this.autoSaveEnabled = autoSaveEnabled; } private class ControlModifyListener implements Listener { @Override public void handleEvent(Event event) { setDirty(true); if (autoSaveEnabled && DBeaverCore.getGlobalPreferenceStore().getBoolean(DBeaverPreferences.RS_EDIT_AUTO_UPDATE_VALUE)) { saveValue(); } } } }