6868import java .util .List ;
6969import java .util .Vector ;
7070import java .util .WeakHashMap ;
71+ import java .util .Map ;
7172
7273import javax .swing .*;
7374import javax .swing .event .DocumentListener ;
8384
8485import edu .rice .cs .drjava .DrJava ;
8586import edu .rice .cs .drjava .DrJavaRoot ;
87+ import edu .rice .cs .drjava .config .Option ;
88+ import edu .rice .cs .drjava .config .OptionParser ;
8689import edu .rice .cs .drjava .config .OptionConstants ;
8790import edu .rice .cs .drjava .config .OptionEvent ;
8891import edu .rice .cs .drjava .config .OptionListener ;
@@ -391,6 +394,7 @@ public void setFileGroupingState(FileGroupingState state) {
391394 _notifier .projectRunnableChanged ();
392395 _notifier .projectBuildDirChanged ();
393396 _notifier .projectWorkDirChanged ();
397+
394398// _notifier.projectModified(); // not currently used
395399 }
396400
@@ -406,10 +410,11 @@ public void setFileGroupingState(FileGroupingState state) {
406410
407411 protected FileGroupingState
408412 makeProjectFileGroupingState (File pr , String main , File bd , File wd , File project , File [] srcFiles , File [] auxFiles ,
409- File [] excludedFiles , Iterable <AbsRelFile > cp , File cjf , int cjflags , boolean refresh , String manifest ) {
413+ File [] excludedFiles , Iterable <AbsRelFile > cp , File cjf , int cjflags , boolean refresh ,
414+ String manifest , Map <OptionParser ,String > storedPreferences ) {
410415
411416 return new ProjectFileGroupingState (pr , main , bd , wd , project , srcFiles , auxFiles , excludedFiles , cp , cjf , cjflags ,
412- refresh , manifest );
417+ refresh , manifest , storedPreferences );
413418 }
414419
415420 /** @return true if the class path state has been changed. */
@@ -530,6 +535,11 @@ public void setProjectRoot(File f) {
530535 /** @return the build directory for the project (assuming one exists). */
531536 public File getBuildDirectory () { return _state .getBuildDirectory (); }
532537
538+ /** @return the stored preferences. */
539+ public Map <OptionParser ,String > getPreferencesStoredInProject () { return _state .getPreferencesStoredInProject (); }
540+
541+ public void setPreferencesStoredInProject (Map <OptionParser ,String > sp ) { _state .setPreferencesStoredInProject (sp ); }
542+
533543 /** Sets the class with the project's main method. Degenerate version overridden in DefaultGlobalModel. */
534544 public void setBuildDirectory (File f ) {
535545 _state .setBuildDirectory (f );
@@ -598,6 +608,7 @@ class ProjectFileGroupingState implements FileGroupingState {
598608 volatile File _createJarFile ;
599609 volatile int _createJarFlags ;
600610 volatile boolean _autoRefreshStatus ;
611+ final Map <OptionParser ,String > _storedPreferences = new HashMap <OptionParser ,String >();
601612
602613 volatile String _manifest = null ;
603614
@@ -606,12 +617,17 @@ class ProjectFileGroupingState implements FileGroupingState {
606617 /** Degenerate constructor for a new project; only the file project name is known. */
607618 ProjectFileGroupingState (File project ) {
608619 this (project .getParentFile (), null , null , null , project , new File [0 ], new File [0 ], new File [0 ],
609- IterUtil .<AbsRelFile >empty (), null , 0 , false , null );
620+ IterUtil .<AbsRelFile >empty (), null , 0 , false , null , new HashMap <OptionParser ,String >());
621+ HashMap <OptionParser ,String > defaultStoredPreferences = new HashMap <OptionParser ,String >();
622+ // by default, put INDENT_LEVEL AND LANGUAGE_LEVEL into the project file
623+ defaultStoredPreferences .put (INDENT_LEVEL , DrJava .getConfig ().getOptionMap ().getString (INDENT_LEVEL ));
624+ defaultStoredPreferences .put (LANGUAGE_LEVEL , DrJava .getConfig ().getOptionMap ().getString (LANGUAGE_LEVEL ));
625+ setPreferencesStoredInProject (defaultStoredPreferences );
610626 }
611627
612628 ProjectFileGroupingState (File pr , String main , File bd , File wd , File project , File [] srcFiles , File [] auxFiles ,
613629 File [] excludedFiles , Iterable <AbsRelFile > cp , File cjf , int cjflags , boolean refreshStatus ,
614- String customManifest ) {
630+ String customManifest , Map < OptionParser , String > storedPreferences ) {
615631 _projRoot = pr ;
616632 _mainClass = main ;
617633 _buildDir = bd ;
@@ -633,6 +649,7 @@ class ProjectFileGroupingState implements FileGroupingState {
633649 _createJarFlags = cjflags ;
634650 _autoRefreshStatus = refreshStatus ;
635651 _manifest = customManifest ;
652+ setPreferencesStoredInProject (storedPreferences );
636653 }
637654
638655 public boolean isProjectActive () { return true ; }
@@ -820,6 +837,21 @@ public boolean isExcludedFile(File f) {
820837 public boolean getAutoRefreshStatus () { return _autoRefreshStatus ; }
821838 public void setAutoRefreshStatus (boolean status ) { _autoRefreshStatus = status ; }
822839
840+ /** @return the stored preferences. */
841+ public Map <OptionParser ,String > getPreferencesStoredInProject () {
842+ return new HashMap <OptionParser ,String >(_storedPreferences );
843+ }
844+
845+ public void setPreferencesStoredInProject (Map <OptionParser ,String > sp ) {
846+ // remove previous listeners
847+ removePreviousListeners ();
848+
849+ _storedPreferences .clear ();
850+ _storedPreferences .putAll (sp );
851+
852+ // add new listeners
853+ addNewListeners (sp );
854+ }
823855
824856 // This only starts the process. It is all done asynchronously.
825857 public void cleanBuildDirectory () {
@@ -923,6 +955,37 @@ public void setExtraClassPath(Iterable<AbsRelFile> cp) {
923955 public void setCustomManifest (String manifest ) { _manifest = manifest ; }
924956 }
925957
958+ @ SuppressWarnings ("unchecked" )
959+ protected void removePreviousListeners () {
960+ for (Map .Entry <OptionParser , OptionListener <?>> e : LISTENERS_TO_REMOVE .entrySet ()) {
961+ // all keys should be full Option instances, not just OptionParser instances
962+ if (e .getKey () instanceof Option ) {
963+ DrJava .getConfig ().removeOptionListener ((Option )e .getKey (), e .getValue ());
964+ }
965+ }
966+ LISTENERS_TO_REMOVE .clear ();
967+ }
968+
969+ @ SuppressWarnings ("unchecked" )
970+ protected void addNewListeners (Map <OptionParser ,String > newValues ) {
971+ for (OptionParser key : newValues .keySet ()) {
972+ // all keys should be full Option instances, not just OptionParser instances
973+ if (key instanceof Option ) {
974+ DrJava .getConfig ().addOptionListener ((Option )key , STORED_PREFERENCES_LISTENER );
975+ LISTENERS_TO_REMOVE .put (key , STORED_PREFERENCES_LISTENER );
976+ }
977+ }
978+ }
979+
980+ protected static final HashMap <OptionParser , OptionListener <? extends Object >> LISTENERS_TO_REMOVE =
981+ new HashMap <OptionParser , OptionListener <? extends Object >>();
982+
983+ public final OptionListener <? extends Object > STORED_PREFERENCES_LISTENER = new OptionListener <Object >() {
984+ public void optionChanged (OptionEvent <Object > oce ) {
985+ setProjectChanged (true );
986+ }
987+ };
988+
926989 protected FileGroupingState makeFlatFileGroupingState () { return new FlatFileGroupingState (); }
927990
928991 class FlatFileGroupingState implements FileGroupingState {
@@ -1007,7 +1070,9 @@ public void removeExcludedFile(File f) { }
10071070 public void setExcludedFiles (File [] fs ) { }
10081071 public boolean getAutoRefreshStatus () {return false ;}
10091072 public void setAutoRefreshStatus (boolean b ) { }
1010-
1073+ public void setPreferencesStoredInProject (Map <OptionParser ,String > sp ) { /* do nothing */ }
1074+ public Map <OptionParser ,String > getPreferencesStoredInProject () { return new HashMap <OptionParser ,String >(); }
1075+
10111076 public void cleanBuildDirectory () { }
10121077
10131078 public List <File > getClassFiles () { return new LinkedList <File >(); }
@@ -1592,6 +1657,7 @@ else if ( doc.isAuxiliaryFile()) {
15921657 * @param file where to save the project
15931658 * @param info
15941659 */
1660+ @ SuppressWarnings ("unchecked" )
15951661 public ProjectProfile _makeProjectProfile (File file , HashMap <OpenDefinitionsDocument , DocumentInfoGetter > info )
15961662 throws IOException {
15971663 ProjectProfile builder = new ProjectProfile (file );
@@ -1663,6 +1729,14 @@ else if (doc.isAuxiliaryFile()) {
16631729 //add custom manifest
16641730 builder .setCustomManifest (_state .getCustomManifest ());
16651731
1732+ // update preference values here
1733+ Map <OptionParser ,String > sp = _state .getPreferencesStoredInProject ();
1734+ for (OptionParser key : sp .keySet ()) {
1735+ sp .put (key , DrJava .getConfig ().getOptionMap ().getString (key ));
1736+ }
1737+ builder .setPreferencesStoredInProject (sp );
1738+ _state .setPreferencesStoredInProject (sp );
1739+
16661740 return builder ;
16671741 }
16681742
@@ -1693,7 +1767,9 @@ public void saveProject(File file, HashMap<OpenDefinitionsDocument, DocumentInfo
16931767 builder .getSourceFiles (), builder .getAuxiliaryFiles (),
16941768 builder .getExcludedFiles (),
16951769 builder .getClassPaths (), builder .getCreateJarFile (),
1696- builder .getCreateJarFlags (), builder .getAutoRefreshStatus (), builder .getCustomManifest ()));
1770+ builder .getCreateJarFlags (), builder .getAutoRefreshStatus (),
1771+ builder .getCustomManifest (),
1772+ builder .getPreferencesStoredInProject ()));
16971773 }
16981774
16991775 /** Writes the project profile in the old project format. Assumes DrJava is in project mode.
@@ -1715,7 +1791,9 @@ public void exportOldProject(File file, HashMap<OpenDefinitionsDocument,Document
17151791 builder .getSourceFiles (), builder .getAuxiliaryFiles (),
17161792 builder .getExcludedFiles (),
17171793 builder .getClassPaths (), builder .getCreateJarFile (),
1718- builder .getCreateJarFlags (), builder .getAutoRefreshStatus (), builder .getCustomManifest ()));
1794+ builder .getCreateJarFlags (), builder .getAutoRefreshStatus (),
1795+ builder .getCustomManifest (),
1796+ builder .getPreferencesStoredInProject ()));
17191797 }
17201798
17211799 public void reloadProject (File file , HashMap <OpenDefinitionsDocument , DocumentInfoGetter > info ) throws IOException {
@@ -1760,6 +1838,7 @@ private void _loadProject(final ProjectFileIR ir) throws IOException {
17601838 int createJarFlags = ir .getCreateJarFlags ();
17611839 final boolean autoRefresh = ir .getAutoRefreshStatus ();
17621840 final String manifest = ir .getCustomManifest ();
1841+ final Map <OptionParser ,String > storedPreferences = ir .getPreferencesStoredInProject ();
17631842
17641843 // clear browser, breakpoint, and bookmark histories
17651844
@@ -1808,7 +1887,7 @@ public boolean accept(OpenDefinitionsDocument d) {
18081887
18091888 setFileGroupingState (makeProjectFileGroupingState (projectRoot , mainClass , buildDir , workDir , projectFile , srcFiles ,
18101889 auxFiles , excludedFiles , projectClassPaths , createJarFile ,
1811- createJarFlags , autoRefresh , manifest ));
1890+ createJarFlags , autoRefresh , manifest , storedPreferences ));
18121891
18131892 resetInteractions (getWorkingDirectory ()); // Reset interactions pane in new working directory
18141893
@@ -1926,6 +2005,9 @@ public void closeProject(boolean suppressReset) {
19262005 makeListNavigator (getDocumentNavigator ()));
19272006 setFileGroupingState (makeFlatFileGroupingState ());
19282007
2008+ // remove previous listeners
2009+ removePreviousListeners ();
2010+
19292011 if (! suppressReset ) resetInteractions (getWorkingDirectory ());
19302012 _notifier .projectClosed ();
19312013 setActiveDocument (getDocumentNavigator ().getDocuments ().get (0 ));
0 commit comments