📄 abstractmainview.java~1~
字号:
* 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.
// We'll just have an empty default-named file out there.
return true;
}
/*****************************************************************************/
/**
* Attempts to close the current document. Any implementation of this
* method <i>must be synchronized</i> so it doesn't interfere with the
* thread checking for files being modified outside of the editor.
*
* @return JOptionPane.YES_OPTION/NO_OPTION/CANCEL_OPTION, depending on
* what the user does.
*/
public abstract int closeCurrentDocument();
/*****************************************************************************/
/**
* Converts all instances of a number of spaces equal to a tab in all open
* documents into tabs.
*
* @see #convertOpenFilesTabsToSpaces
*/
public void convertOpenFilesSpacesToTabs() {
int numDocuments = getNumDocuments();
for (int i=0; i<numDocuments; i++)
getRTextEditorPaneAt(i).convertSpacesToTabs();
}
/*****************************************************************************/
/**
* Converts all tabs in all open documents into an equivalent number of
* spaces.
*
* @see #convertOpenFilesSpacesToTabs
*/
public void convertOpenFilesTabsToSpaces() {
int numDocuments = getNumDocuments();
for (int i=0; i<numDocuments; i++)
getRTextEditorPaneAt(i).convertTabsToSpaces();
}
/*****************************************************************************/
public void copyData(AbstractMainView fromPanel) {
currentTextArea = fromPanel.currentTextArea;
for (int i=0; i<NUM_ACTIONS; i++)
actions[i] = fromPanel.getAction(i);
findDialog = fromPanel.findDialog;
replaceDialog = fromPanel.replaceDialog;
searchStrings = fromPanel.searchStrings;
searchingForward = fromPanel.searchingForward;
searchMatchCase = fromPanel.searchMatchCase;
searchWholeWord = fromPanel.searchWholeWord;
searchRegExpression = fromPanel.searchRegExpression;
searchMarkAll = fromPanel.searchMarkAll;
lineNumbersEnabled = fromPanel.lineNumbersEnabled;
lineWrapEnabled = fromPanel.lineWrapEnabled;
findInFilesDialog = fromPanel.findInFilesDialog;
if (findInFilesDialog!=null) {
findInFilesDialog.removeFindInFilesListener(fromPanel);
findInFilesDialog.addFindInFilesListener(this);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -