package net.sourceforge.fidocadj; import javax.swing.*; import java.util.prefs.*; import java.io.*; import java.util.*; import java.awt.*; import java.lang.reflect.*; import net.sourceforge.fidocadj.circuit.*; import net.sourceforge.fidocadj.circuit.controllers.*; import net.sourceforge.fidocadj.circuit.model.*; import net.sourceforge.fidocadj.export.*; import net.sourceforge.fidocadj.geom.*; import net.sourceforge.fidocadj.globals.*; import net.sourceforge.fidocadj.layers.*; import net.sourceforge.fidocadj.timer.*; import net.sourceforge.fidocadj.graphic.*; /** FidoMain.java SWING App: The starting point of FidoCadJ. <pre> This file is part of FidoCadJ. FidoCadJ is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FidoCadJ is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FidoCadJ. If not, @see <a href=http://www.gnu.org/licenses/>http://www.gnu.org/licenses/</a>. Copyright 2008-2016 by Davide Bucci </pre> @author Davide Bucci */ public class FidoMain { private static CommandLineParser clp; /** The main method. Process the command line options and if necessary shows an instance of FidoFrame. @param args the command line arguments. */ public static void main(String... args) { clp = new CommandLineParser(); if (args.length>=1) clp.processArguments(args); applyOptimizationSettings(clp); // Now we proceed with all the operations: opening files, converting... if(clp.getHeadlessMode()) { // Creates a circuit object DrawingModel P = new DrawingModel(); if("".equals(clp.getLoadFileName())) { System.err.println("You should specify a FidoCadJ file to"+ " read"); System.exit(1); } // Reads the standard libraries readLibrariesProbeDirectory(P, false, clp.getLibDirectory()); P.setLayers(StandardLayers.createStandardLayers()); ParserActions pa=new ParserActions(P); MyTimer mt = new MyTimer(); try { String txt = FileUtils.readFile(clp.getLoadFileName()); // Here txt contains the new circuit: parse it! pa.parseString(new StringBuffer(txt)); } catch(IllegalArgumentException iae) { System.err.println("Illegal filename"); } catch(Exception e) { System.err.println("Unable to process: "+e); } if (clp.shouldConvertFile()) { doConvert(clp, P); } if (clp.getHasToPrintSize()) { PointG o=new PointG(0,0); DimensionG d = DrawingSize.getImageSize(P,1, true, o); System.out.println(""+d.width+" "+d.height); } if (clp.getHasToPrintTime()) { System.out.println("Elapsed time: "+mt.getElapsed()+" ms."); } } if (!clp.getCommandLineOnly()) { SwingUtilities.invokeLater(new CreateSwingInterface( clp.getLibDirectory(), clp.getLoadFileName(), clp.getWantedLocale())); } } /** Apply optimisation settings which are platform-dependent. @param clp command-line arguments may deactivate some optimisations. */ private static void applyOptimizationSettings(CommandLineParser clp) { if(!clp.getStripOptimization() && System.getProperty("os.name").startsWith("Mac")) { // CAREFUL************************************************** // In all MacOSX systems I tried, this greatly increases the // redrawing speed. *HOWEVER* the default value for Java 1.6 // as distributed by Apple is "false" (whereas it was "true" // for Java 1.5). This might mean that in a future this can // be not very useful, or worse slowdown the performances. // CAREFUL************************************************** // NOTE: this does not seem to have any effect! System.setProperty("apple.awt.graphics.UseQuartz", "true"); } /* if(!clp.getStripOptimization() && System.getProperty("os.name").toLowerCase().startsWith("linux")) { // CAREFUL************************************************** // Various sources reports that this option will increase // the redrawing speed using Linux. It might happen, however // that the performances can be somewhat degraded in some // systems. // CAREFUL************************************************** // We tested that in version 0.24.1. In fact, activating this // option renders the software inusable in some systems (Nvidia // graphic software?) So this option is definitively turned off. // System.setProperty("sun.java2d.opengl", "true"); // See for example this discussion: http://tinyurl.com/axoxqcb } */ } /** Perform a conversion into a graphic file, from command line parameters. A file should have already been loaded and parsed into P. This routine also checks if the output file has a correct extension, coherent with the file format chosen. @param clp command-line arguments. @param P the model containing the drawing. */ private static void doConvert(CommandLineParser clp, DrawingModel P) { if(!Globals.checkExtension(clp.getOutputFile(), clp.getExportFormat()) && !clp.getForceMode()) { System.err.println( "File extension is not coherent with the "+ "export output format! Use -f to skip this test."); System.exit(1); } try { if (clp.getResolutionBasedExport()) { ExportGraphic.export(new File(clp.getOutputFile()), P, clp.getExportFormat(), clp.getResolution(), true,false,true, true); } else { ExportGraphic.exportSize(new File(clp.getOutputFile()), P, clp.getExportFormat(), clp.getXSize(), clp.getYSize(), true,false,true,true); } System.out.println("Export completed"); } catch(IOException ioe) { System.err.println("Export error: "+ioe); } } /** Read all libraries, eventually by inspecting the directory specified by the user. There are three standard directories: IHRAM.FCL, FCDstdlib.fcl and PCB.fcl. If those files are found in the external directory specified, the internal version is not loaded. Other files on the external directory are loaded. @param P the parsing class in which the libraries should be loaded @param englishLibraries a flag to specify if the internal libraries should be loaded in English or in Italian. @param libDirectoryO the path of the external directory. */ public static void readLibrariesProbeDirectory(DrawingModel P, boolean englishLibraries, String libDirectoryO) { String libDirectory=libDirectoryO; ParserActions pa = new ParserActions(P); synchronized(P) { if (libDirectory == null || libDirectory.length()<3) libDirectory = System.getProperty("user.home"); readIHRAM(englishLibraries, libDirectory, pa); readFCDstdlib(englishLibraries, libDirectory, pa); readPCBlib(englishLibraries, libDirectory, pa); readEY_Libraries(englishLibraries, libDirectory, pa); readElecLib(englishLibraries, libDirectory, pa); } } /** Read the internal IHRAM library, unless a file called IHRAM.FCL is present in the library directory @param libDirectory path where to search for the library. @param englishLibraries specify if the English version of the lib should be loaded instead of the Italian one. @param pa the object by which the library will be crunched. */ private static void readIHRAM(boolean englishLibraries, String libDirectory, ParserActions pa) { pa.loadLibraryDirectory(libDirectory); if (new File(Globals.createCompleteFileName( libDirectory,"IHRAM.FCL")).exists()) { System.out.println("IHRAM library got from external file"); } else { if(englishLibraries) pa.loadLibraryInJar(FidoFrame.class.getResource( "lib/IHRAM_en.FCL"), "ihram"); else pa.loadLibraryInJar(FidoFrame.class.getResource( "lib/IHRAM.FCL"), "ihram"); } } /** Read the internal FCDstdlib library, unless a file called FCDstdlib.fcl is present in the library directory @param libDirectory path where to search for the library. @param englishLibraries specify if the English version of the lib should be loaded instead of the Italian one. @param pa the object by which the library will be crunched. */ private static void readFCDstdlib(boolean englishLibraries, String libDirectory, ParserActions pa) { if (new File(Globals.createCompleteFileName( libDirectory,"FCDstdlib.fcl")).exists()) { System.out.println("Standard library got from external file"); } else { if(englishLibraries) pa.loadLibraryInJar(FidoFrame.class.getResource( "lib/FCDstdlib_en.fcl"), ""); else pa.loadLibraryInJar(FidoFrame.class.getResource( "lib/FCDstdlib.fcl"), ""); } } /** Read the internal PCB library, unless a file called PCB.fcl is present in the library directory @param libDirectory path where to search for the library. @param englishLibraries specify if the English version of the lib should be loaded instead of the Italian one. @param pa the object by which the library will be crunched. */ private static void readPCBlib(boolean englishLibraries, String libDirectory, ParserActions pa) { if (new File(Globals.createCompleteFileName( libDirectory,"PCB.fcl")).exists()) { System.out.println("Standard PCB library got from external file"); } else { if(englishLibraries) pa.loadLibraryInJar(FidoFrame.class.getResource( "lib/PCB_en.fcl"), "pcb"); else pa.loadLibraryInJar(FidoFrame.class.getResource( "lib/PCB.fcl"), "pcb"); } } /** Read the internal EY_Libraries library, unless a file called EY_Libraries.fcl is present in the library directory @param libDirectory path where to search for the library. @param englishLibraries specify if the English version of the lib should be loaded instead of the Italian one. @param pa the object by which the library will be crunched. */ private static void readEY_Libraries(boolean englishLibraries, String libDirectory, ParserActions pa) { if (new File(Globals.createCompleteFileName( libDirectory,"EY_Libraries.fcl")).exists()) { System.out.println("Standard EY_Libraries got from external file"); } else { pa.loadLibraryInJar(FidoFrame.class.getResource( "lib/EY_Libraries.fcl"), "EY_Libraries"); } } /** Read the internal elettrotecnica library, unless a file called elettrotecnica.fcl is present in the library directory @param libDirectory path where to search for the library. @param englishLibraries specify if the English version of the lib should be loaded instead of the Italian one. @param pa the object by which the library will be crunched. */ private static void readElecLib(boolean englishLibraries, String libDirectory, ParserActions pa) { if (new File(Globals.createCompleteFileName( libDirectory,"elettrotecnica.fcl")).exists()) { System.out.println( "Electrotechnics library got from external file"); } else { if(englishLibraries) pa.loadLibraryInJar(FidoFrame.class.getResource( "lib/elettrotecnica_en.fcl"), "elettrotecnica"); else pa.loadLibraryInJar(FidoFrame.class.getResource( "lib/elettrotecnica.fcl"), "elettrotecnica"); } } } /** Creates the Swing elements needed for the interface. */ class CreateSwingInterface implements Runnable { String libDirectory; String loadFile; Locale currentLocale; /** Constructor where we specify some details concerning the library directory, the file to load (if needed) as well as the locale. @param ld the library directory @param lf the file to load @param ll the locale. */ public CreateSwingInterface (String ld, String lf, Locale ll) { libDirectory = ld; loadFile = lf; currentLocale =ll; } /** Standard constructor. */ public CreateSwingInterface () { libDirectory = ""; loadFile = ""; } /** Run the thread. */ public void run() { /******************************************************************* PLATFORM SELECTION AND CONFIGURATION CODE GOES IN THIS SECTION *******************************************************************/ if (System.getProperty("os.name").startsWith("Mac")) { Globals g=new Globals(); Preferences prefs_static = Preferences.userNodeForPackage(g.getClass()); Globals.quaquaActive = prefs_static.get("QUAQUA", "true").equals("true"); Globals.weAreOnAMac =true; // These settings allows to obtain menus on the right place System.setProperty("com.apple.macos.useScreenMenuBar","true"); // This is for JVM < 1.5 It won't harm on higher versions. System.setProperty("apple.laf.useScreenMenuBar","true"); // This is for having the good application name in the menu System.setProperty( "com.apple.mrj.application.apple.menu.about.name", "FidoCadJ"); try { //Globals.quaquaActive=true; //System.setProperty("Quaqua.Debug.showVisualBounds","true"); //System.setProperty("Quaqua.Debug.showClipBounds","true"); if(Globals.quaquaActive) { UIManager.setLookAndFeel( "ch.randelshofer.quaqua.QuaquaLookAndFeel"); System.out.println("Quaqua look and feel active"); } } catch (Exception e) { // Quaqua is not active. Just continue! System.out.println( "The Quaqua look and feel is not available"); System.out.println( "I will continue with the basic Apple l&f"); } } else if (System.getProperty("os.name").startsWith("Win")) { /* If the host system is a window system, select the Windows look and feel. This is a way to encourage people to use FidoCadJ even on a Windows system, forgotting about Java. */ try { UIManager.setLookAndFeel( "com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); } catch (Exception E) { System.out.println("Could not load the Windows Look and feel!"); } Globals.quaquaActive=false; } else { Globals.quaquaActive=false; } // Un-comment to try to use the Metal LAF /* try { UIManager.setLookAndFeel( UIManager.getCrossPlatformLookAndFeelClassName()); Globals.weAreOnAMac =false; } catch (Exception E) {} */ /******************************************************************* END OF THE PLATFORM SELECTION CODE *******************************************************************/ if(Globals.weAreOnAMac) { // Here we use the reflection provided by Java to understand // if the AppleSpecific class is available on the system. // This class should be compiled separately from the main // program since the compilation can be successful only on // a MacOSX system. try { Class<?> a = Class.forName( "net.sourceforge.fidocadj.AppleSpecific"); Object b = a.newInstance(); Method m = a.getMethod("answerFinder"); m.invoke(b); } catch (Exception exc) { Globals.weAreOnAMac = false; System.out.println("It seems that this software has been "+ "compiled on a system different from MacOSX. Some nice "+ "integrations with MacOSX will therefore be absent. If "+ "you have compiled on MacOSX, make sure you used the "+ "'compile' or 'rebuild' script along with the 'mac' "+ "option."); } } // Here we create the main window object FidoFrame popFrame=new FidoFrame(true, currentLocale); if (!"".equals(libDirectory)) { popFrame.libDirectory = libDirectory; } popFrame.init(); // We begin by showing immediately the window. This improves the // perception of speed given to the user, since the libraries // are not yet loaded popFrame.setVisible(true); // We load the libraries (this does not take so long in modern // systems). popFrame.loadLibraries(); // If a file should be loaded, load it now, since popFrame has been // created and initialized. if(!"".equals(loadFile)) popFrame.getFileTools().load(loadFile); // We force a global validation of the window size, by including // this time the tree containing the various libraries and the // macros. popFrame.setVisible(true); } }