| /******************************************************************************* |
| * Copyright (c) 2010 BSI Business Systems Integration AG. |
| * All rights reserved. This program and the accompanying materials |
| * are 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 |
| * |
| * Contributors: |
| * BSI Business Systems Integration AG - initial API and implementation |
| ******************************************************************************/ |
| package org.eclipse.scout.rt.ui.swing.form.fields.filechooserfield; |
| |
| import java.awt.Point; |
| import java.awt.event.ActionEvent; |
| import java.beans.PropertyChangeEvent; |
| import java.io.File; |
| import java.util.concurrent.atomic.AtomicBoolean; |
| |
| import javax.swing.AbstractAction; |
| import javax.swing.ActionMap; |
| import javax.swing.InputMap; |
| import javax.swing.JComponent; |
| import javax.swing.JTextField; |
| import javax.swing.event.DocumentEvent; |
| import javax.swing.event.DocumentListener; |
| import javax.swing.text.Document; |
| import javax.swing.text.JTextComponent; |
| |
| import org.eclipse.scout.commons.CompareUtility; |
| import org.eclipse.scout.commons.holders.Holder; |
| import org.eclipse.scout.commons.job.JobEx; |
| import org.eclipse.scout.rt.client.ui.action.IAction; |
| import org.eclipse.scout.rt.client.ui.action.menu.IMenu; |
| import org.eclipse.scout.rt.client.ui.basic.filechooser.IFileChooser; |
| import org.eclipse.scout.rt.client.ui.form.fields.filechooserfield.IFileChooserField; |
| import org.eclipse.scout.rt.ui.swing.LogicalGridLayout; |
| import org.eclipse.scout.rt.ui.swing.SwingPopupWorker; |
| import org.eclipse.scout.rt.ui.swing.SwingUtility; |
| import org.eclipse.scout.rt.ui.swing.action.AbstractSwingScoutActionPropertyChangeListener; |
| import org.eclipse.scout.rt.ui.swing.basic.IconGroup; |
| import org.eclipse.scout.rt.ui.swing.ext.IDropDownButtonListener; |
| import org.eclipse.scout.rt.ui.swing.ext.JPanelEx; |
| import org.eclipse.scout.rt.ui.swing.ext.JStatusLabelEx; |
| import org.eclipse.scout.rt.ui.swing.ext.JTextFieldWithDropDownButton; |
| import org.eclipse.scout.rt.ui.swing.form.fields.SwingScoutValueFieldComposite; |
| |
| public class SwingScoutFileChooserField extends SwingScoutValueFieldComposite<IFileChooserField> implements ISwingScoutFileChooserField { |
| private static final long serialVersionUID = 1L; |
| |
| private P_ScoutActionPropertyChangeListener m_scoutActionPropertyListener; |
| |
| @Override |
| protected void initializeSwing() { |
| JPanelEx container = new JPanelEx(); |
| container.setOpaque(false); |
| JStatusLabelEx label = getSwingEnvironment().createStatusLabel(getScoutObject()); |
| container.add(label); |
| // |
| JTextComponent textField = createTextField(container); |
| Document doc = textField.getDocument(); |
| doc.addDocumentListener(new DocumentListener() { |
| @Override |
| public void removeUpdate(DocumentEvent e) { |
| setInputDirty(true); |
| } |
| |
| @Override |
| public void insertUpdate(DocumentEvent e) { |
| setInputDirty(true); |
| } |
| |
| @Override |
| public void changedUpdate(DocumentEvent e) { |
| setInputDirty(true); |
| } |
| }); |
| // key mappings |
| InputMap inputMap = textField.getInputMap(JTextField.WHEN_FOCUSED); |
| inputMap.put(SwingUtility.createKeystroke("F2"), "fileChooser"); |
| ActionMap actionMap = textField.getActionMap(); |
| actionMap.put("fileChooser", new P_SwingFileChooserAction()); |
| // |
| setSwingContainer(container); |
| setSwingLabel(label); |
| setSwingField(textField); |
| // layout |
| getSwingContainer().setLayout(new LogicalGridLayout(getSwingEnvironment(), 1, 0)); |
| } |
| |
| /** |
| * Create and add the text field to the container. |
| * <p> |
| * May add additional components to the container. |
| */ |
| protected JTextComponent createTextField(JComponent container) { |
| JTextFieldWithDropDownButton textField = new JTextFieldWithDropDownButton(getSwingEnvironment()); |
| container.add(textField); |
| textField.addDropDownButtonListener(new IDropDownButtonListener() { |
| @Override |
| public void iconClicked(Object source) { |
| getSwingTextField().requestFocus(); |
| handleSwingFileChooserAction(); |
| } |
| |
| @Override |
| public void menuClicked(Object source) { |
| handleSwingPopup((JComponent) source); |
| } |
| }); |
| return textField; |
| } |
| |
| @Override |
| public JTextComponent getSwingTextField() { |
| return (JTextComponent) getSwingField(); |
| } |
| |
| @Override |
| protected void attachScout() { |
| super.attachScout(); |
| IFileChooserField f = getScoutObject(); |
| setFileIconIdFromScout(f.getFileIconId()); |
| if (m_scoutActionPropertyListener == null) { |
| m_scoutActionPropertyListener = new P_ScoutActionPropertyChangeListener(); |
| } |
| m_scoutActionPropertyListener.attachToScoutMenus(f.getMenus()); |
| if (getSwingField() instanceof JTextFieldWithDropDownButton) { |
| ((JTextFieldWithDropDownButton) getSwingTextField()).setMenuEnabled(calculateDropDownButtonEnabled()); |
| } |
| } |
| |
| @Override |
| protected void detachScout() { |
| if (m_scoutActionPropertyListener != null) { |
| m_scoutActionPropertyListener.detachFromScoutMenus(getScoutObject().getMenus()); |
| m_scoutActionPropertyListener = null; |
| } |
| super.detachScout(); |
| } |
| |
| @Override |
| protected void setDisplayTextFromScout(String s) { |
| if (getSwingField() instanceof JTextFieldWithDropDownButton) { |
| ((JTextFieldWithDropDownButton) getSwingTextField()).setMenuEnabled(calculateDropDownButtonEnabled()); |
| } |
| JTextComponent swingField = getSwingTextField(); |
| swingField.setText(s); |
| } |
| |
| private boolean calculateDropDownButtonEnabled() { |
| final AtomicBoolean hasValidMenus = new AtomicBoolean(false); |
| Runnable t = new Runnable() { |
| @Override |
| public void run() { |
| hasValidMenus.set(getScoutObject().getUIFacade().hasValidMenusFromUI()); |
| } |
| }; |
| JobEx job = getSwingEnvironment().invokeScoutLater(t, 1200); |
| try { |
| job.join(1200); |
| } |
| catch (InterruptedException ex) { |
| //nop |
| } |
| return hasValidMenus.get(); |
| } |
| |
| @Override |
| protected void setHorizontalAlignmentFromScout(int scoutAlign) { |
| if (getSwingTextField() instanceof JTextField) { |
| int swingAlign = SwingUtility.createHorizontalAlignment(scoutAlign); |
| ((JTextField) getSwingTextField()).setHorizontalAlignment(swingAlign); |
| } |
| } |
| |
| @Override |
| protected void setEnabledFromScout(boolean b) { |
| super.setEnabledFromScout(b); |
| if (getSwingField() instanceof JTextFieldWithDropDownButton) { |
| ((JTextFieldWithDropDownButton) getSwingTextField()).setDropDownButtonEnabled(b); |
| } |
| handleDropDownButtonEnabled(); |
| } |
| |
| protected void setFileIconIdFromScout(String s) { |
| if (getSwingField() instanceof JTextFieldWithDropDownButton) { |
| ((JTextFieldWithDropDownButton) getSwingField()).setIconGroup(new IconGroup(getSwingEnvironment(), s)); |
| } |
| } |
| |
| @Override |
| protected boolean handleSwingInputVerifier() { |
| final String text = getSwingTextField().getText(); |
| // only handle if text has changed |
| if (CompareUtility.equals(text, getScoutObject().getDisplayText()) && getScoutObject().getErrorStatus() == null) { |
| return true; |
| } |
| final Holder<Boolean> result = new Holder<Boolean>(Boolean.class, false); |
| // notify Scout |
| Runnable t = new Runnable() { |
| @Override |
| public void run() { |
| boolean b = getScoutObject().getUIFacade().setTextFromUI(text); |
| result.setValue(b); |
| } |
| }; |
| JobEx job = getSwingEnvironment().invokeScoutLater(t, 0); |
| try { |
| job.join(2345); |
| } |
| catch (InterruptedException e) { |
| //nop |
| } |
| // end notify |
| getSwingEnvironment().dispatchImmediateSwingJobs(); |
| return true;// continue always |
| } |
| |
| @Override |
| protected void handleSwingFocusGained() { |
| super.handleSwingFocusGained(); |
| JTextComponent swingField = getSwingTextField(); |
| if (swingField.getDocument().getLength() > 0) { |
| swingField.setCaretPosition(swingField.getDocument().getLength()); |
| swingField.moveCaretPosition(0); |
| } |
| } |
| |
| protected boolean isFileChooserEnabled() { |
| if (getSwingField() instanceof JTextFieldWithDropDownButton) { |
| return (((JTextFieldWithDropDownButton) getSwingTextField()).isDropDownButtonEnabled()); |
| } |
| return false; |
| } |
| |
| protected void handleSwingFileChooserAction() { |
| if (isFileChooserEnabled()) { |
| Runnable scoutJob = new Runnable() { |
| @Override |
| public void run() { |
| IFileChooser fc = getScoutObject().getFileChooser(); |
| final File[] files = fc.startChooser(); |
| |
| Runnable swingJob = new Runnable() { |
| @Override |
| public void run() { |
| if (files != null && files.length > 0) { |
| getSwingTextField().setText(files[0].getAbsolutePath()); |
| handleSwingInputVerifier(); |
| } |
| } |
| }; |
| if (getSwingEnvironment() != null) { |
| getSwingEnvironment().invokeSwingLater(swingJob); |
| } |
| } |
| }; |
| getSwingEnvironment().invokeScoutLater(scoutJob, 0); |
| } |
| } |
| |
| protected void handleSwingPopup(final JComponent target) { |
| if (getScoutObject().hasMenus()) { |
| // notify Scout |
| Runnable t = new Runnable() { |
| @Override |
| public void run() { |
| IMenu[] scoutMenus = getScoutObject().getUIFacade().firePopupFromUI(); |
| // <bsh 2010-10-08> |
| // The default implemention positions the popup menu on the left side of the |
| // "target" component. This is no longer correct in Rayo. So we use the target's |
| // width and substract a certain amount. |
| int x = 0; |
| if (target instanceof JTextFieldWithDropDownButton) { |
| JTextFieldWithDropDownButton tf = (JTextFieldWithDropDownButton) target; |
| x = tf.getWidth() - tf.getMargin().right; |
| } |
| Point point = new Point(x, target.getHeight()); |
| // </bsh> |
| // call swing menu |
| new SwingPopupWorker(getSwingEnvironment(), target, point, scoutMenus).enqueue(); |
| } |
| }; |
| getSwingEnvironment().invokeScoutLater(t, 5678); |
| // end notify |
| } |
| } |
| |
| @Override |
| protected void handleScoutPropertyChange(String name, Object newValue) { |
| super.handleScoutPropertyChange(name, newValue); |
| if (name.equals(IFileChooserField.PROP_FILE_ICON_ID)) { |
| setFileIconIdFromScout((String) newValue); |
| } |
| } |
| |
| protected void handleScoutActionPropertyChange(String name, Object newValue) { |
| if (IAction.PROP_INHERIT_ACCESSIBILITY.equals(name) || IAction.PROP_EMPTY_SPACE.equals(name) || |
| IAction.PROP_SINGLE_SELECTION.equals(name) || IAction.PROP_VISIBLE.equals(name)) { |
| handleDropDownButtonEnabled(); |
| } |
| } |
| |
| protected void handleDropDownButtonEnabled() { |
| if (getSwingField() instanceof JTextFieldWithDropDownButton) { |
| ((JTextFieldWithDropDownButton) getSwingField()).setMenuEnabled(calculateDropDownButtonEnabled()); |
| getSwingField().repaint(); |
| } |
| } |
| |
| /** |
| * Swing action |
| */ |
| private class P_SwingFileChooserAction extends AbstractAction { |
| private static final long serialVersionUID = 1L; |
| |
| @Override |
| public void actionPerformed(ActionEvent e) { |
| handleSwingFileChooserAction(); |
| } |
| }// end private class |
| |
| private class P_ScoutActionPropertyChangeListener extends AbstractSwingScoutActionPropertyChangeListener { |
| @Override |
| public void propertyChange(final PropertyChangeEvent e) { |
| Runnable t = new Runnable() { |
| @Override |
| public void run() { |
| try { |
| getUpdateSwingFromScoutLock().acquire(); |
| // |
| handleScoutActionPropertyChange(e.getPropertyName(), e.getNewValue()); |
| } |
| finally { |
| getUpdateSwingFromScoutLock().release(); |
| } |
| } |
| }; |
| getSwingEnvironment().invokeSwingLater(t); |
| } |
| } // end private class P_ScoutActionPropertyChangeListener |
| |
| } |