View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  /*
19   * @author Paul Smith <psmith@apache.org>
20   *
21  */
22  package org.apache.log4j.chainsaw;
23  
24  import java.awt.Component;
25  import java.awt.EventQueue;
26  import java.io.File;
27  import java.io.FileReader;
28  import java.io.FileWriter;
29  
30  import javax.swing.Icon;
31  import javax.swing.JComponent;
32  import javax.swing.JTabbedPane;
33  
34  import com.thoughtworks.xstream.XStream;
35  import com.thoughtworks.xstream.io.xml.DomDriver;
36  
37  import org.apache.log4j.chainsaw.prefs.LoadSettingsEvent;
38  import org.apache.log4j.chainsaw.prefs.SaveSettingsEvent;
39  import org.apache.log4j.chainsaw.prefs.SettingsListener;
40  import org.apache.log4j.chainsaw.prefs.SettingsManager;
41  
42  
43  /**
44   * The only reason this class is needed is because
45   * of a stupid 'issue' with the JTabbedPane.
46   *
47   * If the currently selected tab is the first tab,
48   * and we insert a new tab at the front, then as
49   * far as the JTabbedPane is concerned, NO STATE has
50   * changed, as the currently selected tab index is still
51   * the same (even though the TAB is different - go figure)
52   * and therefore no ChangeEvent is generated and sent
53   * to listeners.  Thanks very much Sun!
54   *
55   * For more information on the issue:
56   * http://developer.java.sun.com/developer/bugParade/bugs/4253819.html
57   * 
58   * @author Paul Smith <psmith@apache.org>
59   * @author Scott Deboy <sdeboy@apache.org>
60   *
61   */
62  
63  class ChainsawTabbedPane extends JTabbedPane implements SettingsListener {
64    public SavableTabSetting tabSetting;
65    public static final String WELCOME_TAB = "Welcome";
66    public static final String ZEROCONF = "Zeroconf";
67    /**
68     *
69     * Create the tabbed pane.  
70     *
71     */
72    public ChainsawTabbedPane() {
73      super();
74    }
75  
76    /**
77     * Returns true if this TabbedPane has an instance of the WelcomePanel
78     * in it
79     * @return true/false
80     */
81    boolean containsWelcomePanel() {
82      return indexOfTab("Welcome") > -1;
83    }
84  
85    /**
86     * Our custom implementation of inserting a new tab,
87     * this method ALWAYS inserts it at the front because
88     * we get an ArrayIndexOutOfBoundsException otherwise
89     * under some JDK implementations.
90     *
91     * This method also causes a fireStateChange() to be
92     * called so that listeners get notified of the event.
93     * See the class level comments for the reason why...
94     * @param name
95     * @param component
96     */
97    public void addANewTab(String name, JComponent component, Icon icon) {
98      super.insertTab(name, icon, component, null, getTabCount());
99  
100     super.fireStateChanged();
101     if (!"chainsaw-log".equals(name)) {
102         EventQueue.invokeLater(new Runnable() {
103             public void run() {
104                 setSelectedTab(getTabCount() - 1);
105             }
106         });
107     }
108   }
109 
110   public void setSelectedTab(int index) {
111     if (getTabCount() >= index) {
112       setSelectedIndex(index);
113     }
114 
115     getSelectedComponent().setVisible(true);
116     getSelectedComponent().validate();
117     super.fireStateChanged();
118   }
119 
120   public void addANewTab(
121     String name, JComponent component, Icon icon, String tooltip) {
122     super.insertTab(name, icon, component, tooltip, getTabCount());
123     super.fireStateChanged();
124   }
125 
126   public void remove(Component component) {
127     super.remove(component);
128     super.fireStateChanged();
129   }
130 
131   /**
132    * Saves the state of the currently active tabs to an XML file.
133    * Only considers the Welcome, Drag and Drop and chainsaw-log
134    * panels as they are the panel which are always running. Saves
135    * whether they are hidden or not....
136    */
137 
138   public void saveSettings(SaveSettingsEvent event){
139    File file = new File(SettingsManager.getInstance().getSettingsDirectory(), "tab-settings.xml");
140    XStream stream = new XStream(new DomDriver());
141    try {
142      FileWriter writer = new FileWriter(file);
143      int count = super.getTabCount();
144      String title;
145      SavableTabSetting setting = new SavableTabSetting();
146      for(int i = 0 ; i < count ; i++){
147        title = super.getTitleAt(i);
148        if(title.equals(WELCOME_TAB)){
149          setting.setWelcome(true);
150        } else if (title.equals("chainsaw-log")){
151          setting.setChainsawLog(true);
152        } else if (title.equals(ZEROCONF)){
153          setting.setZeroconf(true);
154        }
155      }
156 
157      stream.toXML(setting, writer);
158      writer.close();
159 
160    } catch (Exception e) {
161      file.delete();
162      e.printStackTrace();
163    }
164   }
165 
166   /**
167    * Loads the saved tab setting by reading the XML file.
168    * If the file doesn't exist, all three panels should be
169    * shown as the default setting....
170    */
171 
172   public void loadSettings(LoadSettingsEvent event){
173     File file = new File(SettingsManager.getInstance().getSettingsDirectory(), "tab-settings.xml");
174     XStream stream = new XStream(new DomDriver());
175     try {
176       if (file.exists()) {
177         FileReader reader = new FileReader(file);
178         tabSetting = (SavableTabSetting) stream.fromXML(reader);
179         reader.close();
180       } else {
181         tabSetting = new SavableTabSetting();
182         tabSetting.setWelcome(true);
183         tabSetting.setChainsawLog(true);
184         tabSetting.setZeroconf(true);
185       }
186     } catch (Exception e) {
187       e.printStackTrace();
188       file.delete();
189     }
190   }
191 }