View Javadoc

1   /*
2      Copyright 2002-2006 Martin van den Bemt
3   
4      Licensed under the Apache License, Version 2.0 (the "License");
5      you may not use this file except in compliance with the License.
6      You may obtain a copy of the License at
7   
8          http://www.apache.org/licenses/LICENSE-2.0
9   
10     Unless required by applicable law or agreed to in writing, software
11     distributed under the License is distributed on an "AS IS" BASIS,
12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13     See the License for the specific language governing permissions and
14     limitations under the License.
15  */
16  package org.xulux.guilayer.swing.widgets;
17  
18  import java.awt.Component;
19  import java.awt.Container;
20  import java.awt.event.HierarchyEvent;
21  import java.awt.event.HierarchyListener;
22  import java.util.Iterator;
23  
24  import javax.swing.Icon;
25  import javax.swing.JComponent;
26  import javax.swing.JTabbedPane;
27  import javax.swing.SwingUtilities;
28  
29  import org.xulux.api.gui.IWidget;
30  import org.xulux.api.gui.IXuluxListener;
31  import org.xulux.gui.ContainerWidget;
32  import org.xulux.guilayer.swing.util.SwingUtils;
33  
34  /**
35   * A panel that contains tabs..
36   *
37   *
38   * @todo Dig deeper into tabPanels..
39   * @author <a href="mailto:martin@mvdb.net">Martin van den Bemt</a>
40   * @version $Id: TabPanel.java,v 1.1 2005/12/18 12:58:18 mvdb Exp $
41   */
42  public class TabPanel extends ContainerWidget {
43  
44      /**
45       * The native tabbedPane
46       */
47      private JTabbedPane tabPanel;
48  
49      /**
50       * The tabCount
51       */
52      private int tabCount;
53      /**
54       * The tabid key that is used internally
55       * by nyx. Made it public so people can use
56       * it if they want to in their rules.
57       */
58      public static final String TABID = "nyx-tab-id";
59  
60      /**
61       * Which tab has initialfocus
62       */
63      private String initialFocus;
64      /**
65       * The repaintcomponent class
66       */
67      private RepaintComponent repaintComponent;
68      /**
69       * the repaintthreads
70       */
71      private Thread repaintThread;
72  
73      /**
74       * @param name the name of the tabPanel
75       */
76      public TabPanel(String name) {
77          super(name);
78      }
79  
80      /**
81       * @see org.xulux.gui.XuluxWidget#destroy()
82       */
83      public void destroy() {
84          super.destroy();
85          if (tabPanel == null) {
86              return;
87          }
88          if (repaintComponent != null) {
89              tabPanel.removeHierarchyListener(repaintComponent);
90              repaintComponent = null;
91          }
92          Container container = tabPanel.getParent();
93          tabPanel.setVisible(false);
94          tabPanel.removeAll();
95          if (container != null) {
96              container.remove(tabPanel);
97          }
98          tabPanel = null;
99      }
100 
101     /**
102      * @see org.xulux.nyx.gui.XuluxWidget#focus()
103      * @todo This is bad coding
104      */
105     public void focus() {
106         Object object = getPart().getSession().getValue("nyx.focusrequest");
107         if (object != null) {
108             IWidget w = (IWidget) object;
109             System.out.println("tabcount : " + w.getProperty(TABID));
110             w = findChildAndParentForFocus(w);
111             this.tabPanel.setSelectedComponent((JComponent) w.getNativeWidget());
112         }
113         this.tabPanel.requestFocus();
114     }
115 
116     /**
117      * Tries to find the widget of the parent of the widget passed
118      * and which is also a child of this widget
119      * @param w the widget
120      * @return null when it is not found.
121      */
122     private IWidget findChildAndParentForFocus(IWidget w) {
123         while (w != null) {
124             if (getChildWidgets().contains(w)) {
125                 return w;
126             } else {
127                 w = w.getParent();
128             }
129         }
130         return null;
131     }
132 
133     /**
134      * @see org.xulux.nyx.gui.XuluxWidget#getNativeWidget()
135      */
136     public Object getNativeWidget() {
137         initialize();
138         return this.tabPanel;
139     }
140 
141     /**
142      * @see org.xulux.nyx.gui.XuluxWidget#initialize()
143      */
144     public void initialize() {
145         if (initialized) {
146             return;
147         }
148         // we default to XYLayout for now..
149         initialized = true;
150         tabPanel = new JTabbedPane();
151 //        repaintComponent = new RepaintComponent();
152 //        tabPanel.addHierarchyListener(repaintComponent);
153 //        repaintThread = new Thread(repaintComponent);
154 //        repaintThread.start();
155 //        System.err.println("Still running");
156         initializeChildren();
157         refresh();
158         processInit();
159     }
160 
161     /**
162      * @see org.xulux.nyx.gui.XuluxWidget#refresh()
163      */
164     public void refresh() {
165         isRefreshing = true;
166         initialize();
167 //        tabPanel.setVisible(isVisible());
168         isRefreshing = false;
169     }
170 
171     /**
172      * Adds a widget to the tabPanel if the widget
173      * is a panel. For now no support for other
174      * widget types. Need to dig in deep into
175      * panels to see what can be usefull here
176      * @todo Tooltips don't seem to work in jdk1.3
177      * @see org.xulux.nyx.gui.ContainerWidget#addToParent(org.xulux.nyx.gui.XuluxWidget)
178      */
179     public void addToParent(IWidget widget) {
180 
181         if (widget instanceof Panel || widget instanceof Tab) {
182             System.out.println("Adding panel " + widget);
183             String tabTitle = widget.getProperty("title");
184             String tabTip = widget.getProperty("tip");
185             String tabIcon = widget.getProperty("icon");
186             Icon icon = null;
187             if (tabIcon != null) {
188                 try {
189                     icon = SwingUtils.getIcon(tabIcon, this);
190                 } catch (Exception e) {
191                     System.out.println("Icon resource " + tabIcon + " cannot be found");
192                 }
193             }
194             // always add the parent to the added widget..
195             widget.setParent(this);
196             tabPanel.addTab(tabTitle, icon, (Component) widget.getNativeWidget(), tabTip);
197             // just in case, but this doesn't seem to
198             // work either. Who know jdk1.4 does..
199             tabPanel.setToolTipTextAt(tabCount, tabTip);
200             // add the tabId to the property of the widget.
201             widget.setLazyProperty(TABID, String.valueOf(tabCount));
202             // Set the selectedIndex to the first tab that is not disabled.
203             if (initialFocus == null && widget.isEnabled() && widget.isVisible()) {
204                 initialFocus = String.valueOf(tabCount);
205                 tabPanel.setSelectedIndex(tabCount);
206             }
207             //widget.refresh();
208             tabCount++;
209         } else {
210             // do not yet allow any addition of other widgets.
211             // tabPanel.add((Component)widget.getNativeWidget(), widget);
212             System.out.println("Only panel widgets are allowed on top of a tabPanel, skipping widget " + widget);
213         }
214     }
215     /**
216      * @see org.xulux.nyx.gui.XuluxWidget#getGuiValue()
217      */
218     public Object getGuiValue() {
219         return null;
220     }
221 
222     /**
223      * @see org.xulux.nyx.gui.XuluxWidget#canContainValue()
224      */
225     public boolean canContainValue() {
226         return false;
227     }
228 
229     /**
230      * @see org.xulux.nyx.gui.XuluxWidget#isValueEmpty()
231      */
232     public boolean isValueEmpty() {
233         return true;
234     }
235 
236     /**
237      * @see org.xulux.nyx.gui.XuluxWidget#addXuluxListener(org.xulux.nyx.gui.XuluxListener)
238      */
239     public void addXuluxListener(IXuluxListener listener) {
240     }
241 
242     /**
243      * Fixes painting issues with the tabPanel.
244      * Eg buttons from another panel would shine through
245      * the first panel. After selecting the panel with the shine
246      * through buttons on it, the problems would never appear again.
247      * The selection of other tabs needs to be done in seperate runnables,
248      * since else the painting doesn't complete of other components.
249      * Probably calling the listeners with fireStatChanged will do,
250      * but couldn't figure that out yet..
251      *
252      * @todo : dig in this deeper, probably fixable some other way!
253      */
254     public class RepaintComponent implements Runnable, HierarchyListener {
255         /**
256          * The index
257          */
258         private int index = 0;
259         /**
260          * if the component is running
261          */
262         private boolean isRunning;
263 
264         /**
265          * the constructor
266          */
267         public RepaintComponent() {
268         }
269 
270         /**
271          * @see java.lang.Runnable#run()
272          */
273         public void run() {
274             if (getPart() == null) {
275                 return;
276             }
277             while (!tabPanel.isShowing()) {
278                 //System.err.println("isShowing ? "+tabPanel.isShowing());
279                 boolean sleep = true;
280                 if (sleep) {
281                     try {
282                         Thread.sleep(1000);
283                     } catch (InterruptedException ie) {
284                         // please repaint everything..
285                         sleep = false;
286                         break;
287                     }
288                 }
289             }
290             int selected = tabPanel.getSelectedIndex();
291             for (int i = 0; i < tabPanel.getTabCount(); i++) {
292                 selectIndex(i);
293             }
294             selectIndex(selected);
295             //tabPanel.setVisible(true);
296             tabPanel.validate();
297             tabPanel.repaint();
298         }
299 
300         /**
301          * Select the specified index
302          * @param index the index
303          */
304         public void selectIndex(final int index) {
305             try {
306                 SwingUtilities.invokeAndWait(new Runnable() {
307 
308                     /**
309                      * @see java.lang.Runnable#run()
310                      */
311                     public void run() {
312                         tabPanel.setSelectedIndex(index);
313                     }
314                 });
315             } catch (Exception e) {
316                 e.printStackTrace(System.out);
317             }
318         }
319 
320         /**
321          * @see java.awt.event.HierarchyListener#hierarchyChanged(java.awt.event.HierarchyEvent)
322          */
323         public void hierarchyChanged(HierarchyEvent e) {
324             if (isRunning) {
325                 return;
326             }
327             Iterator it = getPart().getWidgets().iterator();
328             while (it.hasNext()) {
329                 IWidget w = (IWidget) it.next();
330                 if (e.getChanged().equals(w.getNativeWidget())) {
331                     break;
332                 }
333             }
334 
335             if ((e.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED) != 0) {
336                 repaintThread.interrupt();
337             }
338         }
339 
340     }
341 }