OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [javax/] [swing/] [tree/] [DefaultTreeCellEditor.java] - Blame information for rev 772

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 772 jeremybenn
/* DefaultTreeCellEditor.java --
2
   Copyright (C) 2002, 2004, 2005  Free Software Foundation, Inc.
3
 
4
This file is part of GNU Classpath.
5
 
6
GNU Classpath is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2, or (at your option)
9
any later version.
10
 
11
GNU Classpath is distributed in the hope that it will be useful, but
12
WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with GNU Classpath; see the file COPYING.  If not, write to the
18
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
02110-1301 USA.
20
 
21
Linking this library statically or dynamically with other modules is
22
making a combined work based on this library.  Thus, the terms and
23
conditions of the GNU General Public License cover the whole
24
combination.
25
 
26
As a special exception, the copyright holders of this library give you
27
permission to link this library with independent modules to produce an
28
executable, regardless of the license terms of these independent
29
modules, and to copy and distribute the resulting executable under
30
terms of your choice, provided that you also meet, for each linked
31
independent module, the terms and conditions of the license of that
32
module.  An independent module is a module which is not derived from
33
or based on this library.  If you modify this library, you may extend
34
this exception to your version of the library, but you are not
35
obligated to do so.  If you do not wish to do so, delete this
36
exception statement from your version. */
37
 
38
 
39
package javax.swing.tree;
40
 
41
import java.awt.Color;
42
import java.awt.Component;
43
import java.awt.Container;
44
import java.awt.Dimension;
45
import java.awt.Font;
46
import java.awt.Graphics;
47
import java.awt.Rectangle;
48
import java.awt.event.ActionEvent;
49
import java.awt.event.ActionListener;
50
import java.awt.event.MouseEvent;
51
import java.io.IOException;
52
import java.io.ObjectInputStream;
53
import java.io.ObjectOutputStream;
54
import java.util.EventObject;
55
 
56
import javax.swing.DefaultCellEditor;
57
import javax.swing.Icon;
58
import javax.swing.JTextField;
59
import javax.swing.JTree;
60
import javax.swing.SwingUtilities;
61
import javax.swing.Timer;
62
import javax.swing.UIManager;
63
import javax.swing.border.Border;
64
import javax.swing.event.CellEditorListener;
65
import javax.swing.event.EventListenerList;
66
import javax.swing.event.TreeSelectionEvent;
67
import javax.swing.event.TreeSelectionListener;
68
 
69
/**
70
 * Participates in the tree cell editing.
71
 *
72
 * @author Andrew Selkirk
73
 * @author Audrius Meskauskas
74
 */
75
public class DefaultTreeCellEditor
76
  implements ActionListener, TreeCellEditor, TreeSelectionListener
77
{
78
  /**
79
   * This container that appears on the tree during editing session.
80
   * It contains the editing component displays various other editor -
81
   * specific parts like editing icon.
82
   */
83
  public class EditorContainer extends Container
84
  {
85
   /**
86
    * Use v 1.5 serial version UID for interoperability.
87
    */
88
    static final long serialVersionUID = 6470339600449699810L;
89
 
90
    /**
91
     * Creates an <code>EditorContainer</code> object.
92
     */
93
    public EditorContainer()
94
    {
95
      setLayout(null);
96
    }
97
 
98
    /**
99
     * This method only exists for API compatibility and is useless as it does
100
     * nothing. It got probably introduced by accident.
101
     */
102
    public void EditorContainer()
103
    {
104
      // Do nothing here.
105
    }
106
 
107
    /**
108
     * Overrides Container.paint to paint the node's icon and use the selection
109
     * color for the background.
110
     *
111
     * @param g -
112
     *          the specified Graphics window
113
     */
114
    public void paint(Graphics g)
115
    {
116
      // Paint editing icon.
117
      if (editingIcon != null)
118
        {
119
          // From the previous version, the left margin is taken as half
120
          // of the icon width.
121
          int y = Math.max(0, (getHeight() - editingIcon.getIconHeight()) / 2);
122
          editingIcon.paintIcon(this, g, 0, y);
123
        }
124
      // Paint border.
125
      Color c = getBorderSelectionColor();
126
      if (c != null)
127
        {
128
          g.setColor(c);
129
          g.drawRect(0, 0, getWidth() - 1, getHeight() - 1);
130
        }
131
      super.paint(g);
132
    }
133
 
134
    /**
135
     * Lays out this Container, moving the editor component to the left
136
     * (leaving place for the icon).
137
     */
138
    public void doLayout()
139
    {
140
      if (editingComponent != null)
141
        {
142
          editingComponent.getPreferredSize();
143
          editingComponent.setBounds(offset, 0, getWidth() - offset,
144
                                     getHeight());
145
        }
146
      }
147
 
148
    public Dimension getPreferredSize()
149
    {
150
      Dimension dim;
151
      if (editingComponent != null)
152
        {
153
          dim = editingComponent.getPreferredSize();
154
          dim.width += offset + 5;
155
          if (renderer != null)
156
            {
157
              Dimension r = renderer.getPreferredSize();
158
              dim.height = Math.max(dim.height, r.height);
159
            }
160
          if (editingIcon != null)
161
            dim.height = Math.max(dim.height, editingIcon.getIconHeight());
162
          dim.width = Math.max(100, dim.width);
163
        }
164
      else
165
        dim = new Dimension(0, 0);
166
      return dim;
167
    }
168
  }
169
 
170
  /**
171
   * The default text field, used in the editing sessions.
172
   */
173
  public class DefaultTextField extends JTextField
174
  {
175
   /**
176
    * Use v 1.5 serial version UID for interoperability.
177
    */
178
    static final long serialVersionUID = -6629304544265300143L;
179
 
180
    /**
181
     * The border of the text field.
182
     */
183
    protected Border border;
184
 
185
    /**
186
     * Creates a <code>DefaultTextField</code> object.
187
     *
188
     * @param aBorder the border to use
189
     */
190
    public DefaultTextField(Border aBorder)
191
    {
192
      border = aBorder;
193
    }
194
 
195
    /**
196
     * Gets the font of this component.
197
     * @return this component's font; if a font has not been set for
198
     * this component, the font of its parent is returned (if the parent
199
     * is not null, otherwise null is returned).
200
     */
201
    public Font getFont()
202
    {
203
      Font font = super.getFont();
204
      if (font == null)
205
        {
206
          Component parent = getParent();
207
          if (parent != null)
208
            return parent.getFont();
209
          return null;
210
        }
211
      return font;
212
    }
213
 
214
    /**
215
     * Returns the border of the text field.
216
     *
217
     * @return the border
218
     */
219
    public Border getBorder()
220
    {
221
      return border;
222
    }
223
 
224
    /**
225
     * Overrides JTextField.getPreferredSize to return the preferred size
226
     * based on current font, if set, or else use renderer's font.
227
     *
228
     * @return the Dimension of this textfield.
229
     */
230
    public Dimension getPreferredSize()
231
    {
232
      Dimension size = super.getPreferredSize();
233
      if (renderer != null && DefaultTreeCellEditor.this.getFont() == null)
234
        {
235
          size.height = renderer.getPreferredSize().height;
236
        }
237
      return renderer.getPreferredSize();
238
    }
239
  }
240
 
241
  private EventListenerList listenerList = new EventListenerList();
242
 
243
  /**
244
   * Editor handling the editing.
245
   */
246
  protected TreeCellEditor realEditor;
247
 
248
  /**
249
   * Renderer, used to get border and offsets from.
250
   */
251
  protected DefaultTreeCellRenderer renderer;
252
 
253
  /**
254
   * Editing container, will contain the editorComponent.
255
   */
256
  protected Container editingContainer;
257
 
258
  /**
259
   * Component used in editing, obtained from the editingContainer.
260
   */
261
  protected transient Component editingComponent;
262
 
263
  /**
264
   * As of Java 2 platform v1.4 this field should no longer be used.
265
   * If you wish to provide similar behavior you should directly
266
   * override isCellEditable.
267
   */
268
  protected boolean canEdit;
269
 
270
  /**
271
   * Used in editing. Indicates x position to place editingComponent.
272
   */
273
  protected transient int offset;
274
 
275
  /**
276
   * JTree instance listening too.
277
   */
278
  protected transient JTree tree;
279
 
280
  /**
281
   * Last path that was selected.
282
   */
283
  protected transient TreePath lastPath;
284
 
285
  /**
286
   * Used before starting the editing session.
287
   */
288
  protected transient javax.swing.Timer timer;
289
 
290
  /**
291
   * Row that was last passed into getTreeCellEditorComponent.
292
   */
293
  protected transient int lastRow;
294
 
295
  /**
296
   * True if the border selection color should be drawn.
297
   */
298
  protected Color borderSelectionColor;
299
 
300
  /**
301
   * Icon to use when editing.
302
   */
303
  protected transient Icon editingIcon;
304
 
305
  /**
306
   * Font to paint with, null indicates font of renderer is to be used.
307
   */
308
  protected Font font;
309
 
310
  /**
311
   * Constructs a DefaultTreeCellEditor object for a JTree using the
312
   * specified renderer and a default editor. (Use this constructor
313
   * for normal editing.)
314
   *
315
   * @param tree - a JTree object
316
   * @param renderer - a DefaultTreeCellRenderer object
317
   */
318
  public DefaultTreeCellEditor(JTree tree, DefaultTreeCellRenderer renderer)
319
  {
320
    this(tree, renderer, null);
321
  }
322
 
323
  /**
324
   * Constructs a DefaultTreeCellEditor  object for a JTree using the specified
325
   * renderer and the specified editor. (Use this constructor
326
   * for specialized editing.)
327
   *
328
   * @param tree - a JTree object
329
   * @param renderer - a DefaultTreeCellRenderer object
330
   * @param editor - a TreeCellEditor object
331
   */
332
  public DefaultTreeCellEditor(JTree tree, DefaultTreeCellRenderer renderer,
333
                               TreeCellEditor editor)
334
  {
335
    this.renderer = renderer;
336
    realEditor = editor;
337
    if (realEditor == null)
338
      realEditor = createTreeCellEditor();
339
    editingContainer = createContainer();
340
    setTree(tree);
341
    Color c = UIManager.getColor("Tree.editorBorderSelectionColor");
342
    setBorderSelectionColor(c);
343
  }
344
 
345
  /**
346
   * writeObject
347
   *
348
   * @param value0
349
   *          TODO
350
   * @exception IOException
351
   *              TODO
352
   */
353
  private void writeObject(ObjectOutputStream value0) throws IOException
354
  {
355
    // TODO
356
  }
357
 
358
  /**
359
   * readObject
360
   * @param value0 TODO
361
   * @exception IOException TODO
362
   * @exception ClassNotFoundException TODO
363
   */
364
  private void readObject(ObjectInputStream value0)
365
    throws IOException, ClassNotFoundException
366
  {
367
    // TODO
368
  }
369
 
370
  /**
371
   * Sets the color to use for the border.
372
   * @param newColor - the new border color
373
   */
374
  public void setBorderSelectionColor(Color newColor)
375
  {
376
    this.borderSelectionColor = newColor;
377
  }
378
 
379
  /**
380
   * Returns the color the border is drawn.
381
   * @return Color
382
   */
383
  public Color getBorderSelectionColor()
384
  {
385
    return borderSelectionColor;
386
  }
387
 
388
  /**
389
   * Sets the font to edit with. null indicates the renderers
390
   * font should be used. This will NOT override any font you have
391
   * set in the editor the receiver was instantied with. If null for
392
   * an editor was passed in, a default editor will be created that
393
   * will pick up this font.
394
   *
395
   * @param font - the editing Font
396
   */
397
  public void setFont(Font font)
398
  {
399
    if (font != null)
400
      this.font = font;
401
    else
402
      this.font = renderer.getFont();
403
  }
404
 
405
  /**
406
   * Gets the font used for editing.
407
   *
408
   * @return the editing font
409
   */
410
  public Font getFont()
411
  {
412
    return font;
413
  }
414
 
415
  /**
416
   * Configures the editor. Passed onto the realEditor.
417
   * Sets an initial value for the editor. This will cause
418
   * the editor to stopEditing and lose any partially edited value
419
   * if the editor is editing when this method is called.
420
   * Returns the component that should be added to the client's Component
421
   * hierarchy. Once installed in the client's hierarchy this component will
422
   * then be able to draw and receive user input.
423
   *
424
   * @param tree - the JTree that is asking the editor to edit; this parameter can be null
425
   * @param value - the value of the cell to be edited
426
   * @param isSelected - true is the cell is to be rendered with selection highlighting
427
   * @param expanded - true if the node is expanded
428
   * @param leaf - true if the node is a leaf node
429
   * @param row - the row index of the node being edited
430
   *
431
   * @return the component for editing
432
   */
433
  public Component getTreeCellEditorComponent(JTree tree, Object value,
434
                                              boolean isSelected,
435
                                              boolean expanded,
436
                                              boolean leaf, int row)
437
  {
438
    setTree(tree);
439
    lastRow = row;
440
    determineOffset(tree, value, isSelected, expanded, leaf, row);
441
    if (editingComponent != null)
442
      editingContainer.remove(editingComponent);
443
 
444
    editingComponent = realEditor.getTreeCellEditorComponent(tree, value,
445
                                                             isSelected,
446
                                                             expanded, leaf,
447
                                                             row);
448
    Font f = getFont();
449
    if (f == null)
450
      {
451
        if (renderer != null)
452
          f = renderer.getFont();
453
        if (f == null)
454
          f = tree.getFont();
455
      }
456
    editingContainer.setFont(f);
457
    prepareForEditing();
458
    return editingContainer;
459
  }
460
 
461
  /**
462
   * Returns the value currently being edited (requests it from the
463
   * {@link #realEditor}.
464
   *
465
   * @return the value currently being edited
466
   */
467
  public Object getCellEditorValue()
468
  {
469
    return realEditor.getCellEditorValue();
470
  }
471
 
472
  /**
473
   * If the realEditor returns true to this message, prepareForEditing
474
   * is messaged and true is returned.
475
   *
476
   * @param event - the event the editor should use to consider whether to
477
   * begin editing or not
478
   * @return true if editing can be started
479
   */
480
  public boolean isCellEditable(EventObject event)
481
  {
482
    boolean ret = false;
483
    boolean ed = false;
484
    if (event != null)
485
      {
486
        if (event.getSource() instanceof JTree)
487
          {
488
            setTree((JTree) event.getSource());
489
            if (event instanceof MouseEvent)
490
              {
491
                MouseEvent me = (MouseEvent) event;
492
                TreePath path = tree.getPathForLocation(me.getX(), me.getY());
493
                ed = lastPath != null && path != null && lastPath.equals(path);
494
                if (path != null)
495
                  {
496
                    lastRow = tree.getRowForPath(path);
497
                    Object val = path.getLastPathComponent();
498
                    boolean isSelected = tree.isRowSelected(lastRow);
499
                    boolean isExpanded = tree.isExpanded(path);
500
                    TreeModel m = tree.getModel();
501
                    boolean isLeaf = m.isLeaf(val);
502
                    determineOffset(tree, val, isSelected, isExpanded, isLeaf,
503
                                    lastRow);
504
                  }
505
              }
506
          }
507
      }
508
    if (! realEditor.isCellEditable(event))
509
      ret = false;
510
    else
511
      {
512
        if (canEditImmediately(event))
513
          ret = true;
514
        else if (ed && shouldStartEditingTimer(event))
515
          startEditingTimer();
516
        else if (timer != null && timer.isRunning())
517
          timer.stop();
518
      }
519
    if (ret)
520
      prepareForEditing();
521
    return ret;
522
 
523
  }
524
 
525
  /**
526
   * Messages the realEditor for the return value.
527
   *
528
   * @param event -
529
   *          the event the editor should use to start editing
530
   * @return true if the editor would like the editing cell to be selected;
531
   *         otherwise returns false
532
   */
533
  public boolean shouldSelectCell(EventObject event)
534
  {
535
    return true;
536
  }
537
 
538
  /**
539
   * If the realEditor will allow editing to stop, the realEditor
540
   * is removed and true is returned, otherwise false is returned.
541
   * @return true if editing was stopped; false otherwise
542
   */
543
  public boolean stopCellEditing()
544
  {
545
    boolean ret = false;
546
    if (realEditor.stopCellEditing())
547
      {
548
        finish();
549
        ret = true;
550
      }
551
    return ret;
552
  }
553
 
554
  /**
555
   * Messages cancelCellEditing to the realEditor and removes it
556
   * from this instance.
557
   */
558
  public void cancelCellEditing()
559
  {
560
    realEditor.cancelCellEditing();
561
    finish();
562
  }
563
 
564
  private void finish()
565
  {
566
    if (editingComponent != null)
567
      editingContainer.remove(editingComponent);
568
    editingComponent = null;
569
  }
570
 
571
  /**
572
   * Adds a <code>CellEditorListener</code> object to this editor.
573
   *
574
   * @param listener
575
   *          the listener to add
576
   */
577
  public void addCellEditorListener(CellEditorListener listener)
578
  {
579
    realEditor.addCellEditorListener(listener);
580
  }
581
 
582
  /**
583
   * Removes a <code>CellEditorListener</code> object.
584
   *
585
   * @param listener the listener to remove
586
   */
587
  public void removeCellEditorListener(CellEditorListener listener)
588
  {
589
    realEditor.removeCellEditorListener(listener);
590
  }
591
 
592
  /**
593
   * Returns all added <code>CellEditorListener</code> objects to this editor.
594
   *
595
   * @return an array of listeners
596
   *
597
   * @since 1.4
598
   */
599
  public CellEditorListener[] getCellEditorListeners()
600
  {
601
    return (CellEditorListener[]) listenerList.getListeners(CellEditorListener.class);
602
  }
603
 
604
  /**
605
   * Resets lastPath.
606
   *
607
   * @param e - the event that characterizes the change.
608
   */
609
  public void valueChanged(TreeSelectionEvent e)
610
  {
611
    if (tree != null)
612
      {
613
        if (tree.getSelectionCount() == 1)
614
          lastPath = tree.getSelectionPath();
615
        else
616
          lastPath = null;
617
      }
618
    // TODO: We really should do the following here, but can't due
619
    // to buggy DefaultTreeSelectionModel. This selection model
620
    // should only fire if the selection actually changes.
621
//    if (timer != null)
622
//      timer.stop();
623
  }
624
 
625
  /**
626
   * Messaged when the timer fires.
627
   *
628
   * @param e the event that characterizes the action.
629
   */
630
  public void actionPerformed(ActionEvent e)
631
  {
632
    if (tree != null && lastPath != null)
633
      tree.startEditingAtPath(lastPath);
634
  }
635
 
636
  /**
637
   * Sets the tree currently editing for. This is needed to add a selection
638
   * listener.
639
   *
640
   * @param newTree -
641
   *          the new tree to be edited
642
   */
643
  protected void setTree(JTree newTree)
644
  {
645
    if (tree != newTree)
646
      {
647
        if (tree != null)
648
          tree.removeTreeSelectionListener(this);
649
        tree = newTree;
650
        if (tree != null)
651
          tree.addTreeSelectionListener(this);
652
 
653
        if (timer != null)
654
          timer.stop();
655
      }
656
  }
657
 
658
  /**
659
   * Returns true if event is a MouseEvent and the click count is 1.
660
   *
661
   * @param event - the event being studied
662
   * @return true if editing should start
663
   */
664
  protected boolean shouldStartEditingTimer(EventObject event)
665
  {
666
    boolean ret = false;
667
    if (event instanceof MouseEvent)
668
      {
669
        MouseEvent me = (MouseEvent) event;
670
        ret = SwingUtilities.isLeftMouseButton(me) && me.getClickCount() == 1
671
              && inHitRegion(me.getX(), me.getY());
672
      }
673
    return ret;
674
  }
675
 
676
  /**
677
   * Starts the editing timer (if one installed).
678
   */
679
  protected void startEditingTimer()
680
  {
681
    if (timer == null)
682
      {
683
        timer = new Timer(1200, this);
684
        timer.setRepeats(false);
685
      }
686
    timer.start();
687
  }
688
 
689
  /**
690
   * Returns true if event is null, or it is a MouseEvent with
691
   * a click count > 2 and inHitRegion returns true.
692
   *
693
   * @param event - the event being studied
694
   * @return true if event is null, or it is a MouseEvent with
695
   * a click count > 2 and inHitRegion returns true
696
   */
697
  protected boolean canEditImmediately(EventObject event)
698
  {
699
    if (event == null || !(event instanceof MouseEvent) || (((MouseEvent) event).
700
        getClickCount() > 2 && inHitRegion(((MouseEvent) event).getX(),
701
                                         ((MouseEvent) event).getY())))
702
      return true;
703
    return false;
704
  }
705
 
706
  /**
707
   * Returns true if the passed in location is a valid mouse location
708
   * to start editing from. This is implemented to return false if x is
709
   * less than or equal to the width of the icon and icon
710
   * gap displayed by the renderer. In other words this returns true if
711
   * the user clicks over the text part displayed by the renderer, and
712
   * false otherwise.
713
   *
714
   * @param x - the x-coordinate of the point
715
   * @param y - the y-coordinate of the point
716
   *
717
   * @return true if the passed in location is a valid mouse location
718
   */
719
  protected boolean inHitRegion(int x, int y)
720
  {
721
    Rectangle bounds = tree.getPathBounds(lastPath);
722
    return bounds.contains(x, y);
723
  }
724
 
725
  /**
726
   * determineOffset
727
   * @param tree -
728
   * @param value -
729
   * @param isSelected -
730
   * @param expanded -
731
   * @param leaf -
732
   * @param row -
733
   */
734
  protected void determineOffset(JTree tree, Object value, boolean isSelected,
735
                                 boolean expanded, boolean leaf, int row)
736
  {
737
    if (renderer != null)
738
      {
739
        if (leaf)
740
          editingIcon = renderer.getLeafIcon();
741
        else if (expanded)
742
          editingIcon = renderer.getOpenIcon();
743
        else
744
          editingIcon = renderer.getClosedIcon();
745
        if (editingIcon != null)
746
          offset = renderer.getIconTextGap() + editingIcon.getIconWidth();
747
        else
748
          offset = renderer.getIconTextGap();
749
      }
750
    else
751
      {
752
        editingIcon = null;
753
        offset = 0;
754
      }
755
  }
756
 
757
  /**
758
   * Invoked just before editing is to start. Will add the
759
   * editingComponent to the editingContainer.
760
   */
761
  protected void prepareForEditing()
762
  {
763
    if (editingComponent != null)
764
      editingContainer.add(editingComponent);
765
  }
766
 
767
  /**
768
   * Creates the container to manage placement of editingComponent.
769
   *
770
   * @return the container to manage the placement of the editingComponent.
771
   */
772
  protected Container createContainer()
773
  {
774
    return new DefaultTreeCellEditor.EditorContainer();
775
  }
776
 
777
  /**
778
   * This is invoked if a TreeCellEditor is not supplied in the constructor.
779
   * It returns a TextField editor.
780
   *
781
   * @return a new TextField editor
782
   */
783
  protected TreeCellEditor createTreeCellEditor()
784
  {
785
    Border border = UIManager.getBorder("Tree.editorBorder");
786
    JTextField tf = new DefaultTreeCellEditor.DefaultTextField(border);
787
    DefaultCellEditor editor = new DefaultCellEditor(tf);
788
    editor.setClickCountToStart(1);
789
    realEditor = editor;
790
    return editor;
791
  }
792
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.