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