View Javadoc

1   /*
2    *  XNap - A P2P framework and client.
3    *
4    *  See the file AUTHORS for copyright information.
5    *
6    *  This program 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.
9    *
10   *  This program is distributed in the hope that it will be useful,
11   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   *  GNU General Public License for more details.
14   *
15   *  You should have received a copy of the GNU General Public License
16   *  along with this program; if not, write to the Free Software
17   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18   */
19  
20  package org.xnap.gui;
21  
22  import java.awt.BorderLayout;
23  import java.awt.event.ActionEvent;
24  import java.awt.event.ActionListener;
25  
26  import javax.swing.Box;
27  import javax.swing.BoxLayout;
28  import javax.swing.JCheckBoxMenuItem;
29  import javax.swing.JComponent;
30  import javax.swing.JMenu;
31  import javax.swing.JPanel;
32  import javax.swing.SwingUtilities;
33  
34  import org.xnap.gui.event.PopupListener;
35  import org.xnap.gui.util.GUIHelper;
36  import org.xnap.util.Preferences;
37  import org.xnap.util.SystemHelper;
38  
39  /***
40   * The StatusBar is used to display status messages at the bottom of {@link
41   * xnap.gui.XNapFrame XNapFrame}. Plugins and other units can add their own
42   * status components via <code>addComponent()</code>.
43   * 
44   * StatusBar follows the singleton pattern. You cannot create multiple
45   * instances. Use <code>getInstance()</code> to get a reference to the status
46   * bar.
47   *
48   * @see xnap.gui.StatusPanel
49   */
50  public class StatusBar extends JPanel
51  {
52      //--- Constant(s) ---
53      
54      //--- Data field(s) ---
55  
56      private static StatusBar instance = null;
57  
58      private StatusPanel spStatus;
59      private JPanel container;
60  	private JMenu visibleComponentsMenu;
61  	private ActionListener visibleListener = new VisibleListener();
62      private PopupListener popupListener;
63  
64      //--- Constructor(s) ---
65  
66      private StatusBar()
67      {
68  		super(new BorderLayout());
69  
70  		spStatus = new StatusPanel(10000);
71  		add(spStatus, BorderLayout.CENTER);
72  
73  		container = new JPanel();
74  		container.setLayout(new BoxLayout(container, BoxLayout.X_AXIS));
75  		add(container, BorderLayout.EAST);
76  
77  		setBorder(GUIHelper.createRaisedBorder());
78  
79  		visibleComponentsMenu = new JMenu();
80  		popupListener = new PopupListener(visibleComponentsMenu);
81  		this.addMouseListener(popupListener);
82  	
83  		/* the aqua look and feel adds a small resize control in the lower
84  		   right corner which overlaps the status panel therefore we add a
85  		   little offset.  */
86  		if (SystemHelper.isMacOSX) {
87  			container.add(Box.createHorizontalStrut(15));
88  		}
89      }
90  
91      //--- Method(s) ---
92  
93      /***
94       * Kills the instance of StatusBar.
95       */
96      public static void disposeInstance()
97      {
98  		instance = null;
99      }
100 
101     /***
102      * Returns the instance of StatusBar.
103      */
104     public static StatusBar getInstance()
105     {
106 		if (instance == null) {
107 			instance = new StatusBar();
108 		}
109 		return instance;
110     }
111 
112     /***
113      * Adds a panel to the status bar. Panels are added from west to east.
114      *
115      * @param c component to be added.
116      */
117     public void addComponent(JComponent c)
118     {
119 		container.add(c, 0);
120 		updateUI();
121 		addToMenu(c, 0);
122     }
123 
124     /***
125      * Adds a panel to the status bar on the east. 
126      *
127      * @param c component to be added.
128      */
129     public void appendComponent(JComponent c)
130     {
131 		container.add(c);
132 		updateUI();
133 		addToMenu(c, visibleComponentsMenu.getItemCount());
134     }
135 
136 	private void addToMenu(JComponent c, int pos) 
137 	{
138 		if (c.getName() != null) {
139 			Preferences.getInstance().setDefault
140 					("show" + c.getName() + "StatusPanel", "true");
141 			boolean visible = Preferences.getInstance().getBoolean
142 				("show" + c.getName() + "StatusPanel");
143 
144 			JCheckBoxMenuItem item 
145 				= new JCheckBoxMenuItem(c.getName(), visible);
146 			item.setActionCommand(c.getName());
147 			item.addActionListener(visibleListener);
148 			visibleComponentsMenu.add(item, pos);
149 
150 			c.setVisible(visible);
151 			c.addMouseListener(popupListener);
152 		}
153 	}
154     
155     /***
156      * Removes a panel from the status bar.
157      *
158      * @param c component to be removed.
159      */
160     public void removeComponent(JComponent c)
161     {
162 		container.remove(c);
163 		updateUI();
164 
165 		String name = c.getName();
166 		if (name != null) {
167 			for (int i = visibleComponentsMenu.getItemCount() - 1; i >= 0; i--) {
168 				if (name.equals(visibleComponentsMenu.getItem(i).getText())) {
169 					visibleComponentsMenu.remove(i);
170 					break;
171 				}
172 			}
173 		}
174     }
175 
176 	public static void clear()
177 	{
178 		getInstance().spStatus.clear();
179 	}
180 
181     /***
182      * Displays text on the left side of the status bar.
183      *
184      * @param text text to be displayed.
185      */
186     public static void setText(String text)
187     {
188 		// never hide the status bar
189 		if (text == null || text.length() == 0) {
190 			clear();
191 		}
192 		else {
193 			getInstance().spStatus.setText(text);
194 		}
195     }
196 
197     /***
198      * This method is thread safe.
199      *
200      * @see #setText(String)
201      */
202     public static void setTextLater(final String text)
203     {
204 		Runnable runner = new Runnable()
205 			{
206 				public void run() 
207 				{
208 					setText(text);
209 				}
210 			};
211 		SwingUtilities.invokeLater(runner);
212     }
213 
214 	private JComponent getComponentByName(String name) 
215 	{
216 		if (name != null) {
217 			for (int i = container.getComponentCount() - 1; i >= 0; i--) {
218 				if (name.equals(container.getComponent(i).getName())) {
219 					return (JComponent)container.getComponent(i);
220 				}
221 			}
222 		}
223 		return null;
224 	}
225 
226 	private class VisibleListener implements ActionListener
227 	{
228 		public void actionPerformed(ActionEvent event) 
229 		{
230 			JComponent c = getComponentByName(event.getActionCommand());
231 			if (c != null) {
232 				boolean visible 
233 					= ((JCheckBoxMenuItem)event.getSource()).isSelected();
234 				c.setVisible(visible);
235 				Preferences.getInstance().set
236 					("show" + c.getName() + "StatusPanel", visible);
237 			}
238 		}
239 	}
240 
241 }