001: package net.xoetrope.builder.editor.components.swing;
002:
003: import javax.swing.JPanel;
004: import javax.swing.table.TableCellEditor;
005: import javax.swing.JTable;
006: import javax.swing.JButton;
007: import java.awt.BorderLayout;
008: import javax.swing.JTextField;
009: import java.awt.Component;
010: import java.util.EventObject;
011: import java.awt.event.ActionEvent;
012: import javax.swing.event.CellEditorListener;
013: import javax.swing.event.EventListenerList;
014: import javax.swing.event.ChangeEvent;
015: import javax.swing.JFileChooser;
016: import java.awt.event.ActionListener;
017: import net.xoetrope.builder.editor.helper.AFileFilter;
018: import javax.swing.BorderFactory;
019: import java.awt.Dimension;
020: import net.xoetrope.builder.editor.XEditorUtilities;
021: import java.io.File;
022:
023: /**
024: * An editor for selection of a file name
025: * <p>Copyright (c) Xoetrope Ltd., 1998-2004</p>
026: * $Revision: 1.5 $
027: */
028: public class XImageNameEditor extends JPanel implements
029: TableCellEditor, ActionListener {
030: protected EventListenerList listenerList = new EventListenerList();
031: transient protected ChangeEvent changeEvent = null;
032:
033: protected JTextField editor;
034: protected JButton chooseBtn;
035: protected String defaultPath;
036: protected String defaultExtension;
037: protected String defaultCue;
038: protected String extensions[];
039:
040: public XImageNameEditor(String defPath, String extentions[],
041: String defExt, String defCue) {
042: defaultPath = defPath;
043: extensions = extentions;
044: defaultExtension = defExt;
045: defaultCue = defCue;
046:
047: setLayout(new BorderLayout());
048: editor = new JTextField(defPath);
049: editor.setBorder(BorderFactory.createEmptyBorder());
050: add(editor, BorderLayout.CENTER);
051: chooseBtn = new JButton("...");
052: chooseBtn.setPreferredSize(new Dimension(20, 100));
053: add(chooseBtn, BorderLayout.EAST);
054:
055: chooseBtn.addActionListener(this );
056: }
057:
058: /**
059: * Sets an initial <code>value</code> for the editor. This will cause
060: * the editor to <code>stopEditing</code> and lose any partially
061: * edited value if the editor is editing when this method is called. <p>
062: *
063: * Returns the component that should be added to the client's
064: * <code>Component</code> hierarchy. Once installed in the client's
065: * hierarchy this component will then be able to draw and receive
066: * user input.
067: *
068: * @param table the <code>JTable</code> that is asking the
069: * editor to edit; can be <code>null</code>
070: * @param value the value of the cell to be edited; it is
071: * up to the specific editor to interpret
072: * and draw the value. For example, if value is
073: * the string "true", it could be rendered as a
074: * string or it could be rendered as a check
075: * box that is checked. <code>null</code>
076: * is a valid value
077: * @param isSelected true if the cell is to be rendered with
078: * highlighting
079: * @param row the row of the cell being edited
080: * @param column the column of the cell being edited
081: * @return the component for editing
082: */
083: public Component getTableCellEditorComponent(JTable table,
084: Object value, boolean isSelected, int row, int column) {
085: return this ;
086: }
087:
088: /**
089: * Returns the value contained in the editor.
090: * @return the value contained in the editor
091: */
092: public Object getCellEditorValue() {
093: return editor.getText();
094: }
095:
096: /**
097: * Asks the editor if it can start editing using <code>anEvent</code>.
098: * <code>anEvent</code> is in the invoking component coordinate system.
099: * The editor can not assume the Component returned by
100: * <code>getCellEditorComponent</code> is installed. This method
101: * is intended for the use of client to avoid the cost of setting up
102: * and installing the editor component if editing is not possible.
103: * If editing can be started this method returns true.
104: *
105: * @param anEvent the event the editor should use to consider
106: * whether to begin editing or not
107: * @return true if editing can be started
108: * @see #shouldSelectCell
109: */
110: public boolean isCellEditable(EventObject anEvent) {
111: return true;
112: }
113:
114: /**
115: * Returns true if the editing cell should be selected, false otherwise.
116: * Typically, the return value is true, because is most cases the editing
117: * cell should be selected. However, it is useful to return false to
118: * keep the selection from changing for some types of edits.
119: * eg. A table that contains a column of check boxes, the user might
120: * want to be able to change those checkboxes without altering the
121: * selection. (See Netscape Communicator for just such an example)
122: * Of course, it is up to the client of the editor to use the return
123: * value, but it doesn't need to if it doesn't want to.
124: *
125: * @param anEvent the event the editor should use to start
126: * editing
127: * @return true if the editor would like the editing cell to be selected;
128: * otherwise returns false
129: * @see #isCellEditable
130: */
131: public boolean shouldSelectCell(EventObject anEvent) {
132: return true;
133: }
134:
135: /**
136: * Tells the editor to stop editing and accept any partially edited
137: * value as the value of the editor. The editor returns false if
138: * editing was not stopped; this is useful for editors that validate
139: * and can not accept invalid entries.
140: *
141: * @return true if editing was stopped; false otherwise
142: */
143: public boolean stopCellEditing() {
144: fireEditingStopped();
145: return true;
146: }
147:
148: /**
149: * Tells the editor to cancel editing and not accept any partially
150: * edited value.
151: */
152: public void cancelCellEditing() {
153: fireEditingCanceled();
154: }
155:
156: /**
157: * Adds a <code>CellEditorListener</code> to the listener list.
158: * @param l the new listener to be added
159: */
160: public void addCellEditorListener(CellEditorListener l) {
161: listenerList.add(CellEditorListener.class, l);
162: }
163:
164: /**
165: * Removes a <code>CellEditorListener</code> from the listener list.
166: * @param l the listener to be removed
167: */
168: public void removeCellEditorListener(CellEditorListener l) {
169: listenerList.remove(CellEditorListener.class, l);
170: }
171:
172: /**
173: * When an action is performed, editing is ended.
174: * @param e the action event
175: * @see #stopCellEditing
176: */
177: public void actionPerformed(ActionEvent e) {
178: if (e.getSource() == chooseBtn) {
179: JFileChooser chooser = new JFileChooser(defaultPath);
180: AFileFilter filter = new AFileFilter(defaultExtension,
181: defaultCue);
182: for (int i = 0; i < extensions.length; i++)
183: filter.addExtension(extensions[i]);
184:
185: chooser.setFileFilter(filter);
186: int i = chooser.showOpenDialog(this );
187: if (i == 0) {
188: String fullPath = chooser.getSelectedFile()
189: .getAbsolutePath();
190: String fileName = fullPath.substring(fullPath
191: .lastIndexOf(File.separatorChar) + 1);
192: String targetPath = fullPath;
193: if (fullPath.compareToIgnoreCase(targetPath) != 0)
194: XEditorUtilities.copyFile(fullPath, targetPath);
195: editor.setText(fileName);
196: fireEditingStopped();
197: }
198: } else
199: stopCellEditing();
200: }
201:
202: /**
203: * Returns an array of all the <code>CellEditorListener</code>s added
204: * to this AbstractCellEditor with addCellEditorListener().
205: *
206: * @return all of the <code>CellEditorListener</code>s added or an empty
207: * array if no listeners have been added
208: * @since 1.4
209: */
210: public CellEditorListener[] getCellEditorListeners() {
211: return (CellEditorListener[]) listenerList
212: .getListeners(CellEditorListener.class);
213: }
214:
215: /**
216: * Notifies all listeners that have registered interest for
217: * notification on this event type. The event instance
218: * is created lazily.
219: *
220: * @see EventListenerList
221: */
222: protected void fireEditingStopped() {
223: // Guaranteed to return a non-null array
224: Object[] listeners = listenerList.getListenerList();
225: // Process the listeners last to first, notifying
226: // those that are interested in this event
227: for (int i = listeners.length - 2; i >= 0; i -= 2) {
228: if (listeners[i] == CellEditorListener.class) {
229: // Lazily create the event:
230: if (changeEvent == null)
231: changeEvent = new ChangeEvent(this );
232: ((CellEditorListener) listeners[i + 1])
233: .editingStopped(changeEvent);
234: }
235: }
236: }
237:
238: /**
239: * Notifies all listeners that have registered interest for
240: * notification on this event type. The event instance
241: * is created lazily.
242: *
243: * @see EventListenerList
244: */
245: protected void fireEditingCanceled() {
246: // Guaranteed to return a non-null array
247: Object[] listeners = listenerList.getListenerList();
248: // Process the listeners last to first, notifying
249: // those that are interested in this event
250: for (int i = listeners.length - 2; i >= 0; i -= 2) {
251: if (listeners[i] == CellEditorListener.class) {
252: // Lazily create the event:
253: if (changeEvent == null)
254: changeEvent = new ChangeEvent(this );
255: ((CellEditorListener) listeners[i + 1])
256: .editingCanceled(changeEvent);
257: }
258: }
259: }
260: }
|