/**************************************************************************** ** ** Copyright (C) 1992-2007 Trolltech ASA. All rights reserved. ** ** This file is part of Qt Jambi. ** ** ** This file may be used under the terms of the GNU General Public ** License version 2.0 as published by the Free Software Foundation ** and appearing in the file LICENSE.GPL included in the packaging of ** this file. Please review the following information to ensure GNU ** General Public Licensing requirements will be met: ** http://www.trolltech.com/products/qt/opensource.html ** ** If you are unsure which license is appropriate for your use, please ** review the following information: ** http://www.trolltech.com/products/qt/licensing.html or contact the ** sales department at sales@trolltech.com. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ****************************************************************************/ package com.trolltech.launcher; import com.trolltech.qt.core.*; import com.trolltech.qt.gui.*; import com.trolltech.examples.QtJambiExample; import java.lang.reflect.*; public class Launchable { private static class SourceFormatter { private static String KEYWORDS[] = new String[] { "for ", "if ", "switch ", " int ", "const", "void ", "case ", "double ", "static", "new", "this", "package", "true", "false", "public", "protected", "private", "final", "native", "import", "extends", "implements", "else", "class", "super", }; static public String format(String source) { int start = -1; int end = -1; boolean stop = false; do { start = source.indexOf("// REMOVE-START"); end = source.indexOf("// REMOVE-END"); if (start != -1 && end > start) { source = source.substring(0, start) + source.substring(end + 13); } else { stop = true; } } while (!stop); source = source.replace("&", "&"); source = source.replace("<", "<"); source = source.replace(">", ">"); source = source.replace("\t", " "); for (int i=0; i<KEYWORDS.length; ++i) { String keyword = KEYWORDS[i]; source = source.replace(keyword, "<font color=olive>" + keyword + "</font>"); } source = source.replace("(int ", "(<font color=olive><b>int </b></font>"); source = source.replaceAll("(\\d\\d?)", "<font color=navy>$1</font>"); String commentRe = "(//+[.[^\n]]*\n)"; source = source.replaceAll(commentRe, "<font color=darkgreen><i>$1</i></font>"); String stringLiteralRe = "(\".+\")"; source = source.replaceAll(stringLiteralRe, "<font color=green>$1</font>"); source = "<html style=\"white-space:pre-wrap;font-family:courier new\">" + source + "</html>"; return source; } } // end of SourceFormatter private QWidget m_widget; private String m_description; private String m_name; private String m_className; private String m_source; private Launchable(String name, String className) { m_name = name; m_className = className; } public QWidget widget() { if (m_widget == null) createWidget(); return m_widget; } public String name() { return m_name; } public String description() { if (m_description == null) loadDescription(); return m_description; } public String source() { if (m_source == null) loadSource(); return m_source; } public void killWidget() { m_widget.close(); m_widget.disposeLater(); m_widget = null; } private final String resourceFile(String fileType) { QFile f = new QFile("classpath:" + m_className.replace(".", "/") + "." + fileType); if (f.exists() && f.open(new QFile.OpenMode(QFile.OpenModeFlag.ReadOnly, QFile.OpenModeFlag.Text))) return f.readAll().toString(); return null; } /** * Searches for the description and loads it if possible */ private void loadDescription() { m_description = resourceFile("html"); if (m_description == null) m_description = "<h1 align=\"center\">" + m_name + "</h1>" + "<p>The '<i>" + m_name + "</i>' demo does not have a description.</p>" + "<p>Investigate this demo futher:<ul><li>Run it, by clicking the '<i>Launch</i>' button.</li>" + "<li>Look at the source code, by clicking the '<i>View Source</i>' button.</li></ul></p>"; } /** Searches for the source file and loads and HTMLifies it if possible. */ private void loadSource() { m_source = resourceFile("java"); if (m_source == null) { m_source = "<i>No source</i>"; } else { m_source = SourceFormatter.format(m_source); } } private void createWidget() { if (m_widget != null) throw new RuntimeException("widget shouldn't exist at this point"); try { Class<?> cl = Class.forName(m_className); try { cl.getConstructor(); m_widget = (QWidget) cl.newInstance(); } catch(Exception e) { Constructor constructor = cl.getConstructor(QWidget.class); m_widget = (QWidget) constructor.newInstance((QWidget) null); } } catch (Exception e) { e.printStackTrace(); } } public static Launchable create(String className) { try { Class<?> cl = Class.forName(className); if (Modifier.isPublic(cl.getModifiers()) && QWidget.class.isAssignableFrom(cl)) { QtJambiExample info = (QtJambiExample) cl.getAnnotation(QtJambiExample.class); if (info != null) { Constructor constructor = null; try { constructor = cl.getConstructor(); } catch (Exception e) { constructor = cl.getConstructor(QWidget.class); } String visibleName = className; boolean canIndeed = false; String can = info.canInstantiate(); if (can.equals("false") || can.equals("no")) { canIndeed = false; } else if (can.startsWith("call-static-method:")) { try { Method checkMethod = cl.getMethod(can.substring(19)); canIndeed = (Boolean) checkMethod.invoke(cl); } catch (Exception e) { e.printStackTrace(); } } else { // Nothing specified or something else... canIndeed = true; } if (!canIndeed) return null; if (info.name().length() > 0) visibleName = info.name(); if (constructor != null && Modifier.isPublic(constructor.getModifiers())) { Launchable l = new Launchable(visibleName, className); return l; } } } } catch (Throwable e) { System.out.println("failed: " + className + ": " + e.getClass().getName() + "; " + e.getMessage()); } return null; } }