001package kiwi.ui.propeditor;
002
003import java.awt.*;
004import java.awt.event.*;
005import java.util.*;
006import javax.swing.*;
007import javax.swing.border.*;
008import javax.swing.event.*;
009import javax.swing.tree.*;
010
011import kiwi.ui.*;
012import kiwi.ui.model.*;
013
014/*
015 *
016 * @author Mark Lindner
017 */
018
019class PropertyCellEditor implements TreeCellEditor, TreeCellRenderer,
020                         ActionListener
021  {
022  private Border _border, _noborder;
023  private KLabel label, editorLabel;
024  private PropertyValueEditor editor = null;
025  private KPanel editorPanel;
026  protected EventListenerList listenerList = new EventListenerList();
027  transient protected ChangeEvent changeEvent = null;
028  private PropertyValueEditor fixedEditor = new FixedValueEditor();
029  private _MouseListener mouseListener;
030  private Hashtable editors;
031  private PropertyEditorFactory factory;
032
033  /*
034   */
035  
036  PropertyCellEditor(PropertyEditorFactory factory)
037    {
038    this.factory = factory;
039    
040    editorPanel = new KPanel();
041    editorPanel.setLayout(new BorderLayout(5, 5));
042
043    _border = new UnderlineBorder();
044    _noborder = new EmptyBorder(0, 0, 1, 0);
045    
046    editorLabel = new KLabel();
047    editorLabel.setBorder(_noborder);
048    mouseListener = new _MouseListener();
049    editorLabel.addMouseListener(mouseListener);
050    editorPanel.add("West", editorLabel);
051
052    editors = new Hashtable();
053
054    label = new KLabel();
055    label.setBorder(_noborder);
056    }
057
058  /*
059   */
060  
061  void setEditorFactory(PropertyEditorFactory factory)
062    {
063    editors.clear();
064    this.factory = factory;
065    }
066
067  /*
068   */
069
070  private PropertyValueEditor getEditor(PropertyType type)
071    {
072    PropertyValueEditor ed = (PropertyValueEditor)editors.get(type);
073    if(ed == null)
074      {
075      ed = factory.createEditor(type);
076      if(ed != null)
077        editors.put(type, ed);
078      }
079
080    return(ed);
081    }
082
083  /*
084   */
085
086  public synchronized Component getTreeCellEditorComponent(JTree tree,
087                                                           Object value,
088                                                           boolean selected,
089                                                           boolean expanded,
090                                                           boolean leaf,
091                                                           int row)
092    {
093    JComponent c;
094    Property prop = null;
095
096    if(editor != null)
097      {
098      c = editor.getEditorComponent();
099      editor.removeActionListener(this);
100      editorPanel.remove(c);
101      }
102    
103    editor = null;
104    
105    if(value instanceof Property)
106      {
107      prop = (Property)value;
108
109      PropertyType type = prop.getType();
110      
111      if(type != null && prop.isEditable())
112        editor = getEditor(type);
113
114      if(editor == null)
115        editor = fixedEditor;
116      
117      editor.setProperty(prop);
118      editorLabel.setIcon(prop.getIcon());
119      editorLabel.setText(prop.getName() + ":");
120      }
121    
122    // do we actually have an editor after all those checks?
123    
124    if(editor != null)
125      {
126      c = editor.getEditorComponent();
127      editor.addActionListener(this);
128      editorPanel.add("Center", c);
129//      c.setBorder(_noborder);
130      editor.startFocus();
131      }
132    
133    return(editorPanel);
134    }
135  
136  /*
137   */
138  
139  public synchronized Component getTreeCellRendererComponent(JTree tree,
140                                                             Object value,
141                                                             boolean selected,
142                                                             boolean expanded,
143                                                             boolean leaf,
144                                                             int row,
145                                                             boolean hasFocus)
146    {
147    if(value instanceof Property)
148      {
149      Property prop = (Property)value;
150      
151      label.setIcon(prop.getIcon());    
152      label.setText(prop.toString());
153      label.setBorder(prop.isEditable() ? _border : _noborder);
154      }
155    else
156      {
157      label.setText("?");
158      label.setIcon(null);
159      label.setBorder(null);
160      }
161    
162    return(label);
163    }
164  
165  /*
166   */
167  
168  public boolean isCellEditable(EventObject evt)
169    {
170    return(true);
171    }
172  
173  /*
174   */
175  
176  public boolean shouldSelectCell(EventObject evt)
177    {
178    if(editor != null)
179      editor.startFocus();
180    
181    return(true);
182    }
183  
184  /*
185   */
186  
187  public void addCellEditorListener(CellEditorListener listener)
188    {
189    listenerList.add(CellEditorListener.class, listener);
190    }
191  
192  /*
193   */
194  
195  public void removeCellEditorListener(CellEditorListener listener)
196    {
197    listenerList.remove(CellEditorListener.class, listener);
198    }
199  
200  /*
201   */
202  
203  protected void fireEditingStopped()
204    {
205    // Guaranteed to return a non-null array
206    
207    Object[] listeners = listenerList.getListenerList();
208    // Process the listeners last to first, notifying
209    // those that are interested in this event
210    for (int i = listeners.length-2; i>=0; i-=2)
211      {
212      if (listeners[i]==CellEditorListener.class)
213        {
214        // Lazily create the event:
215        if (changeEvent == null)
216          changeEvent = new ChangeEvent(this);
217        ((CellEditorListener)listeners[i+1]).editingStopped(changeEvent);
218        }          
219      }
220    }
221  
222  /*
223   */
224  
225  protected void fireEditingCanceled()
226    {
227    // Guaranteed to return a non-null array
228    Object[] listeners = listenerList.getListenerList();
229    // Process the listeners last to first, notifying
230    // those that are interested in this event
231    for(int i = listeners.length - 2; i >= 0; i -= 2)
232      {
233      if(listeners[i] == CellEditorListener.class)
234        {
235        // Lazily create the event:
236        if(changeEvent == null)
237          changeEvent = new ChangeEvent(this);
238        ((CellEditorListener)listeners[i + 1]).editingCanceled(changeEvent);
239        }
240      }
241    }
242  
243  /*
244   */
245  
246  public void cancelCellEditing()
247    {
248    fireEditingCanceled();
249    }
250  
251  /*
252   */
253  
254  public boolean stopCellEditing()
255    {
256    if(editor == null)
257      return(true);
258    
259    boolean ok = editor.validateInput();
260    
261    if(ok)
262      {
263      editor.commitInput();
264      fireEditingStopped();
265      }
266    
267    return(ok);
268    }
269
270  /*
271   */
272   
273  public Object getCellEditorValue()
274    {
275    return((editor == null) ? null : editor.getProperty().getValue());
276    }
277
278  /*
279   */
280   
281  public void actionPerformed(ActionEvent evt)
282    {
283    stopCellEditing();
284    }
285
286  /*
287   */
288  
289  private class UnderlineBorder extends AbstractBorder
290    {
291    private Insets _insets = new Insets(0, 0, 1, 0);
292    
293    UnderlineBorder()
294      {
295      super();
296      }
297    
298    public void paintBorder(java.awt.Component c, Graphics g, int x, int y,
299                            int width, int height)
300      {
301      Color oldColor = g.getColor();
302      
303      g.setColor(Color.gray);
304      g.drawLine(x, y + height - 1, x + width - 1, y + height - 1);
305      
306      g.setColor(oldColor);
307      }
308      
309    public Insets getBorderInsets()
310      {
311      return(_insets);
312      }
313    
314    public Insets getBorderInsets(Component c, Insets insets)
315      {
316      insets.left = insets.top = insets.right = 0;
317      insets.bottom = 1;
318      
319      return(insets);
320      }
321   }
322    
323   /*
324    */
325   
326  private class _MouseListener extends MouseAdapter
327    {
328    public void mouseClicked(MouseEvent evt)
329      {
330      if(editor != null)
331        {
332        editor.startFocus();
333        }
334      }
335    }
336  }
337
338/* end of source file */