logger.logMessage(ConsoleLogger.WARNING, "No source file for class " + srcLine.getClassName());
logger.logMessage(Logger.WARNING, "No source file for class " + srcLine.getClassName());
	private boolean viewSource(Project project, AnalysisRun analysisRun, final SourceLineAnnotation srcLine)	throws IOException {		// Get rid of old source code text		sourceTextArea.setText("");				// There is nothing to do without a source annotation		// TODO: actually, might want to put a message in the source window		// explaining that we don't have the source file, and that		// they might want to recompile with debugging info turned on.		if (srcLine == null)			return false;				// Look up the source file for this class.		sourceFinder.setSourceBaseList(project.getSourceDirList());		String sourceFile = srcLine.getSourceFile();		if (sourceFile == null || sourceFile.equals("<Unknown>")) {			logger.logMessage(ConsoleLogger.WARNING, "No source file for class " + srcLine.getClassName());			return false;		}				// Try to open the source file and display its contents		// in the source text area.		InputStream in = sourceFinder.openSource(srcLine.getPackageName(), sourceFile);		BufferedReader reader = null;				try {			reader = new BufferedReader(new InputStreamReader(in));						String line;			while ((line = reader.readLine()) != null) {				// TODO: evaluate whether this is inefficient				sourceTextArea.append(line + "\n");			}		} finally {			if (reader != null)				reader.close();		}				if (srcLine.isUnknown()) {			// No line number information, so can't highlight anything			SwingUtilities.invokeLater(new Runnable() {				public void run() {					sourceTextAreaScrollPane.getViewport().setViewPosition(new Point(0, 0));				}			});			return true;		}				// Highlight the annotation.		// There seems to be some bug in Swing that sometimes prevents this code		// from working when executed immediately after populating the		// text in the text area.  My guess is that when a large amount of text		// is added, Swing defers some UI update work until "later" that is needed		// to compute the visibility of text in the text area.		// So, post some code to do the update to the Swing event queue.		// Not really an ideal solution, but it seems to work.		SwingUtilities.invokeLater(new Runnable() {			public void run() {				// Highlight the lines from the source annotation.				// Note that the source lines start at 1, while the line numbers				// in the text area start at 0.				try {					int startLine = srcLine.getStartLine() - 1;					int endLine = srcLine.getEndLine();										// Compute number of rows visible.					// What a colossal pain in the ass this is.					// You'd think there would be a convenient method to					// return this information, but no.					JViewport viewport = sourceTextAreaScrollPane.getViewport();					Rectangle viewportRect = viewport.getViewRect();					int topRow = sourceTextArea.getLineOfOffset(sourceTextArea.viewToModel(viewportRect.getLocation()));					int bottomRow = sourceTextArea.getLineOfOffset(sourceTextArea.viewToModel(new Point(viewportRect.x, (viewportRect.y + viewportRect.height) - 1)));					int numRowsVisible = bottomRow - topRow;										// Scroll the window so the beginning of the					// annotation text will be (approximately) centered.					int viewLine = Math.max(startLine - (numRowsVisible > 0 ? numRowsVisible / 2 : 0), 0);					int viewBegin = sourceTextArea.getLineStartOffset(viewLine);					Rectangle viewRect = sourceTextArea.modelToView(viewBegin);					viewport.setViewPosition(new Point(viewRect.x, viewRect.y));										// Select (and highlight) the annotation.					int selBegin = sourceTextArea.getLineStartOffset(startLine);					int selEnd = sourceTextArea.getLineStartOffset(endLine);					sourceTextArea.select(selBegin, selEnd);					sourceTextArea.getCaret().setSelectionVisible(true);				} catch (javax.swing.text.BadLocationException e) {					logger.logMessage(ConsoleLogger.ERROR, e.toString());				}			}		});				return true;	}