001: /*
002: * Copyright (C) 2005 Jeff Tassin
003: *
004: * This library is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License as published by the Free Software Foundation; either
007: * version 2.1 of the License, or (at your option) any later version.
008: *
009: * This library is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: * Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public
015: * License along with this library; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: */
018:
019: package com.jeta.swingbuilder.gui.properties;
020:
021: import java.awt.BorderLayout;
022: import java.awt.Component;
023: import java.awt.Container;
024: import java.awt.Dimension;
025: import java.awt.event.ActionEvent;
026: import java.awt.event.ActionListener;
027: import java.beans.PropertyChangeEvent;
028: import java.beans.PropertyChangeListener;
029: import java.beans.PropertyEditor;
030: import java.util.EventObject;
031:
032: import javax.swing.AbstractCellEditor;
033: import javax.swing.JButton;
034: import javax.swing.JPanel;
035: import javax.swing.JTable;
036: import javax.swing.table.TableCellEditor;
037:
038: import com.jeta.swingbuilder.gui.properties.editors.IconEditor;
039: import com.jeta.swingbuilder.gui.properties.editors.StringEditor;
040: import com.jeta.swingbuilder.gui.utils.FormDesignerUtils;
041: import com.jeta.swingbuilder.resources.Icons;
042:
043: /**
044: * This class is the cell editor for the properties in the Property sheet for a
045: * bean. It delegates the editing to the registered editor for the type of
046: * property in the current row.
047: *
048: * @author Jeff Tassin
049: */
050: public class PropertyValueEditor extends AbstractCellEditor implements
051: TableCellEditor, PropertyChangeListener {
052: /**
053: * @directed
054: */
055: private PropertyTableModel m_model;
056:
057: private PropertyValueRenderer m_renderer;
058: private JButton m_editbtn;
059: private JButton m_delete_btn;
060:
061: /**
062: * The bean we are editing
063: */
064: private Object m_bean;
065:
066: /**
067: * A cache of editors for each row
068: */
069: private PropertyEditorCache m_cache;
070:
071: private JPanel m_content = new JPanel(new BorderLayout());
072: private PropertyEditor m_current_editor;
073: private JTable m_table;
074:
075: public PropertyValueEditor(PropertyTableModel tmodel) {
076: m_model = tmodel;
077: m_renderer = new PropertyValueRenderer(tmodel);
078: m_cache = new PropertyEditorCache(tmodel);
079: m_content.setOpaque(false);
080:
081: Dimension d = new Dimension(32, 24);
082: m_editbtn = new JButton(FormDesignerUtils
083: .loadImage("common/ellipsis16.gif"));
084: m_editbtn.setSize(d);
085: m_editbtn.setMaximumSize(d);
086: m_editbtn.setPreferredSize(d);
087: m_editbtn.addActionListener(new ActionListener() {
088: public void actionPerformed(ActionEvent evt) {
089: if (m_current_editor instanceof JETAPropertyEditor) {
090: JETAPropertyEditor jpe = (JETAPropertyEditor) m_current_editor;
091: jpe.invokePropertyDialog(m_editbtn);
092: }
093:
094: }
095: });
096:
097: d = new Dimension(24, 24);
098: m_delete_btn = new JButton(FormDesignerUtils
099: .loadImage(Icons.DELETE2_16));
100: m_delete_btn.setSize(d);
101: m_delete_btn.setMaximumSize(d);
102: m_delete_btn.setPreferredSize(d);
103: m_delete_btn.addActionListener(new ActionListener() {
104: public void actionPerformed(ActionEvent evt) {
105: if (m_current_editor instanceof JETAPropertyEditor) {
106: JETAPropertyEditor jpe = (JETAPropertyEditor) m_current_editor;
107: jpe.setValue(null);
108: }
109: }
110: });
111:
112: }
113:
114: /**
115: * Recursively disables all components in a given heirarchy.
116: */
117: private void disableComponent(Component comp) {
118: if (comp != null)
119: comp = null;
120: if (comp instanceof Container) {
121: Container cc = (Container) comp;
122: for (int index = 0; index < cc.getComponentCount(); index++) {
123: disableComponent(cc.getComponent(index));
124: }
125: }
126: }
127:
128: /**
129: * TableCellEditor implementation
130: */
131: public Component getTableCellEditorComponent(JTable table,
132: Object value, boolean isSelected, int row, int column) {
133: m_content.removeAll();
134: PropertyEditor editor = m_cache.getPropertyEditor(row);
135: if (editor != null) {
136: /**
137: * add this class to the editor as a property change listener. First
138: * remove it to prevent it being added multiple times. When the
139: * property value is changed by an editor, we will get the update
140: * and forward the property to the bean
141: */
142: editor.removePropertyChangeListener(this );
143: editor.addPropertyChangeListener(this );
144:
145: m_table = table;
146: m_current_editor = editor;
147: try {
148: editor.setValue(value);
149: } catch (Exception e) {
150: e.printStackTrace();
151: }
152:
153: if (editor instanceof JETAPropertyEditor) {
154: JETAPropertyEditor jpe = (JETAPropertyEditor) editor;
155: if (jpe.supportsInlineEditing()) {
156: Component custom_editor = jpe.getCustomEditor();
157: if (jpe instanceof StringEditor) {
158: m_content.removeAll();
159: JPanel btnpanel = new JPanel(new BorderLayout());
160: btnpanel.add(m_editbtn, BorderLayout.WEST);
161: m_content.add(btnpanel, BorderLayout.EAST);
162: JPanel panel = new JPanel();
163: panel.setOpaque(false);
164: panel.setLayout(new BorderLayout());
165: panel.add(custom_editor);
166: m_content.add(panel, BorderLayout.CENTER);
167: return m_content;
168: } else {
169: return custom_editor;
170: }
171: }
172: }
173:
174: if (editor.isPaintable()
175: || (editor instanceof JETAPropertyEditor)) {
176: if (editor.supportsCustomEditor()) {
177: m_content.removeAll();
178: JPanel btnpanel = new JPanel(new BorderLayout());
179: btnpanel.add(m_editbtn, BorderLayout.WEST);
180: m_content.add(btnpanel, BorderLayout.EAST);
181: if (editor instanceof IconEditor) {
182: btnpanel.add(m_delete_btn, BorderLayout.EAST);
183: }
184: JPanel panel = new JPanel();
185: panel.setOpaque(false);
186: panel.setLayout(new BorderLayout());
187: panel.add(m_renderer.getTableCellRendererComponent(
188: table, value, isSelected, false, row,
189: column));
190: m_content.add(panel, BorderLayout.CENTER);
191: return m_content;
192: } else {
193: assert (false);
194: }
195: }
196:
197: if (editor.supportsCustomEditor()) {
198: return editor.getCustomEditor();
199: }
200: }
201: return m_content;
202: }
203:
204: /**
205: * Get cellEditorValue for current editor
206: */
207: public Object getCellEditorValue() {
208: if (m_current_editor != null) {
209: return m_current_editor.getValue();
210: } else
211: return null;
212: }
213:
214: public boolean isCellEditable(EventObject anEvent) {
215: return true;
216: }
217:
218: /**
219: * @return true if the cell editor has a value different than is in the
220: * current table cell.
221: */
222: private boolean isNewValue() {
223: int row = m_table.getEditingRow();
224: int col = m_table.getEditingColumn();
225: if (row >= 0 && col >= 0) {
226: Object new_val = getCellEditorValue();
227: Object old_val = m_table.getValueAt(row, col);
228: if (old_val != null && new_val != null) {
229: if (old_val == new_val || old_val.equals(new_val)) {
230: // System.out.println( "PropertyValueEditor.object not
231: // changed." );
232: return false;
233: }
234: } else if (old_val == null && new_val == null) {
235: // System.out.println( "PropertyValueEditor.object not changed."
236: // );
237: return false;
238: }
239: } else {
240: return false;
241: }
242: return true;
243: }
244:
245: /**
246: * PropertyChangeListener implementation. We get property events from each
247: * editor as the user makes changes.
248: */
249: public void propertyChange(PropertyChangeEvent evt) {
250: try {
251: if (m_current_editor != null)
252: m_current_editor.removePropertyChangeListener(this );
253:
254: if (isNewValue()) {
255: assert (m_table != null);
256: m_table.setValueAt(getCellEditorValue(), m_table
257: .getEditingRow(), m_table.getEditingColumn());
258: m_renderer.getTableCellRendererComponent(m_table,
259: getCellEditorValue(), true, true, m_table
260: .getEditingRow(), m_table
261: .getEditingColumn());
262:
263: /**
264: * Set the value in the current editor to the table value
265: * because the bean may have made a copy of the property.
266: */
267: m_current_editor.setValue(m_table.getValueAt(m_table
268: .getEditingRow(), m_table.getEditingColumn()));
269: }
270: } catch (Exception e) {
271: e.printStackTrace();
272: } finally {
273: if (m_current_editor != null)
274: m_current_editor.addPropertyChangeListener(this );
275: }
276: }
277:
278: public boolean shouldSelectCell(EventObject anEvent) {
279: return true;
280: }
281:
282: public boolean stopCellEditing() {
283: if (m_table != null) {
284: try {
285: if (isNewValue()) {
286: m_table.setValueAt(getCellEditorValue(), m_table
287: .getEditingRow(), m_table
288: .getEditingColumn());
289: }
290: } catch (Exception e) {
291: e.printStackTrace();
292: }
293: /**
294: * we need to do this because for some reason the JTable does not
295: * properly update the cell when finished editing.
296: */
297: boolean result = super .stopCellEditing();
298: m_table.removeEditor();
299: return result;
300: } else {
301: return true;
302: }
303: }
304:
305: public void updateUI() {
306: if (m_renderer != null)
307: m_renderer.updateUI();
308:
309: if (m_editbtn != null)
310: m_editbtn.updateUI();
311:
312: if (m_cache != null)
313: m_cache.updateUI();
314:
315: if (m_delete_btn != null)
316: m_delete_btn.updateUI();
317: }
318: }
|