View Javadoc

1   /*
2    * Copyright (c) 1998-2004 The Jgroup Team.
3    *
4    * This program is free software; you can redistribute it and/or modify
5    * it under the terms of the GNU Lesser General Public License version 2 as
6    * published by the Free Software Foundation.
7    *
8    * This program is distributed in the hope that it will be useful,
9    * but WITHOUT ANY WARRANTY; without even the implied warranty of
10   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11   * GNU Lesser General Public License for more details.
12   *
13   * You should have received a copy of the GNU Lesser General Public License
14   * along with this program; if not, write to the Free Software
15   * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16   *
17   */
18  
19  package jgroup.experiment.gui.views.helpers;
20  
21  import java.util.Iterator;
22  import java.util.LinkedList;
23  
24  import javax.swing.JComponent;
25  import javax.swing.JLabel;
26  import javax.swing.JPanel;
27  import javax.swing.JTabbedPane;
28  import javax.swing.JTextField;
29  import javax.swing.text.JTextComponent;
30  import javax.swing.tree.DefaultMutableTreeNode;
31  import javax.swing.tree.TreeNode;
32  
33  /**
34   * Utility class providing static methods for marking 
35   * JLabels and tabs when their connected editable
36   * components change.
37   * The component must add a ChangeableActionListener
38   * as action listener, and pass the label and the panel
39   * to be marked in its constructor.
40   * ChangeTracker assumes the parent of the JPanel to be
41   * a JTabbedPane.
42   * The class also provides similar static methods for
43   * marking <code>DefaultMutableTreeNode</code>s in a tree.
44   * No listener is necessary for nodes.
45   * 
46   * @author Bjarte Svaeren
47   */
48  public class ChangeTracker
49  {
50    ////////////////////////////////////////////////////////////////////////////////////////////
51    // Constants
52    ////////////////////////////////////////////////////////////////////////////////////////////
53    
54    private static final int COMPONENT_CHANGES = 0;
55    private static final int NODE_CHANGES      = 1;
56    
57    
58    ////////////////////////////////////////////////////////////////////////////////////////////
59    // Static fields
60    ////////////////////////////////////////////////////////////////////////////////////////////
61  
62    // List containing components with changes (for use with labels and tabs)
63    private static LinkedList componentList = new LinkedList();
64    private static boolean componentChanges = false;
65  
66    // List containing nodes with changes (for use with trees)
67    private static LinkedList nodeList      = new LinkedList();
68    private static boolean nodeChanges      = false;
69    
70  
71    ////////////////////////////////////////////////////////////////////////////////////////////
72    // Public methods
73    ////////////////////////////////////////////////////////////////////////////////////////////
74    
75    public static void performedChange(JComponent comp)
76    {
77      if( !componentList.contains(comp) ) {
78        if( !(comp instanceof JLabel) )
79          throw new IllegalArgumentException("Argument must be a JLabel");
80          
81        componentList.add(comp);
82        markChange(comp);
83        componentChanges = true;
84      }
85    }
86    
87  
88    public static void performedChange(JComponent comp1, JComponent comp2)
89    {
90      if( !(comp1 instanceof JLabel) )
91        throw new IllegalArgumentException("First argument must be a JLabel");
92      if( !(comp2 instanceof JPanel) )
93        throw new IllegalArgumentException("Second argument must be a JPanel");
94  
95      if( !(componentList.contains(comp1)) ) {
96        componentList.add(comp1);
97        markChange(comp1);
98      }
99      if( !(componentList.contains(comp2)) ) { 
100       componentList.add(comp2); 
101       markChange(comp2);   
102     }
103 
104     componentChanges = true;
105   }
106   
107   
108   public static void performedChange(TreeNode node)
109   {
110     if( !nodeList.contains(node) ) { 
111       nodeList.add(node);
112       markChange(node);
113       nodeChanges = true;
114     }
115   }
116   
117   
118   public static void clearChanges()
119   {
120     clearChanges(COMPONENT_CHANGES);
121     clearChanges(NODE_CHANGES);
122   }
123   
124   
125   public static void clearChanges(int changeType)
126   {
127     if(changeType == COMPONENT_CHANGES) {
128       for (Iterator iter = componentList.iterator(); iter.hasNext();) {
129         JComponent component = (JComponent) iter.next();
130        
131         if(component instanceof JLabel) {
132           JLabel label = (JLabel) component;
133           String labelString = label.getText();
134           label.setText(labelString.substring(0, labelString.length() - 1));
135         } else if(component instanceof JPanel) {
136           JPanel panel    = (JPanel) component;
137           JTabbedPane tab = (JTabbedPane) panel.getParent();
138           int index = tab.indexOfComponent(panel);
139           String tabString = tab.getTitleAt(index);
140           tab.setTitleAt(index, tabString.substring(0, tabString.length() - 1));
141         } 
142       }    
143   
144       componentList.clear();
145       componentChanges = false;    
146     } else if(changeType == NODE_CHANGES) {
147       nodeList.clear();
148       nodeChanges = false;
149     }
150   }
151   
152   
153   public static void clearComponent(JComponent component)
154   {
155     componentList.remove(component);
156   }
157   
158   
159   public static void clearNode(TreeNode node)
160   {
161     nodeList.remove(node);
162   }
163   
164 
165   /**
166    * Returns true if there are changes in any components.
167    * Important: 
168    * @return
169    */  
170   public static boolean hasComponentChanges()
171   {
172     return componentChanges;
173   }
174   
175   
176   /**
177    * Returns true if there are changes in any nodes.
178    * @return
179    */
180   public static boolean hasNodeChanges()
181   {
182     return nodeChanges;
183   }
184   
185   
186   /**
187    * Returns true if this component has changed.
188    * @param component
189    * @return
190    */
191   public static boolean hasChanges(JComponent component)
192   {
193     return componentList.contains(component);
194   }
195   
196   
197   /**
198    * Returns true if this node has changed.
199    * @param node
200    * @return
201    */
202   public static boolean hasChanges(TreeNode node)
203   {
204     return nodeList.contains(node);
205   }
206   
207 
208   /**
209    * Returns a list of all changed components.
210    * @return
211    */
212   public static LinkedList getChangedComponents()
213   {
214     return new LinkedList(componentList);
215   }
216   
217   
218   /**
219    * Returns a list of all changed nodes.
220    * @return
221    */
222   public static LinkedList getChangedNodes()
223   {
224     return new LinkedList(nodeList);
225   }
226   
227   
228   /**
229    * Add a change listener for the component.
230    * @param component
231    * @param label
232    * @param panel
233    */
234   public static void addListener(JTextComponent component, JLabel label, JPanel panel)
235   {
236     ChangeableActionListener listener = new ChangeableActionListener(label, panel);
237     component.addFocusListener(listener);
238 
239     // Only add an ActionListener if the component is a JTextField
240     // Not applicable for f.ex. JTextArea
241     if(component instanceof JTextField)
242       ((JTextField) component).addActionListener(listener);
243   }
244   
245 
246   ////////////////////////////////////////////////////////////////////////////////////////////
247   // Private methods
248   ////////////////////////////////////////////////////////////////////////////////////////////
249 
250   private static void markChange(JComponent component)
251   {
252     if(component instanceof JLabel) {
253       JLabel label = (JLabel) component;
254       label.setText(label.getText() + '*');
255     } else if(component instanceof JPanel) {
256       JPanel panel    = (JPanel) component;
257       JTabbedPane tab = (JTabbedPane) panel.getParent();
258       int index = tab.indexOfComponent(panel);
259       tab.setTitleAt(index, tab.getTitleAt(index) + '*');
260     } 
261   }
262   
263   private static void markChange(TreeNode changedNode)
264   {
265     DefaultMutableTreeNode node = (DefaultMutableTreeNode) changedNode;
266     
267     // Mark the node and its parents with *
268     String nodeText = ((String) node.getUserObject()) + '*';
269     node.setUserObject(nodeText);
270     
271     for (int i = 0; i < node.getLevel(); i++) {      
272       performedChange(node.getParent());
273     }
274   }
275 }