下面列出了javax.swing.text.AbstractDocument#readUnlock ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
public static String foldHierarchyToString(JTextComponent target){
String ret = "";
AbstractDocument adoc = (AbstractDocument)target.getDocument();
// Dump fold hierarchy
FoldHierarchy hierarchy = FoldHierarchy.get(target);
adoc.readLock();
try {
hierarchy.lock();
try {
Fold root = hierarchy.getRootFold();
ret = (root == null) ? "root is null" : foldToStringChildren(root, 0); //NOI18N
} finally {
hierarchy.unlock();
}
} finally {
adoc.readUnlock();
}
return ret;
}
public void run() {
AbstractDocument doc = (AbstractDocument)getDocument();
if (doc!=null){
doc.readLock();
try {
LockView lockView = LockView.get(GapDocumentView.this);
if (lockView != null) {
lockView.lock();
try {
layoutLock();
try {
updateView(lockView);
} finally {
updateLayout();
layoutUnlock();
}
} finally {
lockView.unlock();
}
} // missing lock view => likely disconnected from hierarchy
} finally {
doc.readUnlock();
}
}
}
static void refreshHack () {
Iterator<Document> it = managers.keySet ().iterator ();
while (it.hasNext ()) {
AbstractDocument document = (AbstractDocument) it.next ();
document.readLock ();
try {
MutableTextInput mti = (MutableTextInput) document.getProperty (MutableTextInput.class);
mti.tokenHierarchyControl ().rebuild ();
} finally {
document.readUnlock ();
}
// final StyledDocument document = (StyledDocument) it.next ();
// NbDocument.runAtomic (document, new Runnable () {
// public void run() {
// MutableTextInput mti = (MutableTextInput) document.getProperty (MutableTextInput.class);
// mti.tokenHierarchyControl ().rebuild ();
// }
// });
}
}
private static MimePath getFullMimePath(Document document, int offset) {
String langPath = null;
if (document instanceof AbstractDocument) {
AbstractDocument adoc = (AbstractDocument)document;
adoc.readLock();
try {
List<TokenSequence<?>> list = TokenHierarchy.get(document).embeddedTokenSequences(offset, true);
if (list.size() > 1) {
langPath = list.get(list.size() - 1).languagePath().mimePath();
}
} finally {
adoc.readUnlock();
}
}
if (langPath == null) {
langPath = NbEditorUtilities.getMimeType(document);
}
if (langPath != null) {
return MimePath.parse(langPath);
} else {
return null;
}
}
protected void waitForFolding(JTextComponent target, int maxMiliSeconds){
//wait for parser and folding hierarchy creation
int time = (int) maxMiliSeconds / 100;
AbstractDocument adoc = (AbstractDocument)target.getDocument();
// Dump fold hierarchy
FoldHierarchy hierarchy = FoldHierarchy.get(target);
int foldCount = 0;
while (foldCount==0 && time > 0) {
adoc.readLock();
try {
hierarchy.lock();
try {
foldCount = hierarchy.getRootFold().getFoldCount();
} finally {
hierarchy.unlock();
}
} finally {
adoc.readUnlock();
}
try {
Thread.currentThread().sleep(100);
} catch (InterruptedException ex) {
time=0;
}
time--;
}
}
public void propertyChange(java.beans.PropertyChangeEvent evt) {
JTextComponent component = (JTextComponent)getContainer();
if (component==null || evt==null ||
(!EditorUI.LINE_HEIGHT_CHANGED_PROP.equals(evt.getPropertyName()) &&
!EditorUI.TAB_SIZE_CHANGED_PROP.equals(evt.getPropertyName())
)
) {
return;
}
AbstractDocument doc = (AbstractDocument)getDocument();
if (doc!=null) {
doc.readLock();
try{
LockView lockView = LockView.get(this);
lockView.lock();
try {
rebuild(0, getViewCount());
} finally {
lockView.unlock();
}
} finally {
doc.readUnlock();
}
component.revalidate();
}
}
int[] getLinesSpan(int currentLine) {
AbstractDocument adoc = doc;
if (adoc != null)
adoc.readLock();
try {
double componentHeight = getComponentHeight();
double usableHeight = getUsableHeight();
double position = _modelToView(currentLine, componentHeight, usableHeight);
if (position == (-1))
return new int[] {currentLine, currentLine};
int startLine = currentLine;
int endLine = currentLine;
while (position == _modelToView(startLine - 1, componentHeight, usableHeight) && startLine > 0)
startLine--;
while ((endLine + 1) < Utilities.getRowCount(doc) && position == _modelToView(endLine + 1, componentHeight, usableHeight))
endLine++;
return new int[] {startLine, endLine};
} finally {
if (adoc != null)
adoc.readUnlock();
}
}
/** Update visual position of caret(s) */
private void dispatchUpdate(boolean forceInvokeLater) {
boolean alreadyPending;
synchronized (listenerList) {
alreadyPending = caretUpdatePending;
caretUpdatePending = true;
}
if (!alreadyPending) {
Runnable updateRunnable = new Runnable() {
public @Override void run() {
AbstractDocument doc = activeDoc;
if (doc != null) {
doc.readLock();
try {
update(false);
} finally {
doc.readUnlock();
}
} else {
// #269262 avoid that update() is not invoked
synchronized (listenerList) {
caretUpdatePending = false;
}
}
}
};
if (!forceInvokeLater && SwingUtilities.isEventDispatchThread()) {
updateRunnable.run();
} else {
SwingUtilities.invokeLater(updateRunnable);
}
}
}
public Object evaluate (Context context) {
if (context instanceof SyntaxContext) {
Object l = ((SyntaxContext) context).getASTPath ().getLeaf ();
if (l instanceof ASTNode)
return evaluate ((ASTNode) l);
if (l instanceof ASTToken)
return evaluate ((ASTToken) l);
} else {
AbstractDocument document = (AbstractDocument) context.getDocument ();
document.readLock ();
ASTToken stoken = null;
try {
TokenSequence tokenSequence = Utils.getTokenSequence (document, context.getOffset ());
Token token = tokenSequence.token ();
if (token != null)
stoken = ASTToken.create (
null,
token.id ().ordinal (),
token.text ().toString (),
tokenSequence.offset ()
);
} finally {
document.readUnlock ();
}
return evaluate (stoken);
}
throw new IllegalArgumentException ();
}
/**
* Checks to see if an end tag exists for a start tag at a given offset.
* @param document
* @param offset
* @return true if an end tag is found for the start, false otherwise.
*/
public static boolean hasEndTag(Document document, int offset, String startTag) {
AbstractDocument doc = (AbstractDocument)document;
doc.readLock();
try {
TokenHierarchy th = TokenHierarchy.get(doc);
TokenSequence ts = th.tokenSequence();
Token token = findTokenAtContext(ts, offset);
Stack<String> stack = new Stack<String>();
while(ts.moveNext()) {
Token t = ts.token();
if(XMLTokenId.TAG != t.id())
continue;
String tag = t.text().toString();
if(">".equals(tag))
continue;
if(stack.empty()) {
if(("</"+startTag).equals(tag)) {
stack.empty();
stack = null;
return true;
}
} else {
if(tag.equals("/>") || ("</"+stack.peek()).equals(tag)) {
stack.pop();
continue;
}
}
stack.push(tag.substring(1));
}
} finally {
doc.readUnlock();
}
return false;
}
public static void collapseOrExpand(FoldHierarchy hierarchy, Collection foldTypes,
boolean collapse) {
Document d = hierarchy.getComponent().getDocument();
if (!(d instanceof AbstractDocument)) {
// no op, the folding hierarchy does not work for != AbstractDocument
return;
}
AbstractDocument adoc = (AbstractDocument)d;
adoc.readLock();
try {
hierarchy.lock();
try {
List foldList = findRecursive(null,
hierarchy.getRootFold(), foldTypes);
if (collapse) {
hierarchy.collapse(foldList);
} else {
hierarchy.expand(foldList);
}
} finally {
hierarchy.unlock();
}
} finally {
adoc.readUnlock();
}
}
/**
* Checks that no changes (update with the same infos) will not fire events, remove or add any folds.
*
* @throws Exception
*/
public void testUpdateNoChanges() throws Exception {
final TestFoldManager[] mgr = new TestFoldManager[1];
FoldHierarchyTestEnv env = new FoldHierarchyTestEnv(new FoldManagerFactory() {
@Override
public FoldManager createFoldManager() {
return mgr[0] = new TestFoldManager();
}
});
AbstractDocument doc = env.getDocument();
doc.insertString(0, "12345678901234567890", null);
FoldHierarchy hierarchy = env.getHierarchy();
Collection<FoldInfo> infos = new ArrayList<FoldInfo>(10);
infos.add(FoldInfo.range(0, 1, FoldType.MEMBER));
infos.add(FoldInfo.range(9, 10, FoldType.MEMBER));
infos.add(FoldInfo.range(14, 16, FoldType.MEMBER));
// not sorted, check :)
infos.add(FoldInfo.range(3, 12, FoldType.MEMBER));
infos.add(FoldInfo.range(5, 6, FoldType.MEMBER));
doc.readLock();
try {
hierarchy.lock();
TestFoldManager m = mgr[0];
try {
Collection<Fold> remove = new ArrayList<Fold>();
Collection<FoldInfo> create = new ArrayList<FoldInfo>();
final boolean[] changed = new boolean[1];
hierarchy.addFoldHierarchyListener(new FoldHierarchyListener() {
@Override
public void foldHierarchyChanged(FoldHierarchyEvent evt) {
changed[0] = true;
}
});
Map<FoldInfo, Fold> mapping = m.operation.update(infos, remove, create);
assertEquals(m.initFolds.size(), mapping.size());
assertTrue(m.initFolds.containsAll(mapping.values()));
assertFalse(changed[0]);
} finally {
hierarchy.unlock();
}
} finally {
doc.readUnlock();
}
}
public @Override void mouseDragged(MouseEvent e) {
EditorUI eui = editorUI;
if (eui == null) {
return;
}
JTextComponent component = eui.getComponent();
BaseTextUI textUI = (BaseTextUI)component.getUI();
AbstractDocument aDoc = (AbstractDocument)component.getDocument();
aDoc.readLock();
try {
// The drag must be extended to a next line in order to perform any selection
int lineStartOffset = textUI.getPosFromY(e.getY());
boolean updateDragEndOffset = false;
if (dragStartOffset == -1) { // Drag starts now
dragStartOffset = lineStartOffset;
dragEndOffset = lineStartOffset;
} else if (dragStartOffset == dragEndOffset) {
if (lineStartOffset != dragStartOffset) {
updateDragEndOffset = true;
}
} else {
updateDragEndOffset = true;
}
if (updateDragEndOffset) {
// Extend selection to active line's end or begining depending on dragStartOffset
Caret caret = component.getCaret();
if (lineStartOffset >= dragStartOffset) {
if (caret.getMark() != dragStartOffset) {
caret.setDot(dragStartOffset);
}
// Check if the sele
// Extend to next line's begining
dragEndOffset = Math.min(Utilities.getRowEnd((BaseDocument) aDoc, lineStartOffset) + 1, aDoc.getLength());
} else { // Backward selection
// Check if the selection is already reverted i.e. it starts at dragStartOffset's line end
if (caret.getMark() == dragStartOffset) {
caret.setDot(Utilities.getRowEnd((BaseDocument)aDoc, dragStartOffset) + 1);
}
dragEndOffset = lineStartOffset;
}
component.moveCaretPosition(dragEndOffset);
}
} catch (BadLocationException ble) {
// Ignore rather than notify
} finally {
aDoc.readUnlock();
}
}
public void actionPerformed(ActionEvent evt, JTextComponent target) {
AbstractDocument adoc = (AbstractDocument)target.getDocument();
// Dump fold hierarchy
FoldHierarchy hierarchy = FoldHierarchy.get(target);
adoc.readLock();
try {
hierarchy.lock();
try {
/*DEBUG*/System.err.println("FOLD HIERARCHY DUMP:\n" + hierarchy); // NOI18N
TokenHierarchy<?> th = TokenHierarchy.get(adoc);
/*DEBUG*/System.err.println("TOKEN HIERARCHY DUMP:\n" + (th != null ? th : "<NULL-TH>")); // NOI18N
} finally {
hierarchy.unlock();
}
} finally {
adoc.readUnlock();
}
View rootView = null;
TextUI textUI = target.getUI();
if (textUI != null) {
rootView = textUI.getRootView(target); // Root view impl in BasicTextUI
if (rootView != null && rootView.getViewCount() == 1) {
rootView = rootView.getView(0); // Get DocumentView
}
}
if (rootView != null) {
String rootViewDump = (rootView instanceof DocumentView)
? ((DocumentView)rootView).toStringDetail()
: rootView.toString();
/*DEBUG*/System.err.println("DOCUMENT VIEW: " + System.identityHashCode(rootView) + // NOI18N
"\n" + rootViewDump); // NOI18N
int caretOffset = target.getCaretPosition();
int caretViewIndex = rootView.getViewIndex(caretOffset, Position.Bias.Forward);
/*DEBUG*/System.err.println("caretOffset=" + caretOffset + ", caretViewIndex=" + caretViewIndex); // NOI18N
if (caretViewIndex >= 0 && caretViewIndex < rootView.getViewCount()) {
View caretView = rootView.getView(caretViewIndex);
/*DEBUG*/System.err.println("caretView: " + caretView); // NOI18N
}
/*DEBUG*/System.err.println(FixLineSyntaxState.lineInfosToString(adoc));
// Check the hierarchy correctness
//org.netbeans.editor.view.spi.ViewUtilities.checkViewHierarchy(rootView);
}
if (adoc instanceof BaseDocument) {
/*DEBUG*/System.err.println("DOCUMENT:\n" + ((BaseDocument)adoc).toStringDetail()); // NOI18N
}
}
@Override
public void exportToClipboard(JComponent c, Clipboard clip, int action) throws IllegalStateException {
List<Position> regions;
if (c instanceof JTextComponent &&
(Boolean.TRUE.equals(c.getClientProperty(RECTANGULAR_SELECTION_PROPERTY))) &&
(regions = RectangularSelectionUtils.regionsCopy(c)) != null)
{
final JTextComponent tc = (JTextComponent) c;
String[] data;
StringBuilder stringSelectionBuffer;
AbstractDocument doc = (AbstractDocument) tc.getDocument();
doc.readLock();
try {
// Cannot delegate to overriden transfer handler - at least not the JTextComponent.DefaultTransferHandler
// because it would:
// for COPY action whole selection would be copied which is wrong
// for MOVE selection it would in addition remove <dot,mark> portion of the document.
// Therefore handle string selection here explicitly.
CharSequence docText = DocumentUtilities.getText(doc);
stringSelectionBuffer = new StringBuilder(100);
int size = regions.size();
data = new String[size >>> 1];
for (int i = 0; i < size; i++) {
Position startPos = regions.get(i++);
Position endPos = regions.get(i);
CharSequence lineSel = docText.subSequence(startPos.getOffset(), endPos.getOffset());
int halfI = (i >>> 1);
if (halfI != 0) {
stringSelectionBuffer.append('\n');
}
stringSelectionBuffer.append(lineSel);
data[halfI] = lineSel.toString();
}
} finally {
doc.readUnlock();
}
clip.setContents(
new WrappedTransferable(
new StringSelection(stringSelectionBuffer.toString()),
new RectangularSelectionData(data)),
null);
if (action == TransferHandler.MOVE) {
try {
RectangularSelectionUtils.removeSelection(doc, regions);
} catch (BadLocationException ex) {
Exceptions.printStackTrace(ex);
}
}
return;
} else { // No rectangular selection
delegate.exportToClipboard(c, clip, action);
}
}
/**
* Checks that folds are created beween two folds, encapsulating existing folds.
*
* @throws Exception
*/
public void testUpdateCreateFold() throws Exception {
final TestFoldManager[] mgr = new TestFoldManager[1];
FoldHierarchyTestEnv env = new FoldHierarchyTestEnv(new FoldManagerFactory() {
@Override
public FoldManager createFoldManager() {
return mgr[0] = new TestFoldManager();
}
});
AbstractDocument doc = env.getDocument();
doc.insertString(0, "12345678901234567890", null);
FoldHierarchy hierarchy = env.getHierarchy();
List<FoldInfo> infos = createDefaultInfos();
// add a new fold between #1 and #2
infos.add(FoldInfo.range(2, 3, FoldType.MEMBER));
// add a new fold at the end:
infos.add(FoldInfo.range(19,20, FoldType.MEMBER));
// add a fold, which encapsulates #2 - #5
infos.add(FoldInfo.range(3, 18, FoldType.MEMBER));
// add a fold, which encapsulates ##5
infos.add(FoldInfo.range(13, 16, FoldType.MEMBER));
doc.readLock();
try {
hierarchy.lock();
TestFoldManager m = mgr[0];
try {
Collection<Fold> remove = new ArrayList<Fold>();
Collection<FoldInfo> create = new ArrayList<FoldInfo>();
final boolean[] changed = new boolean[1];
hierarchy.addFoldHierarchyListener(new FoldHierarchyListener() {
@Override
public void foldHierarchyChanged(FoldHierarchyEvent evt) {
changed[0] = true;
}
});
Map<FoldInfo, Fold> mapping = m.operation.update(infos, remove, create);
// 3 folds added, no deleted:
assertEquals(4, create.size());
assertEquals(0, remove.size());
} finally {
hierarchy.unlock();
}
} finally {
doc.readUnlock();
}
}
private void updateRectangularSelectionPositionBlocks() {
JTextComponent c = component;
if (rectangularSelection) {
AbstractDocument doc = activeDoc;
if (doc != null) {
doc.readLock();
try {
if (rsRegions == null) {
rsRegions = new ArrayList<Position>();
component.putClientProperty(RECTANGULAR_SELECTION_REGIONS_PROPERTY, rsRegions);
}
synchronized (rsRegions) {
if (LOG.isLoggable(Level.FINE)) {
LOG.fine("EditorCaret.updateRectangularSelectionPositionBlocks: position regions:\n");
}
rsRegions.clear();
if (rsPaintRect != null) {
LockedViewHierarchy lvh = ViewHierarchy.get(c).lock();
try {
float rowHeight = lvh.getDefaultRowHeight();
double y = rsPaintRect.y;
double maxY = y + rsPaintRect.height;
double minX = rsPaintRect.getMinX();
double maxX = rsPaintRect.getMaxX();
do {
int startOffset = lvh.viewToModel(minX, y, null);
int endOffset = lvh.viewToModel(maxX, y, null);
// They could be swapped due to RTL text
if (startOffset > endOffset) {
int tmp = startOffset;
startOffset = endOffset;
endOffset = tmp;
}
Position startPos = activeDoc.createPosition(startOffset);
Position endPos = activeDoc.createPosition(endOffset);
rsRegions.add(startPos);
rsRegions.add(endPos);
if (LOG.isLoggable(Level.FINE)) {
LOG.fine(" <" + startOffset + "," + endOffset + ">\n");
}
y += rowHeight;
} while (y < maxY);
c.putClientProperty(RECTANGULAR_SELECTION_REGIONS_PROPERTY, rsRegions);
} finally {
lvh.unlock();
}
}
}
} catch (BadLocationException ex) {
Exceptions.printStackTrace(ex);
} finally {
doc.readUnlock();
}
}
}
}
public int[] doFindOrigin() throws InterruptedException, BadLocationException {
AbstractDocument doc = (AbstractDocument)document;
doc.readLock();
try {
TokenHierarchy th = TokenHierarchy.get(doc);
TokenSequence ts = th.tokenSequence();
Token token = atOffset(ts, searchOffset);
token = ts.token();
int start = ts.offset();
if(token == null)
return null;
XMLTokenId id = (XMLTokenId)token.id();
String tokenText = token.text().toString();
switch(id) {
case PI_START:
case PI_END: {
return new int[] {start, start+token.length()};
}
case TAG: {
//for ">" move back till the start tag
if(">".equals(tokenText)) {
while(move(ts)) {
if(ts.token().id() == XMLTokenId.TAG)
break;
}
}
return findTagPosition(ts, false);
}
case BLOCK_COMMENT: {
if(!tokenText.startsWith(COMMENT_START) &&
!tokenText.endsWith(COMMENT_END))
return null;
return findGenericOrigin(ts, COMMENT_START, COMMENT_END);
}
case CDATA_SECTION: {
if(!tokenText.startsWith(CDATA_START) &&
!tokenText.endsWith(CDATA_END))
return null;
return findGenericOrigin(ts, CDATA_START, CDATA_END);
}
case DECLARATION: {
if(!tokenText.startsWith(DECLARATION_START) &&
!tokenText.endsWith(DECLARATION_END))
return null;
return findGenericOrigin(ts, DECLARATION_START, DECLARATION_END);
}
default:
break;
}
} finally {
doc.readUnlock();
}
return null;
}
public int[] doFindMatches() throws InterruptedException, BadLocationException {
AbstractDocument doc = (AbstractDocument)document;
doc.readLock();
try {
TokenHierarchy th = TokenHierarchy.get(doc);
TokenSequence ts = th.tokenSequence();
Token token = atOffset(ts, searchOffset);
if(token == null) return null;
XMLTokenId id = (XMLTokenId)token.id();
switch(id) {
case PI_START: {
return findMatchingPair(ts, XMLTokenId.PI_END, true);
}
case PI_END: {
return findMatchingPair(ts, XMLTokenId.PI_START, false);
}
case TAG: {
//for ">" move back till the start tag
if(">".equals(ts.token().text().toString())) {
while(ts.movePrevious()) {
if(ts.token().id() == XMLTokenId.TAG)
break;
}
}
String tagName = ts.token().text().toString();
if(tagName.startsWith("</")) {
return findMatchingTagBackward(ts, tagName.substring(2));
}
if(tagName.startsWith("<")) {
return findMatchingTagForward(ts, tagName.substring(1));
}
}
case BLOCK_COMMENT: {
return findGenericMatch(ts, COMMENT_START, COMMENT_END);
}
case CDATA_SECTION: {
return findGenericMatch(ts, CDATA_START, CDATA_END);
}
case DECLARATION: {
return findGenericMatch(ts, DECLARATION_START, DECLARATION_END);
}
}
} finally {
doc.readUnlock();
}
return null;
}
/**
* Test the creation of several folds.
*/
public void test(boolean outerFirst) throws BadLocationException {
FoldHierarchyTestEnv env = new FoldHierarchyTestEnv(new NestedFoldManagerFactory(outerFirst));
AbstractDocument doc = env.getDocument();
doc.insertString(0, "1234567890", null);
FoldHierarchy hierarchy = env.getHierarchy();
doc.readLock();
try {
hierarchy.lock();
try {
Fold rootFold = hierarchy.getRootFold();
int foldCount = rootFold.getFoldCount();
int expectedFoldCount = 1;
assertTrue("Incorrect fold count " + foldCount, // NOI18N
(foldCount == expectedFoldCount)
);
Fold fold = rootFold.getFold(0);
FoldType foldType = fold.getType();
int foldStartOffset = fold.getStartOffset();
int foldEndOffset = fold.getEndOffset();
assertTrue("Incorrect fold type " + foldType, // NOI18N
(foldType == AbstractFoldManager.REGULAR_FOLD_TYPE));
assertTrue("Incorrect fold start offset " + foldStartOffset, // NOI18N
(foldStartOffset == FOLD_START_OFFSET_OUTER));
assertTrue("Incorrect fold end offset " + foldEndOffset, // NOI18N
(foldEndOffset == FOLD_END_OFFSET_OUTER));
// Test inner fold
Fold outerFold = fold;
foldCount = outerFold.getFoldCount();
expectedFoldCount = 1;
assertTrue("Incorrect fold count " + foldCount, // NOI18N
(foldCount == expectedFoldCount)
);
fold = outerFold.getFold(0);
assertTrue("Folds must differ", (fold != outerFold)); // NOI18N
foldType = fold.getType();
foldStartOffset = fold.getStartOffset();
foldEndOffset = fold.getEndOffset();
assertTrue("Incorrect fold type " + foldType, // NOI18N
(foldType == AbstractFoldManager.REGULAR_FOLD_TYPE));
assertTrue("Incorrect fold start offset " + foldStartOffset, // NOI18N
(foldStartOffset == FOLD_START_OFFSET_INNER));
assertTrue("Incorrect fold end offset " + foldEndOffset, // NOI18N
(foldEndOffset == FOLD_END_OFFSET_INNER));
} finally {
hierarchy.unlock();
}
} finally {
doc.readUnlock();
}
}