001 /* This file is part of the project "Hilbert II" - http://www.qedeq.org
002 *
003 * Copyright 2000-2014, 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.internal.DefaultInternalKernelServices;
050 import org.qedeq.kernel.xml.dao.XmlQedeqFileDao;
051
052 import com.jgoodies.looks.Options;
053
054 /**
055 * This is the main frame of the GUI frontend for a standalone program
056 * version of <b>Hilbert II</b>.
057 *
058 * @author Michael Meyling
059 */
060 public class QedeqMainFrame extends JFrame {
061
062 /** Directory for start within IDE. */
063 private static final String QEDEQ_IDE = "qedeq_ide_run";
064
065 /** Directory for start within IDE. */
066 private static final String QEDEQ_IDE_START = "../../" + QEDEQ_IDE;
067
068 /** Initial frame resolution. */
069 // protected static final Dimension PREFERRED_SIZE = (LookUtils.IS_LOW_RESOLUTION
070 // ? new Dimension(650, 510) : new Dimension(740, 660));
071 protected static final Dimension PREFERRED_SIZE = (GuiHelper.IS_LOW_RESOLUTION
072 ? new Dimension(650, 510) : new Dimension(900, 660));
073
074 /**
075 * Constructor, configures the UI, and builds the content. Also some indirectly some GUI
076 * loggers are added.
077 *
078 * @param settings GUI options.
079 * @throws IOException Initialization failed for IO reasons.
080 */
081 public QedeqMainFrame(final GuiOptions settings) throws IOException {
082 GuiHelper.configureUI(settings);
083
084 checkDirectoryExistenceAndOptionallyCreate(QedeqGuiConfig.getInstance());
085
086 // add various loggers
087 // QedeqLog.getInstance().addLog(new LogListenerImpl()); // System.out
088 QedeqLog.getInstance().addLog(new TraceListener()); // trace file
089 QedeqLog.getInstance() // log file
090 .addLog(new LogListenerImpl(new PrintStream(
091 new FileOutputStream(QedeqGuiConfig.getInstance().getLogFile(), true), true, "UTF8")));
092 ModuleEventLog.getInstance().addLog(new ModuleEventListenerLog()); // all loggers
093
094 // initialize the kernel, this may create already some logging events
095 KernelContext.getInstance().init(
096 QedeqGuiConfig.getInstance(),
097 new DefaultInternalKernelServices(QedeqGuiConfig.getInstance(),
098 KernelContext.getInstance(), new XmlQedeqFileDao()));
099
100 // create new controller for all possible actions
101 final QedeqController controller = new QedeqController(this);
102
103 // assemble main GUI window
104 final JPanel panel = new JPanel(new BorderLayout());
105 panel.add(new QedeqMainPane(controller), BorderLayout.CENTER);
106 setContentPane(panel);
107 setTitle(" " + KernelContext.getInstance().getDescriptiveKernelVersion());
108 final JMenuBar menuBar = new QedeqMenuBar(controller, settings);
109 setJMenuBar(menuBar);
110 setIconImage(GuiHelper.readImageIcon("qedeq/16x16/qedeq.png").getImage());
111 setIconImage(GuiHelper.readImageIcon("qedeq/48x48/qedeq.png").getImage());
112 addWindowListener(new WindowAdapter() {
113 public void windowClosing(final WindowEvent e) {
114 controller.getExitAction().actionPerformed(null);
115 }
116 });
117
118 }
119
120 private void checkDirectoryExistenceAndOptionallyCreate(final QedeqGuiConfig config)
121 throws IOException {
122 // application log file directory
123 {
124 final File file = config.getLogFile();
125 final File dir = file.getParentFile();
126 if (!dir.exists() && !dir.mkdirs()) {
127 throw new IOException("can't create directory: " + dir.getAbsolutePath());
128 }
129 }
130 }
131
132 /**
133 * Make local copy of Log4J properties if we don't find the Log4J property file in application
134 * config directory. This is necessary especially if the application was launched by
135 * Webstart.
136 * <p>
137 * If the copy action fails, error messages are written to <code>System.err</code> but the
138 * application continues.
139 *
140 * @param config Configuration file.
141 */
142 private static void initLog4J(final QedeqGuiConfig config) {
143 final String resourceName = "log4j.xml";
144 // LATER mime 20070927: hard coded entry "config":
145 String resourceDirectoryName = "config";
146 final File resourceDir = new File(config.getBasisDirectory(), resourceDirectoryName);
147 final File log4jConfig = new File(resourceDir, resourceName);
148 String res = "/" + resourceDirectoryName + "/" + resourceName;
149 // if the config file doesn't exist in the file system, we take it from the class path
150 // and save it in the file system!
151 if (!log4jConfig.exists()) {
152 final URL log4jConfigUrl = QedeqMainFrame.class.getResource(res);
153 if (log4jConfigUrl == null) {
154 errorPrintln("Resource not found: " + res);
155 } else {
156 try {
157 if (!resourceDir.exists()) {
158 if (!resourceDir.mkdirs()) {
159 errorPrintln("Creation of directory failed: "
160 + resourceDir.getAbsolutePath());
161 }
162 }
163 final StringBuffer buffer = new StringBuffer();
164 // if this would be a properties file would have to load it with ISO-8859-1
165 IoUtility.loadFile(log4jConfigUrl, buffer, "UTF-8");
166 // if we start this within our IDE we don't want to fiddle with our SCM system
167 System.out.println("basis dir: " + config.getBasisDirectory());
168 if (config.getBasisDirectory().toString().endsWith(QEDEQ_IDE)) {
169 StringUtility.replace(buffer, "log/trace.log", QEDEQ_IDE_START + "/log/trace.log");
170 }
171 IoUtility.saveFile(log4jConfig, buffer, "UTF-8");
172 } catch (IOException e1) {
173 errorPrintln("Resource can not be saved: " + log4jConfig.getAbsolutePath());
174 e1.printStackTrace();
175 }
176 }
177 } else {
178 res = UrlUtility.toUrl(log4jConfig).toString();
179 }
180 System.setProperty("log4j.configDebug", "true");
181 System.setProperty("log4j.configuration", res);
182
183 // init Log4J watchdog
184 try {
185 // set properties and watch file every 5 seconds
186 if (res.endsWith(".xml")) {
187 DOMConfigurator.configureAndWatch(log4jConfig.getCanonicalPath(), 5000);
188 } else {
189 PropertyConfigurator.configureAndWatch(log4jConfig.getCanonicalPath(), 5000);
190 }
191 } catch (Exception e) {
192 e.printStackTrace();
193 }
194 }
195
196 /**
197 * Print error message. Writes to <code>System.err</code>.
198 *
199 * @param message Message to print.
200 */
201 private static void errorPrintln(final String message) {
202 System.err.println("ERROR>>> " + message);
203 }
204
205 public static void main(final String[] args) {
206 // load configuration file
207 try {
208 File startDirectory = IoUtility.getStartDirectory("qedeq");
209 // if we start this within our IDE we don't want to fiddle with our SCM system
210 if (startDirectory.toString().equals(".") && startDirectory.getCanonicalFile().getName()
211 .equals("QedeqGuiSe")) {
212 startDirectory = new File(QEDEQ_IDE_START);
213 }
214 QedeqGuiConfig.init(new File(startDirectory,
215 "config/org.qedeq.properties"), startDirectory);
216 } catch (Throwable e) {
217 e.printStackTrace();
218 JOptionPane.showInternalMessageDialog(null, "Configuration file not found!\n\n"
219 + e, "Hilbert II - Error", JOptionPane.ERROR_MESSAGE);
220 System.exit(-1);
221 return;
222 }
223
224 try {
225 // we make a local file copy of the log4j.properties if it dosen't exist already
226 initLog4J(QedeqGuiConfig.getInstance());
227 } catch (Throwable e) {
228 e.printStackTrace();
229 JOptionPane.showMessageDialog(null, "Initialization of Log4J failed!\n\n"
230 + e, "Hilbert II - Error", JOptionPane.ERROR_MESSAGE);
231 System.exit(-2);
232 return;
233 }
234
235 try {
236 final GuiOptions options = new GuiOptions();
237 {
238 String lafShortName = QedeqGuiConfig.getInstance().getLookAndFeel();
239 String lafClassName;
240 if ("Windows".equalsIgnoreCase(lafShortName)) {
241 lafClassName = Options.JGOODIES_WINDOWS_NAME;
242 } else if ("Plastic".equalsIgnoreCase(lafShortName)) {
243 lafClassName = Options.PLASTIC_NAME;
244 } else if ("Plastic3D".equalsIgnoreCase(lafShortName)) {
245 lafClassName = Options.PLASTIC3D_NAME;
246 } else if ("PlasticXP".equalsIgnoreCase(lafShortName)) {
247 lafClassName = Options.PLASTICXP_NAME;
248 } else if ("Metal".equalsIgnoreCase(lafShortName)) {
249 lafClassName = "javax.swing.plaf.metal.MetalLookAndFeel";
250 } else {
251 lafClassName = lafShortName;
252 }
253 options.setSelectedLookAndFeel(lafClassName);
254 }
255 final QedeqMainFrame instance;
256 try {
257 instance = new QedeqMainFrame(options);
258 } catch (IOException e) {
259 e.printStackTrace(System.out);
260 JOptionPane.showMessageDialog(null, "Application start failed!\n\n"
261 + e, "Hilbert II - Error", JOptionPane.ERROR_MESSAGE);
262 KernelContext.getInstance().shutdown();
263 System.exit(-3);
264 return;
265 }
266 instance.setSize(PREFERRED_SIZE);
267 Dimension paneSize = instance.getSize();
268 Dimension screenSize = instance.getToolkit().getScreenSize();
269 instance.setLocation(
270 (screenSize.width - paneSize.width) / 2,
271 (screenSize.height - paneSize.height) / 2);
272 instance.setVisible(true);
273
274 // wait till GUI is ready
275 SwingUtilities.invokeLater(new Runnable() {
276 public void run() {
277 // now we are ready to fire up the kernel
278 KernelContext.getInstance().startup();
279 }
280 });
281 } catch (Throwable e) {
282 e.printStackTrace(System.out);
283 Trace.fatal(QedeqMainFrame.class, "main(String[])", "Unexpected major failure!", e);
284 JOptionPane.showMessageDialog(null, "Unexpected major failure!\n\n"
285 + e, "Hilbert II - Error", JOptionPane.ERROR_MESSAGE);
286 System.exit(-4);
287 return;
288 }
289 }
290
291 }
|