persist interface config
[jSite2.git] / src / net / pterodactylus / jsite / gui / SwingInterface.java
1 /*
2  * jSite2 - SwingInterface.java -
3  * Copyright © 2008 David Roden
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
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 net.pterodactylus.jsite.gui;
21
22 import java.awt.event.ActionEvent;
23 import java.io.File;
24 import java.io.FileInputStream;
25 import java.io.FileOutputStream;
26 import java.io.IOException;
27 import java.util.ArrayList;
28 import java.util.List;
29 import java.util.Locale;
30 import java.util.Properties;
31
32 import javax.swing.JOptionPane;
33
34 import net.pterodactylus.jsite.core.Core;
35 import net.pterodactylus.jsite.core.CoreListener;
36 import net.pterodactylus.jsite.core.Node;
37 import net.pterodactylus.jsite.i18n.I18n;
38 import net.pterodactylus.jsite.i18n.gui.I18nAction;
39 import net.pterodactylus.util.io.Closer;
40
41 /**
42  * TODO
43  * 
44  * @author David ‘Bombe’ Roden <bombe@freenetproject.org>
45  * @version $Id$
46  */
47 public class SwingInterface implements CoreListener {
48
49         /** The application core. */
50         private final Core core;
51         
52         /** The configuration directory. */
53         private String configDirectory;
54
55         /** The main window. */
56         private MainWindow mainWindow;
57
58         /** The “configure” action. */
59         private I18nAction configureAction;
60
61         /** The “import config” action. */
62         private I18nAction importConfigAction;
63
64         /** The “quit” action. */
65         private I18nAction quitAction;
66
67         /** The “manage nodes” action. */
68         private I18nAction manageNodesAction;
69
70         /** The “connect to node” action. */
71         private I18nAction nodeConnectAction;
72
73         /** The “disconnect from node” action. */
74         private I18nAction nodeDisconnectAction;
75
76         /** The node manager dialog. */
77         private ManageNodesDialog manageNodesDialog;
78
79         /** All lanugage menu items. */
80         private List<I18nAction> languageActions = new ArrayList<I18nAction>();
81
82         /** The “about” action. */
83         private I18nAction helpAboutAction;
84
85         /** The “add project” action. */
86         private I18nAction addProjectAction;
87
88         /** The “about” dialog. */
89         private AboutDialog aboutDialog;
90
91         /** The configuration dialog. */
92         private ConfigurationDialog configurationDialog;
93
94         /** The list of all defined nodes. */
95         private List<Node> nodeList;
96
97         //
98         // CONFIGURATION
99         //
100
101         /** Whether to beautify the GUI. */
102         private boolean beautify;
103
104         /**
105          * Creates a new swing interface.
106          * 
107          * @param core
108          *            The core to operate on
109          */
110         public SwingInterface(Core core) {
111                 this.core = core;
112                 I18n.setLocale(Locale.ENGLISH); /* TODO - load config */
113                 loadConfig();
114                 if (beautify) {
115                         System.setProperty("swing.aatext", "true");
116                         System.setProperty("swing.plaf.metal.controlFont", "Tahoma");
117                         System.setProperty("swing.plaf.metal.userFont", "Tahoma");
118                 }
119                 initActions();
120                 initDialogs();
121         }
122
123         //
124         // ACCESSORS
125         //
126
127         /**
128          * Returns the core that is controlled by the Swing interface.
129          * 
130          * @return The core
131          */
132         Core getCore() {
133                 return core;
134         }
135
136         /**
137          * Returns the main window of the Swing interface.
138          * 
139          * @return The main window
140          */
141         MainWindow getMainWindow() {
142                 return mainWindow;
143         }
144
145         /**
146          * Returns the “configure” action.
147          * 
148          * @return The “configure” action
149          */
150         I18nAction getConfigureAction() {
151                 return configureAction;
152         }
153
154         /**
155          * Returns the “import config” action.
156          * 
157          * @return The “import config” action
158          */
159         I18nAction getImportConfigAction() {
160                 return importConfigAction;
161         }
162
163         /**
164          * Returns the “quit” action.
165          * 
166          * @return The “quit” action
167          */
168         I18nAction getQuitAction() {
169                 return quitAction;
170         }
171
172         /**
173          * Returns the “manage nodes” action.
174          * 
175          * @return The “manage nodes” action
176          */
177         I18nAction getManageNodesAction() {
178                 return manageNodesAction;
179         }
180
181         /**
182          * Returns the “connect to node” action.
183          * 
184          * @return The “connect to node” action
185          */
186         I18nAction getNodeConnectAction() {
187                 return nodeConnectAction;
188         }
189
190         /**
191          * Returns the “disconnect from node” action.
192          * 
193          * @return The “disconnect from node” action
194          */
195         I18nAction getNodeDisconnectAction() {
196                 return nodeDisconnectAction;
197         }
198
199         /**
200          * Returns all language actions.
201          * 
202          * @return All language actions
203          */
204         List<I18nAction> getLanguageActions() {
205                 return languageActions;
206         }
207
208         /**
209          * Returns the “about” action.
210          * 
211          * @return The “about” action
212          */
213         I18nAction getHelpAboutAction() {
214                 return helpAboutAction;
215         }
216
217         /**
218          * Returns the “add project” action.
219          * 
220          * @return The “add project” action
221          */
222         I18nAction getAddProjectAction() {
223                 return addProjectAction;
224         }
225
226         /**
227          * Sets the configuration directory.
228          * 
229          * @param configDirectory
230          *            The directory the configuration is stored in
231          */
232         public void setConfigDirectory(String configDirectory) {
233                 this.configDirectory = configDirectory;
234         }
235
236         //
237         // ACTIONS
238         //
239
240         //
241         // SERVICE METHODS
242         //
243
244         /**
245          * Starts the interface.
246          */
247         public void start() {
248                 mainWindow = new MainWindow(this);
249         }
250
251         //
252         // PRIVATE METHODS
253         //
254
255         /**
256          * Loads the configuration of the interface.
257          */
258         private void loadConfig() {
259                 /* initialize default stuff. */
260                 beautify = false;
261                 /* now read config. */
262                 File configFile = new File(configDirectory, "swing-interface.properties");
263                 if (!configFile.exists() || !configFile.canRead() || !configFile.isFile()) {
264                         System.err.println("could not find “" + configFile.getAbsolutePath() + "”!");
265                         return;
266                 }
267                 Properties configProperties = new Properties();
268                 FileInputStream configInputStream = null;
269                 try {
270                         configInputStream = new FileInputStream(configFile);
271                         configProperties.load(configInputStream);
272                 } catch (IOException ioe1) {
273                         System.err.println("could not load config, " + ioe1.getMessage());
274                 } finally {
275                         Closer.close(configInputStream);
276                 }
277                 if (configProperties.containsKey("beautify")) {
278                         beautify = Boolean.valueOf(configProperties.getProperty("beautify"));
279                 }
280         }
281
282         /**
283          * Saves the configuration.
284          */
285         private void saveConfig() {
286                 File configDirectory = new File(this.configDirectory);
287                 if (!configDirectory.exists()) {
288                         if (!configDirectory.mkdirs()) {
289                                 System.err.println("could not create “" + this.configDirectory + "”!");
290                                 return;
291                         }
292                 }
293                 if (!configDirectory.exists() || !configDirectory.isDirectory() || !configDirectory.canWrite()) {
294                         System.err.println("can not access “" + this.configDirectory + "”!");
295                         return;
296                 }
297                 File configFile = new File(configDirectory, "swing-interface.properties");
298                 Properties configProperties = new Properties();
299                 configProperties.setProperty("beautify", String.valueOf(beautify));
300                 FileOutputStream configOutputStream = null;
301                 try {
302                         configOutputStream = new FileOutputStream(configFile);
303                         configProperties.store(configOutputStream, "configuration of swing interface");
304                 } catch (IOException ioe1) {
305                         System.err.println("could not save config, " + ioe1.getMessage());
306                 } finally {
307                         Closer.close(configOutputStream);
308                 }
309         }
310
311         /**
312          * Initializes all actions.
313          */
314         private void initActions() {
315                 configureAction = new I18nAction("mainWindow.menu.jSite.configure") {
316
317                         /**
318                          * {@inheritDoc}
319                          */
320                         @SuppressWarnings("synthetic-access")
321                         public void actionPerformed(ActionEvent actionEvent) {
322                                 configure();
323                         }
324                 };
325                 importConfigAction = new I18nAction("mainWindow.menu.jSite.importConfig") {
326
327                         /**
328                          * {@inheritDoc}
329                          */
330                         @SuppressWarnings("synthetic-access")
331                         public void actionPerformed(ActionEvent actionEvent) {
332                                 importConfig();
333                         }
334                 };
335                 quitAction = new I18nAction("mainWindow.menu.jSite.quit") {
336
337                         /**
338                          * {@inheritDoc}
339                          */
340                         @SuppressWarnings("synthetic-access")
341                         public void actionPerformed(ActionEvent actionEvent) {
342                                 quit();
343                         }
344                 };
345                 manageNodesAction = new I18nAction("mainWindow.menu.node.item.manageNodes") {
346
347                         /**
348                          * {@inheritDoc}
349                          */
350                         @SuppressWarnings("synthetic-access")
351                         public void actionPerformed(ActionEvent actionEvent) {
352                                 manageNodes();
353                         }
354                 };
355                 nodeConnectAction = new I18nAction("mainWindow.menu.node.item.connect", false) {
356
357                         @SuppressWarnings("synthetic-access")
358                         public void actionPerformed(ActionEvent actionEvent) {
359                                 nodeConnect();
360                         }
361
362                 };
363                 nodeDisconnectAction = new I18nAction("mainWindow.menu.node.item.disconnect", false) {
364
365                         /**
366                          * {@inheritDoc}
367                          */
368                         @SuppressWarnings("synthetic-access")
369                         public void actionPerformed(ActionEvent e) {
370                                 nodeDisconnect();
371                         }
372                 };
373                 List<Locale> availableLanguages = I18n.findAvailableLanguages();
374                 for (final Locale locale: availableLanguages) {
375                         I18nAction languageAction = new I18nAction("general.language." + locale.getLanguage()) {
376
377                                 @SuppressWarnings("synthetic-access")
378                                 public void actionPerformed(ActionEvent e) {
379                                         changeLanguage(locale, this);
380                                 }
381
382                         };
383                         if (I18n.getLocale().getLanguage().equals(locale.getLanguage())) {
384                                 languageAction.setEnabled(false);
385                         }
386                         languageActions.add(languageAction);
387                 }
388                 helpAboutAction = new I18nAction("mainWindow.menu.help.item.about") {
389
390                         /**
391                          * {@inheritDoc}
392                          */
393                         @SuppressWarnings("synthetic-access")
394                         public void actionPerformed(ActionEvent actionEvent) {
395                                 helpAbout();
396                         }
397                 };
398                 addProjectAction = new I18nAction("mainWindow.button.addProject") {
399
400                         /**
401                          * {@inheritDoc}
402                          */
403                         @SuppressWarnings("synthetic-access")
404                         public void actionPerformed(ActionEvent actionEvent) {
405                                 addProject();
406                         }
407                 };
408         }
409
410         /**
411          * Initializes all child dialogs.
412          */
413         private void initDialogs() {
414                 manageNodesDialog = new ManageNodesDialog(this);
415                 aboutDialog = new AboutDialog(this);
416                 configurationDialog = new ConfigurationDialog(this);
417         }
418
419         //
420         // PRIVATE ACTIONS
421         //
422
423         /**
424          * Shows the configuration dialog.
425          */
426         private void configure() {
427                 configurationDialog.setBeautify(beautify);
428                 configurationDialog.setVisible(true);
429                 if (!configurationDialog.wasCancelled()) {
430                         beautify = configurationDialog.getBeautify();
431                         saveConfig();
432                 }
433         }
434
435         /**
436          * Imports old jSite configuration.
437          */
438         private void importConfig() {
439         }
440
441         /**
442          * Quits jSite.
443          */
444         private void quit() {
445                 saveConfig();
446                 System.exit(0);
447         }
448
449         /**
450          * Pops up the “manage nodes” dialog.
451          */
452         private void manageNodes() {
453                 manageNodesDialog.setNodeList(nodeList);
454                 manageNodesDialog.setVisible(true);
455                 nodeList = manageNodesDialog.getNodeList();
456         }
457
458         /**
459          * Connects to the node.
460          */
461         private void nodeConnect() {
462         }
463
464         /**
465          * Disconnects from the node.
466          */
467         private void nodeDisconnect() {
468         }
469
470         /**
471          * Changes the language of the interface. This method also disables the
472          * action for the newly set language and enables all others.
473          * 
474          * @param newLocale
475          *            The new language
476          * @param languageAction
477          *            The action that triggered the change
478          */
479         private void changeLanguage(Locale newLocale, I18nAction languageAction) {
480                 for (I18nAction i18nAction: languageActions) {
481                         i18nAction.setEnabled(i18nAction != languageAction);
482                 }
483                 I18n.setLocale(newLocale);
484         }
485
486         /**
487          * Shows the “about” dialog.
488          */
489         private void helpAbout() {
490                 aboutDialog.setVisible(true);
491         }
492
493         /**
494          * Adds a project.
495          */
496         private void addProject() {
497         }
498
499         //
500         // INTERFACE CoreListener
501         //
502
503         /**
504          * {@inheritDoc}
505          */
506         public void loadingProjectsFailed(String directory) {
507                 JOptionPane.showMessageDialog(mainWindow, I18n.get("mainWindow.error.projectLoadingFailed.message", directory), I18n.get("mainWindow.error.projectLoadingFailed.title"), JOptionPane.ERROR_MESSAGE);
508         }
509
510         /**
511          * {@inheritDoc}
512          */
513         public void coreLoaded() {
514                 this.nodeList = core.getNodes();
515                 manageNodesDialog.setNodeList(nodeList);
516                 mainWindow.setVisible(true);
517                 mainWindow.setStatusBarText("Core loaded.");
518         }
519
520         /**
521          * {@inheritDoc}
522          */
523         public void nodeConnected(Node node) {
524         }
525
526         /**
527          * {@inheritDoc}
528          */
529         public void nodeConnecting(Node node) {
530         }
531
532         /**
533          * {@inheritDoc}
534          */
535         public void nodeDisconnected(Node node) {
536         }
537
538 }