001 /* This file is part of the project "Hilbert II" - http://www.qedeq.org
002 *
003 * Copyright 2000-2013, Michael Meyling <mime@qedeq.org>.
004 *
005 * "Hilbert II" is free software; you can redistribute
006 * it and/or modify it under the terms of the GNU General Public
007 * License as published by the Free Software Foundation; either
008 * version 2 of the License, or (at your option) any later version.
009 *
010 * This program is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
013 * GNU General Public License for more details.
014 */
015
016 package org.qedeq.gui.se.main;
017
018 import java.awt.BorderLayout;
019 import java.awt.Dimension;
020 import java.awt.event.WindowAdapter;
021 import java.awt.event.WindowEvent;
022 import java.io.File;
023 import java.io.FileOutputStream;
024 import java.io.IOException;
025 import java.io.PrintStream;
026 import java.net.URL;
027
028 import javax.swing.JFrame;
029 import javax.swing.JMenuBar;
030 import javax.swing.JOptionPane;
031 import javax.swing.JPanel;
032 import javax.swing.SwingUtilities;
033
034 import org.apache.log4j.PropertyConfigurator;
035 import org.apache.log4j.xml.DOMConfigurator;
036 import org.qedeq.base.io.IoUtility;
037 import org.qedeq.base.io.UrlUtility;
038 import org.qedeq.base.trace.Trace;
039 import org.qedeq.gui.se.control.QedeqController;
040 import org.qedeq.gui.se.pane.QedeqGuiConfig;
041 import org.qedeq.gui.se.util.GuiHelper;
042 import org.qedeq.kernel.bo.KernelContext;
043 import org.qedeq.kernel.bo.log.LogListenerImpl;
044 import org.qedeq.kernel.bo.log.ModuleEventListenerLog;
045 import org.qedeq.kernel.bo.log.ModuleEventLog;
046 import org.qedeq.kernel.bo.log.QedeqLog;
047 import org.qedeq.kernel.bo.log.TraceListener;
048 import org.qedeq.kernel.bo.service.DefaultInternalKernelServices;
049 import org.qedeq.kernel.xml.dao.XmlQedeqFileDao;
050
051 import com.jgoodies.looks.Options;
052
053 /**
054 * This is the main frame of the GUI frontend for a standalone program
055 * version of <b>Hilbert II</b>.
056 *
057 * @author Michael Meyling
058 */
059 public class QedeqMainFrame extends JFrame {
060
061 /** Initial frame resolution. */
062 // protected static final Dimension PREFERRED_SIZE = (LookUtils.IS_LOW_RESOLUTION
063 // ? new Dimension(650, 510) : new Dimension(740, 660));
064 protected static final Dimension PREFERRED_SIZE = (GuiHelper.IS_LOW_RESOLUTION
065 ? new Dimension(650, 510) : new Dimension(900, 660));
066
067 /**
068 * Constructor, configures the UI, and builds the content. Also some indirectly some GUI
069 * loggers are added.
070 *
071 * @param settings GUI options.
072 * @throws IOException Initialization failed for IO reasons.
073 */
074 public QedeqMainFrame(final GuiOptions settings) throws IOException {
075 GuiHelper.configureUI(settings);
076
077 checkDirectoryExistenceAndOptionallyCreate(QedeqGuiConfig.getInstance());
078
079 // add various loggers
080 // QedeqLog.getInstance().addLog(new LogListenerImpl()); // System.out
081 QedeqLog.getInstance().addLog(new TraceListener()); // trace file
082 QedeqLog.getInstance() // log file
083 .addLog(new LogListenerImpl(new PrintStream(
084 new FileOutputStream(QedeqGuiConfig.getInstance().getLogFile(), true), true)));
085 ModuleEventLog.getInstance().addLog(new ModuleEventListenerLog()); // all loggers
086
087 // initialize the kernel, this may create already some logging events
088 KernelContext.getInstance().init(
089 QedeqGuiConfig.getInstance(),
090 new DefaultInternalKernelServices(QedeqGuiConfig.getInstance(),
091 KernelContext.getInstance(), new XmlQedeqFileDao()));
092
093 // create new controller for all possible actions
094 final QedeqController controller = new QedeqController(this);
095
096 // assemble main GUI window
097 final JPanel panel = new JPanel(new BorderLayout());
098 panel.add(new QedeqMainPane(controller), BorderLayout.CENTER);
099 setContentPane(panel);
100 setTitle(" " + KernelContext.getInstance().getDescriptiveKernelVersion());
101 final JMenuBar menuBar = new QedeqMenuBar(controller, settings);
102 setJMenuBar(menuBar);
103 setIconImage(GuiHelper.readImageIcon("qedeq/16x16/qedeq.png").getImage());
104 addWindowListener(new WindowAdapter() {
105 public void windowClosing(final WindowEvent e) {
106 controller.getExitAction().actionPerformed(null);
107 }
108 });
109
110 }
111
112 private void checkDirectoryExistenceAndOptionallyCreate(final QedeqGuiConfig config)
113 throws IOException {
114 // application log file directory
115 {
116 final File file = config.getLogFile();
117 final File dir = file.getParentFile();
118 if (!dir.exists() && !dir.mkdirs()) {
119 throw new IOException("can't create directory: " + dir.getAbsolutePath());
120 }
121 }
122 }
123
124 /**
125 * Make local copy of Log4J properties if we don't find the Log4J property file in application
126 * config directory. This is necessary especially if the application was launched by
127 * Webstart.
128 * <p>
129 * If the copy action fails, error messages are written to <code>System.err</code> but the
130 * application continues.
131 *
132 * @param config Configuration file.
133 */
134 private static void initLog4J(final QedeqGuiConfig config) {
135 final String resourceName = "log4j.xml";
136 // LATER mime 20070927: hard coded entry "config":
137 String resourceDirectoryName = "config";
138 final File resourceDir = new File(config.getBasisDirectory(), resourceDirectoryName);
139 final File log4jConfig = new File(resourceDir, resourceName);
140 String res = "/" + resourceDirectoryName + "/" + resourceName;
141 // if the config file doesn't exist in the file system, we take it from the class path
142 // and save it in the file system!
143 if (!log4jConfig.exists()) {
144 final URL log4jConfigUrl = QedeqMainFrame.class.getResource(res);
145 if (log4jConfigUrl == null) {
146 errorPrintln("Resource not found: " + res);
147 } else {
148 try {
149 if (!resourceDir.exists()) {
150 if (!resourceDir.mkdirs()) {
151 errorPrintln("Creation of directory failed: "
152 + resourceDir.getAbsolutePath());
153 }
154 }
155 final StringBuffer buffer = new StringBuffer();
156 // if this would be a properties file would have to load it with ISO-8859-1
157 IoUtility.loadFile(log4jConfigUrl, buffer, "UTF-8");
158 IoUtility.saveFile(log4jConfig, buffer, "UTF-8");
159 } catch (IOException e1) {
160 errorPrintln("Resource can not be saved: " + log4jConfig.getAbsolutePath());
161 e1.printStackTrace();
162 }
163 }
164 } else {
165 res = UrlUtility.toUrl(log4jConfig).toString();
166 }
167 System.setProperty("log4j.configDebug", "true");
168 System.setProperty("log4j.configuration", res);
169
170 // init Log4J watchdog
171 try {
172 // set properties and watch file every 5 seconds
173 if (res.endsWith(".xml")) {
174 DOMConfigurator.configureAndWatch(log4jConfig.getCanonicalPath(), 5000);
175 } else {
176 PropertyConfigurator.configureAndWatch(log4jConfig.getCanonicalPath(), 5000);
177 }
178 } catch (Exception e) {
179 e.printStackTrace();
180 }
181 }
182
183 /**
184 * Print error message. Writes to <code>System.err</code>.
185 *
186 * @param message Message to print.
187 */
188 private static void errorPrintln(final String message) {
189 System.err.println("ERROR>>> " + message);
190 }
191
192 public static void main(final String[] args) {
193 // load configuration file
194 try {
195 QedeqGuiConfig.init(new File(IoUtility.getStartDirectory("qedeq"),
196 "config/org.qedeq.properties"), IoUtility.getStartDirectory("qedeq"));
197 } catch (Throwable e) {
198 e.printStackTrace();
199 JOptionPane.showInternalMessageDialog(null, "Configuration file not found!\n\n"
200 + e, "Hilbert II - Error", JOptionPane.ERROR_MESSAGE);
201 System.exit(-1);
202 return;
203 }
204
205 try {
206 // we make a local file copy of the log4j.properties if it dosen't exist already
207 initLog4J(QedeqGuiConfig.getInstance());
208 } catch (Throwable e) {
209 e.printStackTrace();
210 JOptionPane.showMessageDialog(null, "Initialization of Log4J failed!\n\n"
211 + e, "Hilbert II - Error", JOptionPane.ERROR_MESSAGE);
212 System.exit(-2);
213 return;
214 }
215
216 try {
217 final GuiOptions options = new GuiOptions();
218 {
219 String lafShortName = QedeqGuiConfig.getInstance().getLookAndFeel();
220 String lafClassName;
221 if ("Windows".equalsIgnoreCase(lafShortName)) {
222 lafClassName = Options.JGOODIES_WINDOWS_NAME;
223 } else if ("Plastic".equalsIgnoreCase(lafShortName)) {
224 lafClassName = Options.PLASTIC_NAME;
225 } else if ("Plastic3D".equalsIgnoreCase(lafShortName)) {
226 lafClassName = Options.PLASTIC3D_NAME;
227 } else if ("PlasticXP".equalsIgnoreCase(lafShortName)) {
228 lafClassName = Options.PLASTICXP_NAME;
229 } else if ("Metal".equalsIgnoreCase(lafShortName)) {
230 lafClassName = "javax.swing.plaf.metal.MetalLookAndFeel";
231 } else {
232 lafClassName = lafShortName;
233 }
234 options.setSelectedLookAndFeel(lafClassName);
235 }
236 final QedeqMainFrame instance;
237 try {
238 instance = new QedeqMainFrame(options);
239 } catch (IOException e) {
240 e.printStackTrace(System.out);
241 JOptionPane.showMessageDialog(null, "Application start failed!\n\n"
242 + e, "Hilbert II - Error", JOptionPane.ERROR_MESSAGE);
243 KernelContext.getInstance().shutdown();
244 System.exit(-3);
245 return;
246 }
247 instance.setSize(PREFERRED_SIZE);
248 Dimension paneSize = instance.getSize();
249 Dimension screenSize = instance.getToolkit().getScreenSize();
250 instance.setLocation(
251 (screenSize.width - paneSize.width) / 2,
252 (screenSize.height - paneSize.height) / 2);
253 instance.setVisible(true);
254
255 // wait till GUI is ready
256 SwingUtilities.invokeLater(new Runnable() {
257 public void run() {
258 // now we are ready to fire up the kernel
259 KernelContext.getInstance().startup();
260 }
261 });
262 } catch (Throwable e) {
263 e.printStackTrace(System.out);
264 Trace.fatal(QedeqMainFrame.class, "main(String[])", "Unexpected major failure!", e);
265 JOptionPane.showMessageDialog(null, "Unexpected major failure!\n\n"
266 + e, "Hilbert II - Error", JOptionPane.ERROR_MESSAGE);
267 System.exit(-4);
268 return;
269 }
270 }
271
272 }
|