1   /**
2    * Distribution License:
3    * BibleDesktop is free software; you can redistribute it and/or modify it under
4    * the terms of the GNU General Public License, version 2 as published by
5    * the Free Software Foundation. This program is distributed in the hope
6    * that it will be useful, but WITHOUT ANY WARRANTY; without even the
7    * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
8    * See the GNU General Public License for more details.
9    *
10   * The License is available on the internet at:
11   *       http://www.gnu.org/copyleft/gpl.html
12   * or by writing to:
13   *      Free Software Foundation, Inc.
14   *      59 Temple Place - Suite 330
15   *      Boston, MA 02111-1307, USA
16   *
17   * Copyright: 2005
18   *     The copyright to this program is held by it's authors.
19   *
20   * ID: $Id: SitesPane.java 2105 2011-03-07 21:13:31Z dmsmith $
21   */
22  package org.crosswire.bibledesktop.book.install;
23  
24  import java.awt.BorderLayout;
25  import java.awt.Component;
26  import java.awt.FlowLayout;
27  import java.awt.Frame;
28  import java.awt.event.WindowAdapter;
29  import java.awt.event.WindowEvent;
30  import java.io.IOException;
31  import java.io.ObjectInputStream;
32  import java.util.Map;
33  
34  import javax.swing.BorderFactory;
35  import javax.swing.JButton;
36  import javax.swing.JDialog;
37  import javax.swing.JOptionPane;
38  import javax.swing.JPanel;
39  import javax.swing.JTabbedPane;
40  
41  import org.crosswire.bibledesktop.BDMsg;
42  import org.crosswire.common.progress.swing.JobsProgressBar;
43  import org.crosswire.common.swing.ActionFactory;
44  import org.crosswire.common.swing.GuiUtil;
45  import org.crosswire.common.swing.desktop.LayoutPersistence;
46  import org.crosswire.jsword.book.install.InstallManager;
47  import org.crosswire.jsword.book.install.Installer;
48  import org.crosswire.jsword.book.install.InstallerEvent;
49  import org.crosswire.jsword.book.install.InstallerListener;
50  
51  /**
52   * A SitesPane manages library sites.
53   * <p>
54   * so start one of these call:
55   * 
56   * <pre>
57   * sitesPane = new SitesPane();
58   * sitesPane.showInDialog(parent);
59   * </pre>
60   * 
61   * @see gnu.gpl.License for license details.<br>
62   *      The copyright to this program is held by it's authors.
63   * @author Joe Walker [joe at eireneh dot com]
64   */
65  public class SitesPane extends JPanel {
66      /**
67       * Simple ctor
68       */
69      public SitesPane() {
70          init();
71  
72          imanager = new InstallManager();
73          installers = imanager.getInstallers();
74  
75          addAllInstallers();
76  
77          imanager.addInstallerListener(new SiteInstallerListener());
78          GuiUtil.applyDefaultOrientation(this);
79      }
80  
81      /**
82       * Build the GUI components
83       */
84      private void init() {
85          actions = new ActionFactory(this);
86  
87          tabMain = new JTabbedPane();
88          this.setLayout(new BorderLayout());
89          this.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
90          this.add(tabMain, BorderLayout.CENTER);
91          this.add(new JobsProgressBar(true), BorderLayout.SOUTH);
92      }
93  
94      /**
95       * Re-create the list of installers
96       */
97      protected final void addAllInstallers() {
98          // Now add panels for book installation sites
99          for (String name : installers.keySet()) {
100             Installer installer = installers.get(name);
101 
102             SitePane site = new SitePane(installer);
103             tabMain.add(name, site);
104         }
105 
106         // TRANSLATOR: Label for the tab showing the installed books.
107         tabMain.add(BDMsg.gettext("Installed Books"), new SitePane());
108     }
109 
110     /**
111      * Remove all the non-local installers
112      */
113     protected void removeAllInstallers() {
114         tabMain.removeAll();
115     }
116 
117     /**
118      * Add a site to the list of install sources.
119      */
120     public void doManageSites() {
121         EditSitePane edit = new EditSitePane(imanager);
122         edit.showInDialog(this);
123     }
124 
125     /**
126      * We are done, close the window
127      */
128     public void doSitesClose() {
129         if (dlgMain != null) {
130             LayoutPersistence.instance().saveLayout(dlgMain);
131             dlgMain.setVisible(false);
132         }
133     }
134 
135     /**
136      * Open this Panel in it's own dialog box.
137      */
138     public void showInDialog(Component parent) {
139         Frame root = JOptionPane.getFrameForComponent(parent);
140         dlgMain = new JDialog(root);
141         dlgMain.getContentPane().setLayout(new BorderLayout());
142         dlgMain.getContentPane().add(this, BorderLayout.CENTER);
143         dlgMain.getContentPane().add(createButtons(), BorderLayout.SOUTH);
144         // TRANSLATOR: Title to the window that allows the management of books. 
145         dlgMain.setTitle(BDMsg.gettext("Available Books"));
146         dlgMain.setResizable(true);
147         // dlgMain.setModal(true);
148         // Set the name for Persistent Layout
149         dlgMain.setName("Sites");
150         dlgMain.addWindowListener(new WindowAdapter() {
151             /* (non-Javadoc)
152              * @see java.awt.event.WindowListener#windowClosed(java.awt.event.WindowEvent)
153              */
154             @Override
155             public void windowClosed(WindowEvent ev) {
156                 doSitesClose();
157             }
158         });
159         dlgMain.setLocationRelativeTo(parent);
160 
161         // Restore window size, position, and layout if previously opened,
162         // otherwise use defaults.
163         LayoutPersistence layoutPersistence = LayoutPersistence.instance();
164         if (layoutPersistence.isLayoutPersisted(dlgMain)) {
165             layoutPersistence.restoreLayout(dlgMain);
166         } else {
167             dlgMain.setSize(750, 500);
168             GuiUtil.centerOnScreen(dlgMain);
169         }
170 
171         dlgMain.setVisible(true);
172         dlgMain.toFront();
173         GuiUtil.applyDefaultOrientation(dlgMain);
174     }
175 
176     /**
177      *
178      */
179     private Component createButtons() {
180         if (pnlButtons == null) {
181             // TRANSLATOR: This is the text of an "OK" button that dismisses the dialog
182             JButton btnOK = new JButton(actions.addAction("SitesClose", BDMsg.gettext("OK")));
183 
184             // TRANSLATOR: This is the text of an "Edit Sites ..." button brings up a download site editor
185             JButton btnAdd = new JButton(actions.addAction("ManageSites", BDMsg.gettext("Edit Sites ...")));
186 
187             pnlButtons = new JPanel();
188             pnlButtons.setLayout(new FlowLayout(FlowLayout.TRAILING));
189             pnlButtons.add(btnAdd, null);
190             pnlButtons.add(btnOK);
191         }
192         return pnlButtons;
193 
194     }
195 
196     /**
197      * Serialization support.
198      * 
199      * @param is
200      * @throws IOException
201      * @throws ClassNotFoundException
202      */
203     private void readObject(ObjectInputStream is) throws IOException, ClassNotFoundException {
204         actions = new ActionFactory(this);
205         imanager = new InstallManager();
206         installers = imanager.getInstallers();
207 
208         is.defaultReadObject();
209 
210         addAllInstallers();
211 
212         imanager.addInstallerListener(new SiteInstallerListener());
213     }
214 
215     /**
216      * Local listener for install events.
217      */
218     class SiteInstallerListener implements InstallerListener {
219 
220         /* (non-Javadoc)
221          * @see org.crosswire.jsword.book.install.InstallerListener#installerAdded(org.crosswire.jsword.book.install.InstallerEvent)
222          */
223         public void installerAdded(InstallerEvent ev) {
224             Installer installer = ev.getInstaller();
225             String name = imanager.getInstallerNameForInstaller(installer);
226 
227             SitePane site = new SitePane(installer);
228             tabMain.add(name, site);
229         }
230 
231         /* (non-Javadoc)
232          * @see org.crosswire.jsword.book.install.InstallerListener#installerRemoved(org.crosswire.jsword.book.install.InstallerEvent)
233          */
234         public void installerRemoved(InstallerEvent ev) {
235             // This gets tricky because if you add a site with a new name
236             // but the same details as an old one, then the old name goes
237             // so we can't get the old name to remove it's tab (and anyway
238             // we would have to do a search through all the tabs to find it
239             // by name)
240             // So we just nuke all the tabs and re-create them
241             removeAllInstallers();
242             addAllInstallers();
243         }
244     }
245 
246     /**
247      * The known installers fetched from InstallManager
248      */
249     private transient Map<String, Installer> installers;
250 
251     /**
252      * The current installer
253      */
254     protected transient InstallManager imanager;
255 
256     private transient ActionFactory actions;
257 
258     /*
259      * GUI Components
260      */
261     private JDialog dlgMain;
262     private JPanel pnlButtons;
263     protected JTabbedPane tabMain;
264 
265     /**
266      * Serialization ID
267      */
268     private static final long serialVersionUID = 3258126947069605936L;
269 }
270