2 * jSite2 - SwingInterface.java -
3 * Copyright © 2008 David Roden
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.
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.
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.
20 package net.pterodactylus.jsite.gui;
22 import java.awt.event.ActionEvent;
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;
32 import javax.swing.JOptionPane;
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.core.Project;
38 import net.pterodactylus.jsite.i18n.I18n;
39 import net.pterodactylus.jsite.i18n.gui.I18nAction;
40 import net.pterodactylus.util.io.Closer;
43 * The Swing user interface.
45 * @author David ‘Bombe’ Roden <bombe@freenetproject.org>
48 public class SwingInterface implements CoreListener {
50 /** The application core. */
51 private final Core core;
53 /** The configuration directory. */
54 private final String configDirectory;
56 /** The main window. */
57 private MainWindow mainWindow;
59 /** The “configure” action. */
60 private I18nAction configureAction;
62 /** The “import config” action. */
63 private I18nAction importConfigAction;
65 /** The “quit” action. */
66 private I18nAction quitAction;
68 /** The “manage nodes” action. */
69 private I18nAction manageNodesAction;
71 /** The “connect to node” action. */
72 private I18nAction nodeConnectAction;
74 /** The “disconnect from node” action. */
75 private I18nAction nodeDisconnectAction;
77 /** The node manager dialog. */
78 private ManageNodesDialog manageNodesDialog;
80 /** All lanugage menu items. */
81 private List<I18nAction> languageActions = new ArrayList<I18nAction>();
83 /** The “about” action. */
84 private I18nAction helpAboutAction;
86 /** The “add project” action. */
87 private I18nAction addProjectAction;
89 /** The “clone project” action. */
90 private I18nAction cloneProjectAction;
92 /** The “delete project” action. */
93 private I18nAction deleteProjectAction;
95 /** The “about” dialog. */
96 private AboutDialog aboutDialog;
98 /** The configuration dialog. */
99 private ConfigurationDialog configurationDialog;
101 /** The list of all defined nodes. */
102 private List<Node> nodeList;
108 /** The advanced mode. */
109 private boolean advancedMode;
111 /** Whether to antialias the GUI. */
112 private boolean antialias;
114 /** The control font. */
115 private String controlFont;
117 /** The user font. */
118 private String userFont;
121 * Creates a new swing interface.
124 * The core to operate on
125 * @param configDirectory
126 * The directory the configuration is stored in
128 public SwingInterface(Core core, String configDirectory) {
130 this.configDirectory = configDirectory;
131 I18n.setLocale(Locale.ENGLISH);
134 System.setProperty("swing.aatext", "true");
136 if (controlFont != null) {
137 System.setProperty("swing.plaf.metal.controlFont", controlFont);
139 if (userFont != null) {
140 System.setProperty("swing.plaf.metal.userFont", userFont);
151 * Returns the core that is controlled by the Swing interface.
160 * Returns the main window of the Swing interface.
162 * @return The main window
164 MainWindow getMainWindow() {
169 * Returns the “configure” action.
171 * @return The “configure” action
173 I18nAction getConfigureAction() {
174 return configureAction;
178 * Returns the “import config” action.
180 * @return The “import config” action
182 I18nAction getImportConfigAction() {
183 return importConfigAction;
187 * Returns the “quit” action.
189 * @return The “quit” action
191 I18nAction getQuitAction() {
196 * Returns the “manage nodes” action.
198 * @return The “manage nodes” action
200 I18nAction getManageNodesAction() {
201 return manageNodesAction;
205 * Returns the “connect to node” action.
207 * @return The “connect to node” action
209 I18nAction getNodeConnectAction() {
210 return nodeConnectAction;
214 * Returns the “disconnect from node” action.
216 * @return The “disconnect from node” action
218 I18nAction getNodeDisconnectAction() {
219 return nodeDisconnectAction;
223 * Returns all language actions.
225 * @return All language actions
227 List<I18nAction> getLanguageActions() {
228 return languageActions;
232 * Returns the “about” action.
234 * @return The “about” action
236 I18nAction getHelpAboutAction() {
237 return helpAboutAction;
241 * Returns the “add project” action.
243 * @return The “add project” action
245 I18nAction getAddProjectAction() {
246 return addProjectAction;
250 * Returns the “clone project” action.
252 * @return The “clone project” action
254 I18nAction getCloneProjectAction() {
255 return cloneProjectAction;
259 * Returns the “delete project” action.
261 * @return The “delete project” action
263 I18nAction getDeleteProjectAction() {
264 return deleteProjectAction;
276 * Starts the interface.
278 public void start() {
279 mainWindow = new MainWindow(this);
287 * Loads the configuration of the interface.
289 private void loadConfig() {
290 /* initialize default stuff. */
292 /* now read config. */
293 File configFile = new File(configDirectory, "swing-interface.properties");
294 if (!configFile.exists() || !configFile.canRead() || !configFile.isFile()) {
295 System.err.println("could not find “" + configFile.getAbsolutePath() + "”!");
298 Properties configProperties = new Properties();
299 FileInputStream configInputStream = null;
301 configInputStream = new FileInputStream(configFile);
302 configProperties.load(configInputStream);
303 } catch (IOException ioe1) {
304 System.err.println("could not load config, " + ioe1.getMessage());
306 Closer.close(configInputStream);
308 if (configProperties.containsKey("advancedMode")) {
309 advancedMode = Boolean.valueOf(configProperties.getProperty("advancedMode"));
311 if (configProperties.containsKey("antialias")) {
312 antialias = Boolean.valueOf(configProperties.getProperty("antialias"));
314 if (configProperties.containsKey("controlFont")) {
315 controlFont = configProperties.getProperty("controlFont");
317 if (configProperties.containsKey("userFont")) {
318 userFont = configProperties.getProperty("userFont");
320 if (configProperties.containsKey("language")) {
321 I18n.setLocale(new Locale(configProperties.getProperty("language")));
326 * Saves the configuration.
328 private void saveConfig() {
329 File configDirectory = new File(this.configDirectory);
330 if (!configDirectory.exists()) {
331 if (!configDirectory.mkdirs()) {
332 System.err.println("could not create “" + this.configDirectory + "”!");
336 if (!configDirectory.exists() || !configDirectory.isDirectory() || !configDirectory.canWrite()) {
337 System.err.println("can not access “" + this.configDirectory + "”!");
340 File configFile = new File(configDirectory, "swing-interface.properties");
341 Properties configProperties = new Properties();
342 configProperties.setProperty("advancedMode", String.valueOf(advancedMode));
343 configProperties.setProperty("antialias", String.valueOf(antialias));
344 if (controlFont != null) {
345 configProperties.setProperty("controlFont", controlFont);
347 if (userFont != null) {
348 configProperties.setProperty("userFont", userFont);
350 configProperties.setProperty("language", I18n.getLocale().getLanguage());
351 FileOutputStream configOutputStream = null;
353 configOutputStream = new FileOutputStream(configFile);
354 configProperties.store(configOutputStream, "configuration of swing interface");
355 } catch (IOException ioe1) {
356 System.err.println("could not save config, " + ioe1.getMessage());
358 Closer.close(configOutputStream);
363 * Initializes all actions.
365 private void initActions() {
366 configureAction = new I18nAction("mainWindow.menu.jSite.configure") {
371 @SuppressWarnings("synthetic-access")
372 public void actionPerformed(ActionEvent actionEvent) {
376 importConfigAction = new I18nAction("mainWindow.menu.jSite.importConfig") {
381 @SuppressWarnings("synthetic-access")
382 public void actionPerformed(ActionEvent actionEvent) {
386 quitAction = new I18nAction("mainWindow.menu.jSite.quit") {
391 @SuppressWarnings("synthetic-access")
392 public void actionPerformed(ActionEvent actionEvent) {
396 manageNodesAction = new I18nAction("mainWindow.menu.node.item.manageNodes") {
401 @SuppressWarnings("synthetic-access")
402 public void actionPerformed(ActionEvent actionEvent) {
406 nodeConnectAction = new I18nAction("mainWindow.menu.node.item.connect", false) {
408 @SuppressWarnings("synthetic-access")
409 public void actionPerformed(ActionEvent actionEvent) {
414 nodeDisconnectAction = new I18nAction("mainWindow.menu.node.item.disconnect", false) {
419 @SuppressWarnings("synthetic-access")
420 public void actionPerformed(ActionEvent e) {
424 List<Locale> availableLanguages = I18n.findAvailableLanguages();
425 for (final Locale locale: availableLanguages) {
426 I18nAction languageAction = new I18nAction("general.language." + locale.getLanguage()) {
428 @SuppressWarnings("synthetic-access")
429 public void actionPerformed(ActionEvent e) {
430 changeLanguage(locale, this);
434 if (I18n.getLocale().getLanguage().equals(locale.getLanguage())) {
435 languageAction.setEnabled(false);
437 languageActions.add(languageAction);
439 helpAboutAction = new I18nAction("mainWindow.menu.help.item.about") {
444 @SuppressWarnings("synthetic-access")
445 public void actionPerformed(ActionEvent actionEvent) {
449 addProjectAction = new I18nAction("mainWindow.button.addProject") {
454 @SuppressWarnings("synthetic-access")
455 public void actionPerformed(ActionEvent actionEvent) {
459 cloneProjectAction = new I18nAction("mainWindow.button.cloneProject") {
464 @SuppressWarnings("synthetic-access")
465 public void actionPerformed(ActionEvent actionEvent) {
469 deleteProjectAction = new I18nAction("mainWindow.button.deleteProject") {
474 @SuppressWarnings("synthetic-access")
475 public void actionPerformed(ActionEvent actionEvent) {
482 * Initializes all child dialogs.
484 private void initDialogs() {
485 manageNodesDialog = new ManageNodesDialog(this);
486 aboutDialog = new AboutDialog(this);
487 configurationDialog = new ConfigurationDialog(this);
495 * Shows the configuration dialog.
497 private void configure() {
498 configurationDialog.setAdvancedMode(advancedMode);
499 configurationDialog.setAntialias(antialias);
500 configurationDialog.setControlFont(controlFont);
501 configurationDialog.setUserFont(userFont);
502 configurationDialog.setVisible(true);
503 if (!configurationDialog.wasCancelled()) {
504 advancedMode = configurationDialog.isAdvancedMode();
505 if (!advancedMode && (nodeList.size() > 1)) {
506 JOptionPane.showMessageDialog(mainWindow, I18n.get("mainWindow.warning.multipleNodesNotAdvancedMode.message"), I18n.get("mainWindow.warning.multipleNodesNotAdvancedMode.title"), JOptionPane.WARNING_MESSAGE);
508 antialias = configurationDialog.isAntialias();
509 controlFont = configurationDialog.getControlFont();
510 userFont = configurationDialog.getUserFont();
516 * Imports old jSite configuration.
518 private void importConfig() {
525 private void quit() {
531 * Pops up the “manage nodes” dialog.
533 private void manageNodes() {
535 manageNodesDialog.setNodeList(nodeList);
536 manageNodesDialog.setVisible(true);
537 nodeList = manageNodesDialog.getNodeList();
539 if (nodeList.isEmpty()) {
540 Node newNode = new Node();
541 newNode.setName(I18n.get("general.defaultNode.name"));
542 newNode.setHostname("localhost");
543 newNode.setPort(9481);
544 nodeList.add(newNode);
546 Node firstNode = nodeList.get(0);
547 EditNodeDialog editNodeDialog = manageNodesDialog.getEditNodeDialog();
548 editNodeDialog.setNodeName(firstNode.getName());
549 editNodeDialog.setNodeHostname(firstNode.getHostname());
550 editNodeDialog.setNodePort(firstNode.getPort());
551 editNodeDialog.setVisible(true);
552 if (!editNodeDialog.wasCancelled()) {
553 firstNode.setName(editNodeDialog.getNodeName());
554 firstNode.setHostname(editNodeDialog.getNodeHostname());
555 firstNode.setPort(editNodeDialog.getNodePort());
556 /* TODO - give to core. */
562 * Connects to the node.
564 private void nodeConnect() {
569 * Disconnects from the node.
571 private void nodeDisconnect() {
576 * Changes the language of the interface. This method also disables the
577 * action for the newly set language and enables all others.
581 * @param languageAction
582 * The action that triggered the change
584 private void changeLanguage(Locale newLocale, I18nAction languageAction) {
585 for (I18nAction i18nAction: languageActions) {
586 i18nAction.setEnabled(i18nAction != languageAction);
588 I18n.setLocale(newLocale);
592 * Shows the “about” dialog.
594 private void helpAbout() {
595 aboutDialog.setVisible(true);
601 private void addProject() {
602 Project project = new Project();
603 project.setName("New Project");
604 project.setDescription("");
610 private void cloneProject() {
617 private void deleteProject() {
622 // INTERFACE CoreListener
629 public void loadingProjectsDone(String directory) {
630 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.projectLoadingDone"));
636 public void loadingProjectsFailed(String directory, Throwable throwable) {
637 JOptionPane.showMessageDialog(mainWindow, I18n.get("mainWindow.error.projectLoadingFailed.message", directory), I18n.get("mainWindow.error.projectLoadingFailed.title"), JOptionPane.ERROR_MESSAGE);
643 public void savingProjectsDone(String directory) {
644 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.projectSavingDone"));
650 public void savingProjectsFailed(String directory, Throwable throwabled) {
657 public void loadingNodesDone(String directory) {
658 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.loadingNodesDone"));
664 public void loadingNodesFailed(String directory, Throwable throwable) {
671 public void savingNodesDone(String directory) {
672 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.savingNodesDone"));
678 public void savingNodesFailed(String directory, Throwable throwable) {
685 public void coreLoaded() {
686 this.nodeList = core.getNodes();
687 manageNodesDialog.setNodeList(nodeList);
688 mainWindow.setVisible(true);
689 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.coreLoaded"));
695 public void coreStopped() {
696 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.coreStopped"));
702 public void nodeConnected(Node node) {
709 public void nodeConnecting(Node node) {
716 public void nodeDisconnected(Node node) {