/* GeoGebra - Dynamic Mathematics for Everyone http://www.geogebra.org This file is part of GeoGebra. This program 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. */ package geogebra.main; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.util.Locale; import java.util.Properties; /** * Class GeoGebraPortablePreferences * * Stores user settings and options as a property file. * For use in portable GeoGebra on usb and Cd/DVD. * * This class is returned by GeoGebraPreferences.getPrefs() instead * of GeoGebraPreferences itself, if the file * preferences.properties exists in the geogebra.jar-folder. * This opens up for three modes: * - Normal * - Portable GeoGebra * - Read-only network share or CD/DVD, where we want same setting for all * * geogebra.properties must have one line: * is_read_only=true (or false) * * A cleaner implementation would be to rewrite GeoGebraPreferences to an abstract class, as * an interface for GeoGebraSystemPreferences and GeoGebraPropertyFile, but as there probably * never will be a demand for a third class later, I chose a solution which makes it unneccessary * to change too many calling classes, by just making this one and do a small rewrite of getPrefs() * and add a setPropertyFile() in GeoGebraPreferences which then behaves like a kind of "singleton factory". * * This class implements all the commands of GeoGebraPreferences, but stores in propertyfile * given on the commandline: --settingsFile=\ (prefs.properties) * * Options/ToDo: * Might as well store: * xml in user.xml * ggt in macro.bin * to avoid escaping "=", b64 encode/decoding and save some time... * Also useful to have the xml in a separate file for editing? * On the other hand, this is done automatically in Properties, so not really a problem. * * @author Hans-Petter Ulven * @version 2010-03-07 */ public class GeoGebraPortablePreferences extends GeoGebraPreferences{ /* don't need, erase, have made protected in parentclass: private String XML_GGB_FACTORY_DEFAULT; // see loadPreferences() // special preference keys (copied from GeoGebraPreferences private final String XML_USER_PREFERENCES = "xml_user_preferences"; private final String TOOLS_FILE_GGT = "tools_file_ggt"; private final String APP_LOCALE = "app_locale"; private final String APP_CURRENT_IMAGE_PATH = "app_current_image_path"; private final String APP_FILE_ = "app_file_"; */ /// --- --- /// private final static boolean DEBUG = true; private final static String ERROR = "Error?"; //For debugging //private final static String EQUAL = "�EQUALS�"; //Substituting for "=" private final static String COMMENT = "GeoGebra Portable preferences (GeoGebra settings file)"; /// --- Properties --- /// // use parent class PROPERTY_FILEPATH private static String path=null; private static Properties properties=new Properties(); private static GeoGebraPortablePreferences singleton=null; /// --- Interface --- /// /* private singleton constructor */ private GeoGebraPortablePreferences(){} /* Singleton getInstance()->getPref() */ public synchronized static GeoGebraPreferences getPref() { if (singleton == null){ singleton = new GeoGebraPortablePreferences(); singleton.loadPreferences(); }//if return singleton; }//getPref() private void loadPreferences(){ try{ //debug("path: "+GeoGebraPreferences.PROPERTY_FILEPATH); File propertyfile=new File(GeoGebraPreferences.PROPERTY_FILEPATH); if(propertyfile.exists()){ //path=propertyfile.getCanonicalPath(); BufferedInputStream fis=new BufferedInputStream(new FileInputStream(propertyfile)); properties.load(fis); fis.close(); //debug("loadPreferences():");properties.list(System.out); }else{ //debug("Found no settings file..."); clearPreferences(); //clean and store a blank one. }//if }catch(Exception e){ debug("Problem loading settings file..."); e.printStackTrace(); }//try-catch }//loadPreferences private void storePreferences(){ if(!get("read_only","false").equals("true")){ try { BufferedOutputStream os=new BufferedOutputStream(new FileOutputStream(new File(GeoGebraPreferences.PROPERTY_FILEPATH))); properties.store(os,COMMENT); //Application.debug("storePreferences(): ");properties.list(System.out); os.close(); } catch (Exception e) { Application.debug("Problem with storing of preferences.properties..."+e.toString()); }//try-catch }//if not read-only. (else do nothing...) }//storePreferences() /// --- GeoGebraPreferences interface --- /// public String loadPreference(String key, String defaultValue) { //debug("loadPreferene() called with: "+key+", "+defaultValue); return get(key,defaultValue); }//loadPreference(key,def) public void savePreference(String key, String value) { //debug("savePreferneces() called with: "+key+", "+value); set(key,value); }//savePreferences(key,val) /** * Returns the path of the first file in the file list */ public File getDefaultFilePath() { File file = new File(properties.getProperty(APP_FILE_ + "1", "")); //debug("getDeafultFilepath(): "+file.toString()); if (file.exists()) return file.getParentFile(); else return null; }//getDefaultFilePath() /** * Returns the default image path */ public File getDefaultImagePath() { // image path String pathName = properties.getProperty(APP_CURRENT_IMAGE_PATH, null); if (pathName != null) return new File(pathName); else return null; } /** * Saves the currently set locale. */ public void saveDefaultImagePath(File imgPath) { try { if (imgPath != null) set(APP_CURRENT_IMAGE_PATH, imgPath.getCanonicalPath()); } catch (Exception e) { e.printStackTrace(); } }//saveDefaultImagePath(File) /** * Returns the default locale */ public Locale getDefaultLocale() { // language String strLocale = get(APP_LOCALE, null); if (strLocale != null) return Application.getLocale(strLocale); else return null; }//getDefaultLocale() /** * Saves the currently set locale. */ public void saveDefaultLocale(Locale locale) { // save locale (language) set(APP_LOCALE, locale.toString()); }//saveDefaultLocle(Locale) /** * Loads the names of the eight last used files from the preferences backing store. */ public void loadFileList() { // load last four files for (int i=Application.MAX_RECENT_FILES; i >= 1; i--) { File file = new File(get(APP_FILE_ + i, "")); //debug("loadFileList() called: "+file.toString()); Application.addToFileList(file); } }//loadFileList() /** * Saves the names of the four last used files. */ public void saveFileList() { String path; try { // save last four files for (int i=1; i <= Application.MAX_RECENT_FILES; i++) { File file = Application.getFromFileList(i-1); if (file != null){ path=file.getCanonicalPath(); //debug("saveFilelist(): "+path.toString()); set(APP_FILE_ + i, path); }else set(APP_FILE_ + i, ""); } //debug("list:");properties.list(System.out); } catch (Exception e) { e.printStackTrace(); } //If this is the last call to the pref system and is always done on exit //this should be enough: (??) storePreferences(); }//saveFileList() /** * Saves preferences by taking the application's current values. * Apparently no limit on property length! (# preferences: 8192), * so no need to split up in pieces :-) * But we have to convert byte[]--b64-->String */ public void saveXMLPreferences(Application app) { //debug("saveXMLPreferences(app):"); // preferences xml String xml = app.getPreferencesXML(); set(XML_USER_PREFERENCES, xml); if (!(app.is3D())) // TODO: implement it in Application3D! { String xmlDef = app.getKernel().getConstruction().getConstructionDefaults().getCDXML(); set(XML_DEFAULT_OBJECT_PREFERENCES, xmlDef); } byte[] macrofile =app.getMacroFileAsByteArray(); String macrostring =geogebra.util.Base64.encode(macrofile,0); set(TOOLS_FILE_GGT,macrostring); //just an idea, might be useful? set("b64",getB64(app)); //Force writing, "flush": //properties.list(System.out); storePreferences(); }//saveXMLPreferences(Application) /** * Loads XML preferences (empty construction with GUI and kernel settings) and sets application accordingly. * This method clears the current construction in the application. * Note: the XML string used is the same as for ggb files. */ public void loadXMLPreferences(Application app) { app.setWaitCursor(); // load this preferences xml file in application try { // load tools from ggt file (byte array) // Must convert String--b64-->byte String ggtString=get(TOOLS_FILE_GGT,ERROR); if(ggtString.equals(ERROR)){ debug("problem with getting GGT..."); }else{ byte [] ggtFile = geogebra.util.Base64.decode(ggtString); app.loadMacroFileFromByteArray(ggtFile, true); }//if error // load preferences xml initDefaultXML(app); //This might not have been called before! String xml = get(XML_USER_PREFERENCES, factoryDefaultXml); app.setXML(xml, true); if (xml.equals(factoryDefaultXml)) { // temporary solution, may there be an auto rightAngleStyle in the future app.updateRightAngleStyle(); } if (!(app.is3D())) // TODO: implement it in Application3D! { String xmlDef = get(XML_DEFAULT_OBJECT_PREFERENCES, factoryDefaultXml); if (!xmlDef.equals(factoryDefaultXml)) { boolean eda = app.getKernel().getElementDefaultAllowed(); app.getKernel().setElementDefaultAllowed(true); app.setXML(xmlDef, false); app.getKernel().setElementDefaultAllowed(eda); } } } catch (Exception e) { e.printStackTrace(); }//try-catch app.setDefaultCursor(); //debug("loadXMLPreferences() called");properties.list(System.out); }//loadXMLPreferences(Application) /** * Clears all user preferences. */ public void clearPreferences() { try { properties.clear(); //ggbPrefs.flush(); storePreferences(); } catch (Exception e) { Application.debug(e+""); } } /// --- Private --- /// // get/set with check private final String get(String key,String def){ if(properties!=null){ return properties.getProperty(key,def); }else{ return ERROR; }//if }//get() public final void set(String key,String val){ if(properties!=null){ properties.setProperty(key, val);} }//set() // --- SNIP --------------------------------------------------- //Just a thought: //b64=...