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.base.utility.StringUtility;
040 import org.qedeq.gui.se.control.QedeqController;
041 import org.qedeq.gui.se.pane.QedeqGuiConfig;
042 import org.qedeq.gui.se.util.GuiHelper;
043 import org.qedeq.kernel.bo.KernelContext;
044 import org.qedeq.kernel.bo.log.LogListenerImpl;
045 import org.qedeq.kernel.bo.log.ModuleEventListenerLog;
046 import org.qedeq.kernel.bo.log.ModuleEventLog;
047 import org.qedeq.kernel.bo.log.QedeqLog;
048 import org.qedeq.kernel.bo.log.TraceListener;
049 import org.qedeq.kernel.bo.service.DefaultInternalKernelServices;
050 import org.qedeq.kernel.xml.dao.XmlQedeqFileDao;
051
052 import com.jgoodies.looks.LookUtils;
053 import com.jgoodies.looks.Options;
054
055 /**
056 * This is the main frame of the GUI frontend for a standalone program
057 * version of <b>Hilbert II</b>.
058 *
059 * @author Michael Meyling
060 */
061 public class QedeqMainFrame extends JFrame {
062
063 /** Initial frame resolution. */
064 protected static final Dimension PREFERRED_SIZE = (LookUtils.IS_LOW_RESOLUTION
065 ? new Dimension(650, 510) : new Dimension(740, 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 resource = new File(resourceDir, resourceName);
140 String res = "/" + resourceDirectoryName + "/" + resourceName;
141 if (!resource.exists()) {
142 final URL url = QedeqMainFrame.class.getResource(res);
143 if (url == null) {
144 errorPrintln("Resource not found: " + res);
145 } else {
146 try {
147 if (!resourceDir.exists()) {
148 if (!resourceDir.mkdirs()) {
149 errorPrintln("Creation of directory failed: "
150 + resourceDir.getAbsolutePath());
151 }
152 }
153 final StringBuffer buffer = new StringBuffer();
154 IoUtility.loadFile(url, buffer, "ISO-8859-1");
155 File traceFile = config.createAbsolutePath("log/trace.txt");
156 StringUtility.replace(buffer, "@trace_file_path@", traceFile.toString()
157 .replace('\\', '/'));
158 // for a properties file:
159 // IoUtility.escapeProperty(traceFile.toString().replace('\\', '/')));
160 IoUtility.saveFile(resource, buffer, "ISO-8859-1");
161 res = UrlUtility.toUrl(resource).toString();
162 } catch (IOException e1) {
163 errorPrintln("Resource can not be saved: " + resource.getAbsolutePath());
164 e1.printStackTrace();
165 }
166 }
167 } else {
168 res = UrlUtility.toUrl(resource).toString();
169 }
170 System.setProperty("log4j.configDebug", "true");
171 System.setProperty("log4j.configuration", res);
172
173 // init Log4J watchdog
174 try {
175 // set properties and watch file every 5 seconds
176 if (res.endsWith(".xml")) {
177 DOMConfigurator.configureAndWatch(resource.getCanonicalPath(), 5000);
178 } else {
179 PropertyConfigurator.configureAndWatch(resource.getCanonicalPath(), 5000);
180 }
181 } catch (Exception e) {
182 e.printStackTrace();
183 }
184 }
185
186 /**
187 * Print error message. Writes to <code>System.err</code>.
188 *
189 * @param message Message to print.
190 */
191 private static void errorPrintln(final String message) {
192 System.err.println("ERROR>>> " + message);
193 }
194
195 public static void main(final String[] args) {
196 // load configuration file
197 try {
198 QedeqGuiConfig.init(new File(IoUtility.getStartDirectory("qedeq"),
199 "config/org.qedeq.properties"), IoUtility.getStartDirectory("qedeq"));
200 } catch (Throwable e) {
201 e.printStackTrace();
202 JOptionPane.showInternalMessageDialog(null, "Configuration file not found!\n\n"
203 + e, "Hilbert II - Error", JOptionPane.ERROR_MESSAGE);
204 System.exit(-1);
205 return;
206 }
207
208 try {
209 // we make a local file copy of the log4j.properties if it dosen't exist already
210 initLog4J(QedeqGuiConfig.getInstance());
211 } catch (Throwable e) {
212 e.printStackTrace();
213 JOptionPane.showMessageDialog(null, "Initialization of Log4J failed!\n\n"
214 + e, "Hilbert II - Error", JOptionPane.ERROR_MESSAGE);
215 System.exit(-2);
216 return;
217 }
218
219 try {
220 final GuiOptions options = new GuiOptions();
221 {
222 String lafShortName = QedeqGuiConfig.getInstance().getLookAndFeel();
223 String lafClassName;
224 if ("Windows".equalsIgnoreCase(lafShortName)) {
225 lafClassName = Options.JGOODIES_WINDOWS_NAME;
226 } else if ("Plastic".equalsIgnoreCase(lafShortName)) {
227 lafClassName = Options.PLASTIC_NAME;
228 } else if ("Plastic3D".equalsIgnoreCase(lafShortName)) {
229 lafClassName = Options.PLASTIC3D_NAME;
230 } else if ("PlasticXP".equalsIgnoreCase(lafShortName)) {
231 lafClassName = Options.PLASTICXP_NAME;
232 } else if ("Metal".equalsIgnoreCase(lafShortName)) {
233 lafClassName = "javax.swing.plaf.metal.MetalLookAndFeel";
234 } else {
235 lafClassName = lafShortName;
236 }
237 options.setSelectedLookAndFeel(lafClassName);
238 }
239 final QedeqMainFrame instance;
240 try {
241 instance = new QedeqMainFrame(options);
242 } catch (IOException e) {
243 e.printStackTrace(System.out);
244 JOptionPane.showMessageDialog(null, "Application start failed!\n\n"
245 + e, "Hilbert II - Error", JOptionPane.ERROR_MESSAGE);
246 KernelContext.getInstance().shutdown();
247 System.exit(-3);
248 return;
249 }
250 instance.setSize(PREFERRED_SIZE);
251 Dimension paneSize = instance.getSize();
252 Dimension screenSize = instance.getToolkit().getScreenSize();
253 instance.setLocation(
254 (screenSize.width - paneSize.width) / 2,
255 (screenSize.height - paneSize.height) / 2);
256 instance.setVisible(true);
257
258 // wait till GUI is ready
259 SwingUtilities.invokeLater(new Runnable() {
260 public void run() {
261 // now we are ready to fire up the kernel
262 KernelContext.getInstance().startup();
263 }
264 });
265 } catch (Throwable e) {
266 e.printStackTrace(System.out);
267 Trace.fatal(QedeqMainFrame.class, "main(String[])", "Unexpected major failure!", e);
268 JOptionPane.showMessageDialog(null, "Unexpected major failure!\n\n"
269 + e, "Hilbert II - Error", JOptionPane.ERROR_MESSAGE);
270 System.exit(-4);
271 return;
272 }
273 }
274
275 }
|