📄 abstractmainview.java
字号:
*
* @param title The name of the document to display.
* @param component The component to add (usually an RTextScrollPane).
* @param fileFullPath The full path to the file being displayed by the
* component.
*/
public abstract void addDocument(String title, Component component,
String fileFullPath);
/*****************************************************************************/
/**
* Adds an empty text file to this tabbed pane. This method is
* synchronized so it doesn't interfere with the thread checking for files
* being modified outside of the editor.
*
* @param fileNameAndPath The full path and name of the file to add.
*/
private void addNewEmptyTextFile(String fileNameAndPath) {
addNewEmptyTextFile(fileNameAndPath,
RTextFileChooser.getDefaultEncoding());
}
/*****************************************************************************/
/**
* Adds an empty text file to this tabbed pane. This method is
* synchronized so it doesn't interfere with the thread checking for files
* being modified outside of the editor.
*
* @param fileNameAndPath The full path and name of the file to add.
* @param encoding The encoding in which the file is to be saved. If an
* invalid value is passed in, <code>US-ASCII</code> is
* used.
*/
private synchronized void addNewEmptyTextFile(String fileNameAndPath,
String encoding) {
// Ensure the encoding is a proper value.
if (encoding == null) {
encoding = RTextFileChooser.getDefaultEncoding();
// Actually create the file on disk.
}
if (!fileNameAndPath.equals(getDefaultFileName())) {
try {
new File(fileNameAndPath).createNewFile();
}
catch (IOException ioe) {
ResourceBundle msg = owner.getResourceBundle();
JOptionPane.showMessageDialog(this,
msg.getString("ErrorWritingFile"),
msg.getString("ErrorDialogTitle"),
JOptionPane.ERROR_MESSAGE);
}
}
// Set pointers for easy reference to new document.
int syntaxStyle = syntaxFilters.getSyntaxStyleForFile(fileNameAndPath);
currentTextArea = createRTextEditorPane(fileNameAndPath,
syntaxStyle, encoding);
// Add new text file to tabbed pane.
RTextScrollPane scrollPane = new RTextScrollPane(500, 400,
currentTextArea, lineNumbersEnabled, null);
addDocument(currentTextArea.getFileName(), scrollPane,
currentTextArea.getFileFullPath());
// Let anybody who cares know we've opened this file.
firePropertyChange(NEW_FILE_ADDED_PROPERTY, null,
currentTextArea.getFileFullPath());
}
/*****************************************************************************/
/**
* Adds an empty text file with a default name to this panel. This method
* is synchronized so it doesn't interfere with the thread checking for
* files being modified outside of the editor.
*/
public synchronized void addNewEmptyUntitledTextFile() {
addNewEmptyTextFile(getDefaultFileName());
}
/*****************************************************************************/
/**
* Adds an already-created text file to this tabbed pane. This method is
* synchronized so it doesn't interfere with the thread checking for files
* being modified outside of the editor.
*
* @param fileNameAndPath The full path and name of the file to add.
* @param charSet The encoding to use when reading/writing this file.
* @throws FileNotFoundException If the file does not exist and the user
* chooses not to create a new file.
* @throws InvalidCharSetException If the specified character set is
* invalid.
*/
public void addOldTextFile(String fileNameAndPath, String charSet) throws
FileNotFoundException {
// Ensure the encoding is a proper value.
if (charSet == null) {
charSet = RTextFileChooser.getDefaultEncoding();
}
ResourceBundle msg = owner.getResourceBundle();
// If the only document open is untitled and empty, remove
// (and thus replace) replace it.
if (getNumDocuments() == 1 &&
currentTextArea.getFileName().equals(owner.getNewFileName()) &&
currentTextArea.getText().equals("") &&
currentTextArea.isModified() == false) {
removeComponentAt(0);
}
// The file we want to open.
File check = new File(fileNameAndPath);
// If we're on Windows, convert the filename to a canonical path;
// this is because, since Windows is case-insensitive, RText used
// to open the same file twice and not recognize it as the same file
// if the user uses different case to open them (e.g., "c:\file.txt"
// and "C:\file.txt" were seen as different files). So, to fix
// this, we will always use the canonical path case on Windows.
if (owner.getOS() == RText.OS_WINDOWS) {
try {
fileNameAndPath = check.getCanonicalPath();
}
catch (IOException ioe) {
ioe.printStackTrace();
/* This can fail, for example, when the user enters:
"*.class"
(double-quotes included) for the file name - since '*' is
an invalid filename character.
*/
/* Oh well... */
}
}
// If check is a regular file AND exists...
if (check.isFile()) {
BufferedReader in = null;
try {
// NOTE: We COULD auto-detect Unicode status here, but
// the charSet comes from the file chooser, which auto-
// detects itself. So, unless the user changes it, we
// should be okay here.
//in = new BufferedReader(new org.fife.UnicodeReader(...
if (charSet != null) {
// Workaround for Java Bug ID 4508058 -
// InputStreamReader does not recognize a BOM in a
// UTF-8 encoded file. Some editors, such as Windows
// Notepad, insert a BOM into UTF-8 files (which is OK
// by the standard). So, if charSet is UTF-8, we'll
// use a homebrew "UnicodeReader" to ensure that UTF-8
// is used whether or not the BOM exists. This Java
// bug is still not fixed as of 1.5.
// FIXME: Take me out when Java Bug 4508058 is fixed.
if ( (charSet.equals("UTF-8") ||
charSet.equals("UTF8"))) {
in = new BufferedReader(new UnicodeReader(check,
charSet));
}
else {
// Another workaround as it appears that UTF-16LE and
// UTF16-BE encodings in Java don't read the BOM, when
// they decode (it's included in the stream itself).
// So, we'll just use UTF-16 (which reads the BOM
// correctly) for the load.
String tempCS = charSet;
if (charSet.indexOf("UTF-16") > -1 ||
charSet.indexOf("UTF16") > -1) {
tempCS = "UTF-16"; // Auto-detects encoding.
}
in = new BufferedReader(new InputStreamReader(
new FileInputStream(check), tempCS));
}
} // End of if (charSet!=null).
}
catch (Exception e) {
// IOException, etc.
owner.displayException(e);
}
int syntaxStyle = syntaxFilters.getSyntaxStyleForFile(fileNameAndPath);
RTextEditorPane tempTextArea = createRTextEditorPane(
fileNameAndPath, syntaxStyle, charSet);
try {
tempTextArea.read(in, null);
in.close();
}
catch (IOException ioe) {
JOptionPane.showMessageDialog(owner,
msg.getString("ErrorReadingFile") + ioe,
msg.getString("ErrorDialogTitle"),
JOptionPane.ERROR_MESSAGE);
}
catch (OutOfMemoryError oome) {
JOptionPane.showMessageDialog(owner,
msg.getString("ErrorOutOfMemoryMessage") +
oome,
msg.getString("ErrorDialogTitle"),
JOptionPane.ERROR_MESSAGE);
}
// This is needed because the text area's undoManager picked up
// the read() call above and added it as an insertion edit. We
// don't want the user to be able to undo this, however.
tempTextArea.discardAllEdits();
// Add the new document into our tabbed pane.
// This sets currentTextArea==tempTextArea.
RTextScrollPane scrollPane = new RTextScrollPane(500, 400,
tempTextArea, lineNumbersEnabled, null);
addDocument(tempTextArea.getFileName(), scrollPane,
tempTextArea.getFileFullPath());
tempTextArea = null;
// REMEMBER: currentTextArea has just been updated by
// addDocument() above!!
// Let anybody who cares know we've opened this file.
firePropertyChange(OLD_FILE_ADDED_PROPERTY, null,
currentTextArea.getFileFullPath());
} // End of if (check.isFile()).
// If the file 'check' doesn't exist...
else {
String temp = RTextUtilities.getRegularExpressionForLine(fileNameAndPath, true);
if (temp != null) {
temp = msg.getString("FileNECreateItMsg").replaceFirst("%file%", temp);
}
else {
temp = msg.getString("FileNECreateItMsg"); // Just leave the %file% in there.
}
if (JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(this, temp,
msg.getString("ConfDialogTitle"), JOptionPane.YES_NO_OPTION)) {
addNewEmptyTextFile(fileNameAndPath, owner.getFileChooser().getEncoding());
}
else if (getNumDocuments() == 0) { // Here, they MUST have hit the "No" button above.
addNewEmptyUntitledTextFile();
}
else {
throw new FileNotFoundException("File not found: " + fileNameAndPath);
}
}
}
/*****************************************************************************/
/**
* Returns whether or not tabs are emulated with spaces.
*
* @return <code>true</code> iff tabs are emulated with spaces.
*/
public boolean areTabsEmulated() {
return emulateTabsWithWhitespace;
}
/*****************************************************************************/
/**
* Checks the "modified" timestamps for open files against the last known
* "modified" timestamps to see if any files have been modified outside of
* this RText instance. This method is synchronized so that it isn't
* called while the user is loading or saving a file.
*/
public synchronized void checkFilesForOutsideModification() {
// If we're currently not waiting on the user to decide about a
// previous "another program modified..." message...
if (checkForModification == true) {
// Flag so that if the user takes to long deciding, messages
// don't pile up about the same file being modified.
// NOTE: This is theoretically not thread-safe, but the
// delay is set at 10 seconds, so it should be more than
// enough to get to and complete this line).
checkForModification = false;
int numDocuments = getNumDocuments();
String docsToAskAbout = "";
for (int i = 0; i < numDocuments; i++) {
RTextEditorPane textArea = getRTextEditorPaneAt(i);
String fileFullPath = textArea.getFileFullPath();
File file = new File(fileFullPath);
if (file.exists() && file.lastModified() > textArea.getLastModified()) {
docsToAskAbout = docsToAskAbout + " " + i;
}
}
// If no documents were modified outsied the editor, allow the
// thread to check again; otherwise, remember to prompt the user
// about all of the documents that changed outside of the editor.
if ("".equals(docsToAskAbout)) {
checkForModification = true;
}
else {
final String actionCommand = "FileModified." + docsToAskAbout;
SwingUtilities.invokeLater(new Runnable() {
public void run() {
actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED,
actionCommand));
}
});
}
} // End of if (checkForModification==true).
}
/*****************************************************************************/
/**
* Attempts to close all currently active documents.
*
* @return <code>true</code> if all active documents were closed, and
* <code>false</code> if they weren't (i.e., the user hit cancel).
*/
public boolean closeAllDocuments() {
// Cycle through each document, one by one.
int numDocuments = getNumDocuments();
for (int i = numDocuments - 1; i >= 0; i--) {
// Try to close the document.
int rc = closeCurrentDocument();
// If the user cancels out of it, quit the whole schibang.
if (rc == JOptionPane.CANCEL_OPTION) {
// If the newly-active file is read-only, say so in the status bar.
owner.setStatusBarReadOnlyIndicatorEnabled(
currentTextArea == null ? false
: currentTextArea.isReadOnly());
return false;
}
} // End of for (int i=tabCount-1; i>=0; i--).
// If we got this far, then all documents were closed.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -