001: /*BEGIN_COPYRIGHT_BLOCK
002: *
003: * Copyright (c) 2001-2007, JavaPLT group at Rice University (javaplt@rice.edu)
004: * All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions are met:
008: * * Redistributions of source code must retain the above copyright
009: * notice, this list of conditions and the following disclaimer.
010: * * Redistributions in binary form must reproduce the above copyright
011: * notice, this list of conditions and the following disclaimer in the
012: * documentation and/or other materials provided with the distribution.
013: * * Neither the names of DrJava, the JavaPLT group, Rice University, nor the
014: * names of its contributors may be used to endorse or promote products
015: * derived from this software without specific prior written permission.
016: *
017: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
018: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
019: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
020: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
021: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
022: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
023: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
024: * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
025: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
026: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
027: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
028: *
029: * This software is Open Source Initiative approved Open Source Software.
030: * Open Source Initative Approved is a trademark of the Open Source Initiative.
031: *
032: * This file is part of DrJava. Download the current version of this project
033: * from http://www.drjava.org/ or http://sourceforge.net/projects/drjava/
034: *
035: * END_COPYRIGHT_BLOCK*/
036:
037: package edu.rice.cs.drjava.model;
038:
039: import java.io.File;
040: import java.io.Serializable;
041: import java.util.List;
042:
043: import edu.rice.cs.drjava.model.compiler.CompilerListener;
044: import edu.rice.cs.util.FileOpenSelector;
045: import edu.rice.cs.util.classloader.ClassFileError;
046: import edu.rice.cs.util.swing.AsyncTask;
047:
048: /** Keeps track of all listeners to the model, and has the ability to notify them of some event.
049: * <p>
050: * This class has a specific role of managing GlobalModelListeners. Other classes with similar names use similar
051: * code to perform the same function for other interfaces, e.g. InteractionsEventNotifier and JavadocEventNotifier.
052: * These classes implement the appropriate interface definition so that they can be used transparently as composite
053: * packaging for a particular listener interface.
054: * <p>
055: * Components which might otherwise manage their own list of listeners use EventNotifiers instead to simplify their
056: * internal implementation. Notifiers should therefore be considered a private implementation detail of the
057: * components, and should not be used directly outside of the "host" component.
058: * <p>
059: * TODO: remove direct references to GlobalEventNotifier outside of DefaultGlobalModel
060: * TODO: remove public modifier from this class when above has happened
061: *
062: * All methods in this class must use the synchronization methods provided by ReaderWriterLock. This ensures that
063: * multiple notifications (reads) can occur simultaneously, but only one thread can be adding or removing listeners
064: * (writing) at a time, and no reads can occur during a write.
065: * <p>
066: * <i>No</i> methods on this class should be synchronized using traditional Java synchronization!
067: * <p>
068: * @version $Id: GlobalEventNotifier.java 4255 2007-08-28 19:17:37Z mgricken $
069: */
070: public class GlobalEventNotifier extends
071: EventNotifier<GlobalModelListener> implements
072: GlobalModelListener, Serializable {
073:
074: public <P, R> void executeAsyncTask(AsyncTask<P, R> task, P param,
075: boolean showProgress, boolean lockUI) {
076: _lock.startRead();
077: try {
078: for (GlobalModelListener l : _listeners) {
079: l.executeAsyncTask(task, param, showProgress, lockUI);
080: }
081: } finally {
082: _lock.endRead();
083: }
084: }
085:
086: public void filesNotFound(File... f) {
087: _lock.startRead();
088: try {
089: for (GlobalModelListener l : _listeners) {
090: l.filesNotFound(f);
091: }
092: } finally {
093: _lock.endRead();
094: }
095: }
096:
097: /**
098: * Performs any UI related steps to handle the case in which a file is being opened that
099: * is already open and modified. The two choices are to revert to the copy on disk, or to
100: * keep the current changes.
101: * @param doc {@code true} if the user wishes to revert the document, {@code false} to ignore
102: */
103: public void handleAlreadyOpenDocument(OpenDefinitionsDocument doc) {
104: _lock.startRead();
105: try {
106: for (GlobalModelListener l : _listeners) {
107: l.handleAlreadyOpenDocument(doc);
108: }
109: } finally {
110: _lock.endRead();
111: }
112: }
113:
114: /* -------------- project state ------------------*/
115: public void projectOpened(File pfile, FileOpenSelector files) {
116: _lock.startRead();
117: try {
118: for (GlobalModelListener l : _listeners) {
119: l.projectOpened(pfile, files);
120: }
121: } finally {
122: _lock.endRead();
123: }
124: }
125:
126: public void projectClosed() {
127: _lock.startRead();
128: try {
129: for (GlobalModelListener l : _listeners) {
130: l.projectClosed();
131: }
132: } finally {
133: _lock.endRead();
134: }
135: }
136:
137: public void projectModified() {
138: _lock.startRead();
139: try {
140: for (GlobalModelListener l : _listeners) {
141: l.projectModified();
142: }
143: } finally {
144: _lock.endRead();
145: }
146: }
147:
148: public void projectBuildDirChanged() {
149: _lock.startRead();
150: try {
151: for (GlobalModelListener l : _listeners) {
152: l.projectBuildDirChanged();
153: }
154: } finally {
155: _lock.endRead();
156: }
157: }
158:
159: public void projectWorkDirChanged() {
160: _lock.startRead();
161: try {
162: for (GlobalModelListener l : _listeners) {
163: l.projectWorkDirChanged();
164: }
165: } finally {
166: _lock.endRead();
167: }
168: }
169:
170: public void projectRunnableChanged() {
171: _lock.startRead();
172: try {
173: for (GlobalModelListener l : _listeners) {
174: l.projectRunnableChanged();
175: }
176: } finally {
177: _lock.endRead();
178: }
179: }
180:
181: /* ---------- Deprecated Methods ---------- */
182:
183: /** Lets the listeners know some event has taken place.
184: * @param n tells the listener what happened.
185: */
186: public void notifyListeners(Notifier n) {
187: _lock.startRead();
188: try {
189: for (GlobalModelListener l : _listeners) {
190: n.notifyListener(l);
191: }
192: } finally {
193: _lock.endRead();
194: }
195: }
196:
197: /** Allows the GlobalModel to ask its listeners a yes/no question and receive a response.
198: * @param p the question being asked of the listeners
199: * @return the listeners' responses ANDed together, true if they all
200: * agree, false if some disagree
201: * @deprecated Use listener methods directly instead.
202: */
203: @Deprecated
204: public boolean pollListeners(Poller p) {
205: _lock.startRead();
206: try {
207: for (GlobalModelListener l : _listeners) {
208: if (!p.poll(l))
209: return false;
210: }
211: return true;
212: } finally {
213: _lock.endRead();
214: }
215: }
216:
217: /**
218: * Class model for notifying listeners of an event.
219: * @deprecated Use listener methods directly instead.
220: */
221: @Deprecated
222: public abstract static class Notifier {
223: public abstract void notifyListener(GlobalModelListener l);
224: }
225:
226: /**
227: * Class model for asking listeners a yes/no question.
228: * @deprecated Use listener methods directly instead.
229: */
230: @Deprecated
231: public abstract static class Poller {
232: public abstract boolean poll(GlobalModelListener l);
233: }
234:
235: // ---------- End of Deprecated Methods ----------
236:
237: //------------------------------ GlobalModel -------------------------------//
238:
239: /** Called when a file's main method is about to be run. */
240: public void runStarted(OpenDefinitionsDocument doc) {
241: _lock.startRead();
242: try {
243: for (GlobalModelListener l : _listeners) {
244: l.runStarted(doc);
245: }
246: } finally {
247: _lock.endRead();
248: }
249: }
250:
251: /** Called after a new document is created. */
252: public void newFileCreated(OpenDefinitionsDocument doc) {
253: _lock.startRead();
254: try {
255: for (GlobalModelListener l : _listeners) {
256: l.newFileCreated(doc);
257: }
258: } finally {
259: _lock.endRead();
260: }
261: }
262:
263: /** Called when the console window is reset. */
264: public void consoleReset() {
265: _lock.startRead();
266: try {
267: for (GlobalModelListener l : _listeners) {
268: l.consoleReset();
269: }
270: } finally {
271: _lock.endRead();
272: }
273: }
274:
275: /** Called after the current document is saved. */
276: public void fileSaved(OpenDefinitionsDocument doc) {
277: // ScrollableDialog sd = new ScrollableDialog(null, "fileSaved(" + doc + ") called in GlobalEventNotifier.java", "", "");
278: // sd.show();
279: _lock.startRead();
280: try {
281: for (GlobalModelListener l : _listeners) {
282: l.fileSaved(doc);
283: }
284: } finally {
285: _lock.endRead();
286: }
287: }
288:
289: /** Called after a file is opened and read into the current document. */
290: public void fileOpened(OpenDefinitionsDocument doc) {
291: _lock.startRead();
292: try {
293: for (GlobalModelListener l : _listeners) {
294: l.fileOpened(doc);
295: }
296: } finally {
297: _lock.endRead();
298: }
299: }
300:
301: /** Called after a document is closed. */
302: public void fileClosed(OpenDefinitionsDocument doc) {
303: _lock.startRead();
304: try {
305: for (GlobalModelListener l : _listeners) {
306: l.fileClosed(doc);
307: }
308: } finally {
309: _lock.endRead();
310: }
311: }
312:
313: /** Called after a document is reverted. */
314: public void fileReverted(OpenDefinitionsDocument doc) {
315: _lock.startRead();
316: try {
317: for (GlobalModelListener l : _listeners) {
318: l.fileReverted(doc);
319: }
320: } finally {
321: _lock.endRead();
322: }
323: }
324:
325: /** Called when an undoable edit occurs. */
326: public void undoableEditHappened() {
327: _lock.startRead();
328: try {
329: for (GlobalModelListener l : _listeners) {
330: l.undoableEditHappened();
331: }
332: } finally {
333: _lock.endRead();
334: }
335: }
336:
337: /** Called to ask the listeners if it is OK to abandon the current document. */
338: public boolean canAbandonFile(OpenDefinitionsDocument doc) {
339: _lock.startRead();
340: try {
341: for (GlobalModelListener l : _listeners) {
342: if (!l.canAbandonFile(doc))
343: return false;
344: }
345: return true;
346: } finally {
347: _lock.endRead();
348: }
349: }
350:
351: /** Called to ask the listeners save the file before quitting at the user's option.
352: * @return true if quitting should continue, false if the user cancelled */
353: public boolean quitFile(OpenDefinitionsDocument doc) {
354: _lock.startRead();
355: try {
356: // if one of the listeners returns false (=user cancelled), abort
357: for (GlobalModelListener l : _listeners) {
358: if (!l.quitFile(doc))
359: return false;
360: }
361: } finally {
362: _lock.endRead();
363: }
364: return true;
365: }
366:
367: /** Called to ask the listeners if it is OK to revert the current document to the version saved on disk. */
368: public boolean shouldRevertFile(OpenDefinitionsDocument doc) {
369: _lock.startRead();
370: try {
371: for (GlobalModelListener l : _listeners) {
372: if (!l.shouldRevertFile(doc))
373: return false;
374: }
375: return true;
376: } finally {
377: _lock.endRead();
378: }
379: }
380:
381: /** Called when the selection in the navigator changes the current directory without changing the active document. */
382: public void currentDirectoryChanged(File dir) {
383: _lock.startRead();
384: try {
385: for (GlobalModelListener l : _listeners) {
386: l.currentDirectoryChanged(dir);
387: }
388: } finally {
389: _lock.endRead();
390: }
391: }
392:
393: /** Called when the selection in the navigator changes the active document. */
394: public void activeDocumentChanged(OpenDefinitionsDocument active) {
395: _lock.startRead();
396: try {
397: for (GlobalModelListener l : _listeners) {
398: l.activeDocumentChanged(active);
399: }
400: } finally {
401: _lock.endRead();
402: }
403: }
404:
405: /** Called when the active document is refreshed. */
406: public void activeDocumentRefreshed(OpenDefinitionsDocument active) {
407: _lock.startRead();
408: try {
409: for (GlobalModelListener l : _listeners) {
410: l.activeDocumentRefreshed(active);
411: }
412: } finally {
413: _lock.endRead();
414: }
415: }
416:
417: /** Called to shift the focus to the Definitions Pane. */
418: public void focusOnDefinitionsPane() {
419: _lock.startRead();
420: try {
421: for (GlobalModelListener l : _listeners) {
422: l.focusOnDefinitionsPane();
423: }
424: } finally {
425: _lock.endRead();
426: }
427: }
428:
429: /** Called to shift the focus to the last focus owner among the main frame panes. */
430: public void focusOnLastFocusOwner() {
431: _lock.startRead();
432: try {
433: for (GlobalModelListener l : _listeners) {
434: l.focusOnLastFocusOwner();
435: }
436: } finally {
437: _lock.endRead();
438: }
439: }
440:
441: // /** Called to demand that all files be saved before running the main method of a document. It is up to the caller
442: // * of this method to check if the documents have been saved, using IGetDocuments.hasModifiedDocuments(). This is
443: // * nor used currently, but it is commented out in case it is needed later. */
444: // public void saveBeforeRun() {
445: // _lock.startRead();
446: // try { for (GlobalModelListener l : _listeners) { l.saveBeforeRun(); } }
447: // finally { _lock.endRead(); }
448: // }
449:
450: //------------------------------ Interactions ------------------------------//
451:
452: /** Called after an interaction is started by the GlobalModel. */
453: public void interactionStarted() {
454: _lock.startRead();
455: try {
456: for (GlobalModelListener l : _listeners) {
457: l.interactionStarted();
458: }
459: } finally {
460: _lock.endRead();
461: }
462: }
463:
464: /** Called when an interaction has finished running. */
465: public void interactionEnded() {
466: _lock.startRead();
467: try {
468: for (GlobalModelListener l : _listeners) {
469: l.interactionEnded();
470: }
471: } finally {
472: _lock.endRead();
473: }
474: }
475:
476: /** Called when the interactions window generates a syntax error.
477: * @param offset the error's offset into the InteractionsDocument.
478: * @param length the length of the error.
479: */
480: public void interactionErrorOccurred(int offset, int length) {
481: _lock.startRead();
482: try {
483: for (GlobalModelListener l : _listeners) {
484: l.interactionErrorOccurred(offset, length);
485: }
486: } finally {
487: _lock.endRead();
488: }
489: }
490:
491: /** Called when the interactionsJVM has begun resetting. */
492: public void interpreterResetting() {
493: _lock.startRead();
494: try {
495: for (GlobalModelListener l : _listeners) {
496: l.interpreterResetting();
497: }
498: } finally {
499: _lock.endRead();
500: }
501: }
502:
503: /** Called when the interactions window is reset. */
504: public void interpreterReady(File wd) {
505: _lock.startRead();
506: try {
507: for (GlobalModelListener l : _listeners) {
508: l.interpreterReady(wd);
509: }
510: } finally {
511: _lock.endRead();
512: }
513: }
514:
515: /** Called if the interpreter reset failed.
516: * @param t Throwable explaining why the reset failed.
517: * (Subclasses must maintain listeners.)
518: */
519: public void interpreterResetFailed(final Throwable t) {
520: _lock.startRead();
521: try {
522: for (GlobalModelListener l : _listeners) {
523: l.interpreterResetFailed(t);
524: }
525: } finally {
526: _lock.endRead();
527: }
528: }
529:
530: /** Called when the interactions JVM was closed by System.exit or by being aborted. Immediately after this the
531: * interactions will be reset.
532: * @param status the exit code
533: */
534: public void interpreterExited(int status) {
535: _lock.startRead();
536: try {
537: for (GlobalModelListener l : _listeners) {
538: l.interpreterExited(status);
539: }
540: } finally {
541: _lock.endRead();
542: }
543: }
544:
545: /** Called when the active interpreter is changed.
546: * @param inProgress Whether the new interpreter is processing an interaction (i.e,. whether an interactionEnded
547: * event will be fired)
548: */
549: public void interpreterChanged(boolean inProgress) {
550: _lock.startRead();
551: try {
552: for (GlobalModelListener l : _listeners) {
553: l.interpreterChanged(inProgress);
554: }
555: } finally {
556: _lock.endRead();
557: }
558: }
559:
560: //-------------------------------- Compiler --------------------------------//
561:
562: /** Called after a compile is started by the GlobalModel. */
563: public void compileStarted() {
564: _lock.startRead();
565: try {
566: for (GlobalModelListener l : _listeners) {
567: l.compileStarted();
568: }
569: } finally {
570: _lock.endRead();
571: }
572: }
573:
574: /** Called when a compile has finished running. */
575: public void compileEnded(File workDir,
576: List<? extends File> excludedFiles) {
577: _lock.startRead();
578: try {
579: for (GlobalModelListener l : _listeners) {
580: l.compileEnded(workDir, excludedFiles);
581: }
582: } finally {
583: _lock.endRead();
584: }
585: }
586:
587: /** Called to demand that all files be saved before compiling. It is up to the caller of this method to check
588: * if the documents have been saved, using IGetDocuments.hasModifiedDocuments().
589: */
590: public void saveBeforeCompile() {
591: _lock.startRead();
592: try {
593: for (GlobalModelListener l : _listeners) {
594: l.saveBeforeCompile();
595: }
596: } finally {
597: _lock.endRead();
598: }
599: }
600:
601: /** Called to demand that the active document, which is untitled, is saved before compiling. */
602: public void saveUntitled() {
603: _lock.startRead();
604: try {
605: for (GlobalModelListener l : _listeners) {
606: l.saveUntitled();
607: }
608: } finally {
609: _lock.endRead();
610: }
611: }
612:
613: //---------------------------------- JUnit ---------------------------------//
614:
615: /** Called when trying to test a non-TestCase class.
616: * @param isTestAll whether or not it was a use of the test all button
617: */
618: public void nonTestCase(boolean isTestAll) {
619: _lock.startRead();
620: try {
621: for (GlobalModelListener l : _listeners) {
622: l.nonTestCase(isTestAll);
623: }
624: } finally {
625: _lock.endRead();
626: }
627: }
628:
629: /** Called when trying to test an illegal class file.
630: * @param e the ClassFileError thrown when DrJava attempted to load the offending file
631: */
632: public void classFileError(ClassFileError e) {
633: _lock.startRead();
634: try {
635: for (GlobalModelListener l : _listeners) {
636: l.classFileError(e);
637: }
638: } finally {
639: _lock.endRead();
640: }
641: }
642:
643: /** Called before attempting unit testing if tested class files are out of sync, to give the user a chance to save. Do
644: * not continue with JUnit if the user doesn't recompile!
645: */
646: public void compileBeforeJUnit(final CompilerListener cl) {
647: // Utilities.show("compileBeforeJUnit invoked with argument " + cl + " in GlobalEventNotifier " + this);
648: _lock.startRead();
649: try {
650: for (GlobalModelListener l : _listeners) {
651: l.compileBeforeJUnit(cl);
652: }
653: } finally {
654: _lock.endRead();
655: }
656: }
657:
658: /** Called after JUnit is started by the GlobalModel. */
659: public void junitStarted() {
660: _lock.startRead();
661: try {
662: for (GlobalModelListener l : _listeners) {
663: l.junitStarted();
664: }
665: } finally {
666: _lock.endRead();
667: }
668: }
669:
670: /** Called when testing specific list of classes. */
671: public void junitClassesStarted() {
672: _lock.startRead();
673: try {
674: for (GlobalModelListener l : _listeners) {
675: l.junitClassesStarted();
676: }
677: } finally {
678: _lock.endRead();
679: }
680: }
681:
682: /** Called to indicate that a suite of tests has started running.
683: * @param numTests The number of tests in the suite to be run.
684: */
685: public void junitSuiteStarted(int numTests) {
686: _lock.startRead();
687: try {
688: for (GlobalModelListener l : _listeners) {
689: l.junitSuiteStarted(numTests);
690: }
691: } finally {
692: _lock.endRead();
693: }
694: }
695:
696: /** Called when a particular test is started.
697: * @param name The name of the test being started.
698: */
699: public void junitTestStarted(String name) {
700: _lock.startRead();
701: try {
702: for (GlobalModelListener l : _listeners) {
703: l.junitTestStarted(name);
704: }
705: } finally {
706: _lock.endRead();
707: }
708: }
709:
710: /** Called when a particular test has ended.
711: * @param name the name of the test that has ended
712: * @param wasSuccessful whether the test passed or not
713: * @param causedError if not successful, whether the test caused an error or simply failed
714: */
715: public void junitTestEnded(String name, boolean wasSuccessful,
716: boolean causedError) {
717: _lock.startRead();
718: try {
719: for (GlobalModelListener l : _listeners) {
720: l.junitTestEnded(name, wasSuccessful, causedError);
721: }
722: } finally {
723: _lock.endRead();
724: }
725: }
726:
727: /** Called after JUnit is finished running tests. */
728: public void junitEnded() {
729: _lock.startRead();
730: try {
731: for (GlobalModelListener l : _listeners) {
732: l.junitEnded();
733: }
734: } finally {
735: _lock.endRead();
736: }
737: }
738:
739: // /** Called to demand that all files be saved before running JUnit tests. It is up to the caller of this
740: // * method to check if the documents have been saved, using IGetDocuments.hasModifiedDocuments(). This is
741: // * never called currently, but it is commented out in case it is needed later. */
742: // public void saveBeforeJUnit() {
743: // _lock.startRead();
744: // try {
745: // for (GlobalModelListener l : _listeners) {
746: // l.saveBeforeJUnit();
747: // }
748: // }
749: // finally {
750: // _lock.endRead();
751: // }
752: // }
753:
754: //--------------------------------- Javadoc --------------------------------//
755:
756: /** Called after Javadoc is started by the GlobalModel. */
757: public void javadocStarted() {
758: _lock.startRead();
759: try {
760: for (GlobalModelListener l : _listeners) {
761: l.javadocStarted();
762: }
763: } finally {
764: _lock.endRead();
765: }
766: }
767:
768: /** Called after Javadoc is finished.
769: * @param success whether the Javadoc operation generated proper output
770: * @param destDir if (success) the location where the output was generated, otherwise undefined (possibly null)
771: * @param allDocs Whether Javadoc was run for all open documents
772: */
773: public void javadocEnded(boolean success, File destDir,
774: boolean allDocs) {
775: _lock.startRead();
776: try {
777: for (GlobalModelListener l : _listeners) {
778: l.javadocEnded(success, destDir, allDocs);
779: }
780: } finally {
781: _lock.endRead();
782: }
783: }
784:
785: /** Called before attempting Javadoc, to give the user a chance to save. Do not continue with Javadoc if the user
786: * doesn't save!
787: */
788: public void saveBeforeJavadoc() {
789: _lock.startRead();
790: try {
791: for (GlobalModelListener l : _listeners) {
792: l.saveBeforeJavadoc();
793: }
794: } finally {
795: _lock.endRead();
796: }
797: }
798:
799: // /** Called to demand that all files be saved before starting the debugger. It is up to the caller of this method
800: // * to check if the documents have been saved, using IGetDocuments.hasModifiedDocuments(). This is not used
801: // * currently, but it is commented out in case it is needed later. */
802: // public void saveBeforeDebug() {
803: // _lock.startRead();
804: // try { for (GlobalModelListener l : _listeners) { l.saveBeforeDebug(); } }
805: // finally { _lock.endRead(); }
806: // }
807:
808: /** Notifies the view that the current interaction is incomplete. */
809: public void interactionIncomplete() {
810: _lock.startRead();
811: try {
812: for (GlobalModelListener l : _listeners) {
813: l.interactionIncomplete();
814: }
815: } finally {
816: _lock.endRead();
817: }
818: }
819:
820: public void slaveJVMUsed() {
821: _lock.startRead();
822: try {
823: for (GlobalModelListener l : _listeners) {
824: l.slaveJVMUsed();
825: }
826: } finally {
827: _lock.endRead();
828: }
829: }
830:
831: /** Notifies the view that the current file path contains a #. */
832: public void filePathContainsPound() {
833: _lock.startRead();
834: try {
835: for (GlobalModelListener l : _listeners) {
836: l.filePathContainsPound();
837: }
838: } finally {
839: _lock.endRead();
840: }
841: }
842:
843: // ----- Cache -----
844: public void documentNotFound(OpenDefinitionsDocument d, File f) {
845: _lock.startRead();
846: try {
847: for (GlobalModelListener l : _listeners) {
848: l.documentNotFound(d, f);
849: }
850: } finally {
851: _lock.endRead();
852: }
853: }
854: }
|