/******************************************************************************* * Copyright (c) 2010 Red Hat, Inc. * Distributed under license by Red Hat, Inc. All rights reserved. * This program is made available under the terms of the * Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html * * Contributor: * Red Hat, Inc. - initial API and implementation ******************************************************************************/ package org.hibernate.eclipse.console.views; import java.text.MessageFormat; import org.eclipse.jface.viewers.TextCellEditor; import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; import org.eclipse.swt.events.FocusEvent; import org.eclipse.swt.events.FocusListener; import org.eclipse.swt.events.KeyAdapter; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Layout; import org.eclipse.swt.widgets.Text; import org.hibernate.console.StringListDialog; /** * @author Dmitry Geraskov * */ public class StringArrayDialogCellEditor extends TextCellEditor { private Text text; /** * The button. */ private Button button; /** * The editor control. */ private Composite editor; private String[] strValues = null; private FocusListener buttonFocusListener; protected StringArrayDialogCellEditor(Composite parent) { super(parent); } @Override protected Control createControl(Composite parent) { Font font = parent.getFont(); Color bg = parent.getBackground(); editor = new Composite(parent, getStyle()); editor.setFont(font); editor.setBackground(bg); editor.setLayout(new DialogCellLayout()); text = (Text) super.createControl(editor); updateContents(strValues); button = createButton(editor); button.setFont(font); button.addKeyListener(new KeyAdapter() { /* (non-Javadoc) * @see org.eclipse.swt.events.KeyListener#keyReleased(org.eclipse.swt.events.KeyEvent) */ public void keyReleased(KeyEvent e) { if (e.character == '\u001b') { // Escape fireCancelEditor(); } } }); button.addFocusListener(getButtonFocusListener()); button.addSelectionListener(new SelectionAdapter() { /* (non-Javadoc) * @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent) */ public void widgetSelected(SelectionEvent event) { // Remove the button's focus listener since it's guaranteed // to lose focus when the dialog opens button.removeFocusListener(getButtonFocusListener()); Object newValue = openDialogBox(editor); // Re-add the listener once the dialog closes button.addFocusListener(getButtonFocusListener()); if (newValue != null) { boolean newValidState = isCorrect(newValue); if (newValidState) { markDirty(); doSetValue(newValue); } else { // try to insert the current value into the error message. setErrorMessage(MessageFormat.format(getErrorMessage(), new Object[] { newValue.toString() })); } fireApplyEditorValue(); } } }); setValueValid(true); return editor; } @Override protected void focusLost() { if (isActivated()) { if (button != null && !button.isDisposed() && !button.isFocusControl()) { if (text != null && !text.isDisposed() && !text.isFocusControl()){ fireApplyEditorValue(); deactivate(); } } } } protected Object openDialogBox(Control cellEditorWindow) { String[] value = (String[]) getValue(); StringListDialog pld = new StringListDialog(null, value); if (pld.open()==Window.OK){ return pld.getValue();//String[] } return null; } private FocusListener getButtonFocusListener() { if (buttonFocusListener == null) { buttonFocusListener = new FocusListener() { /* (non-Javadoc) * @see org.eclipse.swt.events.FocusListener#focusGained(org.eclipse.swt.events.FocusEvent) */ public void focusGained(FocusEvent e) { } /* (non-Javadoc) * @see org.eclipse.swt.events.FocusListener#focusLost(org.eclipse.swt.events.FocusEvent) */ public void focusLost(FocusEvent e) { StringArrayDialogCellEditor.this.focusLost(); } }; } return buttonFocusListener; } protected Button createButton(Composite parent) { Button result = new Button(parent, SWT.DOWN); result.setText("..."); //$NON-NLS-1$ return result; } public void deactivate() { if (button != null && !button.isDisposed()) { button.removeFocusListener(getButtonFocusListener()); } super.deactivate(); } @Override protected void editOccured(ModifyEvent e) { String text = this.text.getText(); if (strValues == null || strValues.length == 0){ strValues = new String[]{text}; } else { strValues[0] = text; } super.editOccured(e); } protected Object doGetValue() { return strValues; } protected void doSetValue(Object value) { if (value == null) { this.strValues = new String[]{""}; //$NON-NLS-1$ } else if (value.getClass().isArray()){ this.strValues = (String[])value; } super.doSetValue(strValues.length > 0 ? strValues[0] : ""); //$NON-NLS-1$ } protected void updateContents(String[] value) { if (text == null) { return; } String strVal = "";//$NON-NLS-1$ if (value != null && value.length > 0) { strVal = value[0]; } text.setText(strVal); } private class DialogCellLayout extends Layout { public void layout(Composite editor, boolean force) { Rectangle bounds = editor.getClientArea(); Point size = button.computeSize(SWT.DEFAULT, SWT.DEFAULT, force); if (text != null) { text.setBounds(0, 0, bounds.width - size.x, bounds.height); } button.setBounds(bounds.width - size.x, 0, size.x, bounds.height); } public Point computeSize(Composite editor, int wHint, int hHint, boolean force) { if (wHint != SWT.DEFAULT && hHint != SWT.DEFAULT) { return new Point(wHint, hHint); } Point contentsSize = text.computeSize(SWT.DEFAULT, SWT.DEFAULT, force); Point buttonSize = button.computeSize(SWT.DEFAULT, SWT.DEFAULT, force); // Just return the button width to ensure the button is not clipped // if the label is long. // The label will just use whatever extra width there is Point result = new Point(buttonSize.x, Math.max(contentsSize.y, buttonSize.y)); return result; } } }