下面列出了javax.swing.text.JTextComponent#putClientProperty ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
/**
* Fetches the previous caret location, stores the current caret location,
* If the caret is on another line, repaint the previous line and the current line
*
* @param c the text component
*/
private static void currentLineChanged(JTextComponent c) {
try {
int previousCaret = ((Integer) c.getClientProperty(PREVIOUS_CARET)).intValue();
Rectangle prev = c.modelToView(previousCaret);
Rectangle r = c.modelToView(c.getCaretPosition());
c.putClientProperty(PREVIOUS_CARET, new Integer(c.getCaretPosition()));
if ((prev != null) && (prev.y != r.y)) {
c.repaint(0, prev.y, c.getWidth(), r.height);
c.repaint(0, r.y, c.getWidth(), r.height);
}
} catch (BadLocationException e) {
// ignore
}
}
/**
* Records the navigation filter. Note that the filter is stored in the JTextComponent rather than
* in this Caret. If the Component's UI changes or the caret is recreated for some reason, the
* navigation filters remain registered.
*
* @param type type of nav filter
* @param n the filter instance
*/
private static void doPutNavigationFilter(JTextComponent component, String type, NavigationFilter n) {
if (component == null) {
throw new IllegalStateException("Not attached to a Component");
}
Map<String, NavigationFilter> m = (Map<String, NavigationFilter>)component.getClientProperty(NAVIGATION_FILTER_PROPERTY);
if (m == null) {
if (n == null) {
return;
}
m = new HashMap<>();
component.putClientProperty(NAVIGATION_FILTER_PROPERTY, m);
}
if (n == null) {
m.remove(type);
} else {
m.put(type, n);
}
}
public static synchronized MasterMatcher get(JTextComponent component) {
MasterMatcher mm = (MasterMatcher) component.getClientProperty(MasterMatcher.class);
if (mm == null) {
mm = new MasterMatcher(component);
component.putClientProperty(MasterMatcher.class, mm);
}
return mm;
}
private static void setSearchDirection(JTextComponent component, String value) {
String s = null;
if (value != null) {
for (String [] pair : SEARCH_DIRECTIONS) {
if (pair[1].equals(value)) {
s = pair[0];
break;
}
}
}
component.putClientProperty(MasterMatcher.PROP_SEARCH_DIRECTION, s);
}
/**
* Return the MouseEvent's click count, possibly reduced by the value of
* the component's {@code SKIP_CLICK_COUNT} client property. Clears
* the {@code SKIP_CLICK_COUNT} property if the mouse event's click count
* is 1. In order for clearing of the property to work correctly, there
* must be a mousePressed implementation on the caller with this
* call as the first line.
*/
public static int getAdjustedClickCount(JTextComponent comp, MouseEvent e) {
int cc = e.getClickCount();
if (cc == 1) {
comp.putClientProperty(SKIP_CLICK_COUNT, null);
} else {
Integer sub = (Integer) comp.getClientProperty(SKIP_CLICK_COUNT);
if (sub != null) {
return cc - sub;
}
}
return cc;
}
/**
* Return the MouseEvent's click count, possibly reduced by the value of
* the component's {@code SKIP_CLICK_COUNT} client property. Clears
* the {@code SKIP_CLICK_COUNT} property if the mouse event's click count
* is 1. In order for clearing of the property to work correctly, there
* must be a mousePressed implementation on the caller with this
* call as the first line.
*/
public static int getAdjustedClickCount(JTextComponent comp, MouseEvent e) {
int cc = e.getClickCount();
if (cc == 1) {
comp.putClientProperty(SKIP_CLICK_COUNT, null);
} else {
Integer sub = (Integer) comp.getClientProperty(SKIP_CLICK_COUNT);
if (sub != null) {
return cc - sub;
}
}
return cc;
}
private static void setFwdLookahead(JTextComponent component, String value) {
if (value == null || value.trim().length() == 0) {
component.putClientProperty(MasterMatcher.PROP_MAX_FORWARD_LOOKAHEAD, null);
} else {
component.putClientProperty(MasterMatcher.PROP_MAX_FORWARD_LOOKAHEAD, value);
}
}
/**
* Remove the given item from registry and return the next one.
*
* @param item item to remove.
* @return next item in registry.
*/
static Item removeFromRegistry(Item item, List<PropertyChangeEvent> events) {
boolean lastFocused = (items == item);
// Remove component from item chain
JTextComponent component = item.get();
item = removeFromItemList(item);
if (component != null) {
// unregister the listeneres
component.putClientProperty(Item.class, null);
component.removeFocusListener(FocusL.INSTANCE);
component.removeAncestorListener(AncestorL.INSTANCE);
component.removePropertyChangeListener(CloneableEditorUsageL.INSTANCE);
events.add(new PropertyChangeEvent(EditorRegistry.class, COMPONENT_REMOVED_PROPERTY, component, null));
if (LOG.isLoggable(Level.FINEST)) {
LOG.fine("Component removed: " + dumpComponent(component) + '\n'); //NOI18N
logItemListFinest();
}
if (lastFocused) {
events.add(new PropertyChangeEvent(EditorRegistry.class, LAST_FOCUSED_REMOVED_PROPERTY, component, lastFocusedComponent()));
if (LOG.isLoggable(Level.FINE)) {
LOG.fine("Fired LAST_FOCUSED_REMOVED_PROPERTY for " + dumpComponent(component) + '\n'); //NOI18N
}
}
}
return item;
}
/**
* Set text view background color correctly. See bug #225829.
*/
private void setTextViewBackground(JTextComponent textView, Color bg) {
getOutputPane().getTextView().setBackground(bg);
getOutputPane().getFoldingSideBar().setBackground(bg);
if ("Nimbus".equals(UIManager.getLookAndFeel().getName())) { //NOI18N
UIDefaults defaults = new UIDefaults();
defaults.put("EditorPane[Enabled].backgroundPainter", bg); //NOI18N
textView.putClientProperty("Nimbus.Overrides", defaults); //NOI18N
textView.putClientProperty(
"Nimbus.Overrides.InheritDefaults", true); //NOI18N
textView.setBackground(bg);
}
}
private static void setShowParameters(JTextComponent component, boolean show) {
component.putClientProperty(MasterMatcher.PROP_SHOW_SEARCH_PARAMETERS, Boolean.toString(show));
}
@Override
public MarkProvider createMarkProvider (JTextComponent pane) {
AnnotationMarkProvider amp = new AnnotationMarkProvider();
pane.putClientProperty(PROVIDER_KEY, amp);
return amp;
}
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 InstantRefactoringPerformer(final JTextComponent target, int caretOffset, InstantRefactoringUI ui) {
releaseAll();
this.target = target;
this.ui = ui;
doc = target.getDocument();
MutablePositionRegion mainRegion = null;
List<MutablePositionRegion> regions = new ArrayList<>(ui.getRegions().size());
for (MutablePositionRegion current : ui.getRegions()) {
// TODO: type parameter name is represented as ident -> ignore surrounding <> in rename
if (isIn(current, caretOffset)) {
mainRegion = current;
} else {
regions.add(current);
}
}
if (mainRegion == null) {
throw new IllegalArgumentException("No highlight contains the caret.");
}
regions.add(0, mainRegion);
region = new SyncDocumentRegion(doc, regions);
if (doc instanceof BaseDocument) {
BaseDocument bdoc = ((BaseDocument) doc);
bdoc.addPostModificationDocumentListener(this);
UndoableWrapper wrapper = MimeLookup.getLookup("text/x-java").lookup(UndoableWrapper.class);
if(wrapper != null) {
wrapper.setActive(true, this);
}
UndoableEdit undo = new CancelInstantRenameUndoableEdit(this);
for (UndoableEditListener l : bdoc.getUndoableEditListeners()) {
l.undoableEditHappened(new UndoableEditEvent(doc, undo));
}
}
target.addKeyListener(this);
target.putClientProperty(InstantRefactoringPerformer.class, this);
target.putClientProperty("NetBeansEditor.navigateBoundaries", mainRegion); // NOI18N
requestRepaint();
target.select(mainRegion.getStartOffset(), mainRegion.getEndOffset());
span = region.getFirstRegionLength();
compl = new CompletionLayout(this);
compl.setEditorComponent(target);
final KeyStroke OKKS = ui.getKeyStroke();
target.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(OKKS, OKActionKey);
Action OKAction = new AbstractAction() {
@Override
public void actionPerformed(ActionEvent ae) {
if(registry.contains(InstantRefactoringPerformer.this)) {
doFullRefactoring();
target.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).remove(OKKS);
target.getActionMap().remove(OKActionKey);
} else {
target.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).remove(OKKS);
target.getActionMap().remove(OKActionKey);
}
}
};
target.getActionMap().put(OKActionKey, OKAction);
final KeyStroke keyStroke = ui.getKeyStroke();
compl.showCompletion(ui.getOptions(), caretOffset, Bundle.INFO_PressAgain(getKeyStrokeAsText(keyStroke)));
registry.add(this);
}
/** Creates a new instance of InstantRenamePerformer */
private InstantRenamePerformer(JTextComponent target, Set<OffsetRange> highlights, int caretOffset) throws BadLocationException {
this.target = target;
doc = target.getDocument();
MutablePositionRegion mainRegion = null;
List<MutablePositionRegion> regions = new ArrayList<MutablePositionRegion>();
for (OffsetRange h : highlights) {
Position start = NbDocument.createPosition(doc, h.getStart(), Bias.Backward);
Position end = NbDocument.createPosition(doc, h.getEnd(), Bias.Forward);
MutablePositionRegion current = new MutablePositionRegion(start, end);
if (isIn(current, caretOffset)) {
mainRegion = current;
} else {
regions.add(current);
}
}
if (mainRegion == null) {
Logger.getLogger(InstantRenamePerformer.class.getName()).warning("No highlight contains the caret (" + caretOffset + "; highlights=" + highlights + ")"); //NOI18N
// Attempt to use another region - pick the one closest to the caret
if (regions.size() > 0) {
mainRegion = regions.get(0);
int mainDistance = Integer.MAX_VALUE;
for (MutablePositionRegion r : regions) {
int distance = caretOffset < r.getStartOffset() ? (r.getStartOffset()-caretOffset) : (caretOffset-r.getEndOffset());
if (distance < mainDistance) {
mainRegion = r;
mainDistance = distance;
}
}
} else {
return;
}
}
regions.add(0, mainRegion);
region = new SyncDocumentRegion(doc, regions);
if (doc instanceof BaseDocument) {
((BaseDocument) doc).addPostModificationDocumentListener(this);
}
target.addKeyListener(this);
target.putClientProperty("NetBeansEditor.navigateBoundaries", mainRegion); // NOI18N
target.putClientProperty(InstantRenamePerformer.class, this);
requestRepaint();
target.select(mainRegion.getStartOffset(), mainRegion.getEndOffset());
}
/**
* Creates initially hidden annotations sidebar.
* It's called once by target lifetime.
*/
public JComponent createSideBar(JTextComponent target) {
final AnnotationBar ab = new AnnotationBar(target);
target.putClientProperty(AnnotationBarManager.BAR_KEY, ab);
return ab;
}
@Override
public void actionPerformed(final ActionEvent evt, final JTextComponent target) {
Document doc = target.getDocument();
JavaSource js = JavaSource.forDocument(doc);
final Object lock = new Object();
final AtomicBoolean cancel = new AtomicBoolean();
final AtomicBoolean alreadyRunning = new AtomicBoolean();
if (js != null && !DocumentUtilities.isWriteLocked(doc)) {
boolean finished = runQuickly(js, new Task<CompilationController>() {
@Override
public void run(CompilationController parameter) throws Exception {
synchronized (lock) {
if (cancel.get()) {
return;
}
alreadyRunning.set(true);
}
try {
target.putClientProperty(RUN_SYNCHRONOUSLY, true);
JavaCutToLineBeginOrEndAction.super.actionPerformed(evt, target);
} finally {
target.putClientProperty(RUN_SYNCHRONOUSLY, null);
}
}
});
if (finished) {
return;
}
}
synchronized (lock) {
if (alreadyRunning.get()) {
return;
}
cancel.set(true);
}
try {
target.putClientProperty(NO_IMPORTS, true);
super.actionPerformed(evt, target);
} finally {
target.putClientProperty(NO_IMPORTS, null);
}
}
FoldingEditorSupport(FoldHierarchy h, JTextComponent component) {
this.component = component;
this.foldHierarchy = h;
component.putClientProperty("org.netbeans.api.fold.expander", new C());
foldHierarchy.addFoldHierarchyListener(this);
}
@Override
public void foldHierarchyChanged(FoldHierarchyEvent evt) {
boolean collapsedAdded = false;
boolean changedToCollapsed = false;
// Check if any collapsed fold was added or a collapsed/expanded state changed
for (int i = evt.getAddedFoldCount() - 1; i >= 0; i--) {
if (evt.getAddedFold(i).isCollapsed()) {
collapsedAdded = true;
break;
}
}
if (!collapsedAdded) {
for (int i = evt.getFoldStateChangeCount() - 1; i >= 0; i--) {
FoldStateChange foldStateChange = evt.getFoldStateChange(i);
if (foldStateChange.isCollapsedChanged() && foldStateChange.getFold().isCollapsed()) {
changedToCollapsed = true;
break;
}
}
}
collapsedFoldEncountered |= collapsedAdded || changedToCollapsed;
JTextComponent comp = textComponent();
if (collapsedFoldEncountered && comp != null) {
// [TODO] there could be more detailed inspection done among folds
// of what really changed and what are in fact the same folds as before the change
// possibly performed even on the Fold API level.
int startOffset = evt.getAffectedStartOffset();
int endOffset = evt.getAffectedEndOffset();
if (CHANGE_LOG.isLoggable(Level.FINE)) {
ViewUtils.log(CHANGE_LOG, "CHANGE in FoldViewFactory: <" + // NOI18N
startOffset + "," + endOffset + ">\n"); // NOI18N
}
if (collapsedAdded) {
// this hint covers a specific case when a fold is created as *initially* collapsed
// to maintain caret position on screen, if the caret was visible.
comp.putClientProperty("editorcaret.updateRetainsVisibleOnce", Boolean.TRUE);
}
fireEvent(EditorViewFactoryChange.createList(startOffset, endOffset,
EditorViewFactoryChange.Type.PARAGRAPH_CHANGE));
}
}
/**
* Get mutex used to lock the view hierarchy.
* All the services manipulating the view hierarchy
* or providing data for the view hierarchy
* may choose to lock on this mutex
* rather having its own locking mechanism
* to simplify their locking model
* and eliminate possibility of deadlocks
* because of counter-locking.
* <br>
* The <code>LockView</code> itself uses this mutex
* as well as the code folding hierarchy.
*/
public static synchronized PriorityMutex getViewHierarchyMutex(JTextComponent component) {
// A single mutex instance must be shared by view and fold hierarchies
PriorityMutex mutex = (PriorityMutex)component.getClientProperty(PROPERTY_FOLD_HIERARCHY_MUTEX);
if (mutex == null) {
mutex = new PriorityMutex();
component.putClientProperty(PROPERTY_FOLD_HIERARCHY_MUTEX, mutex);
}
component.putClientProperty(PROPERTY_VIEW_HIERARCHY_MUTEX, mutex);
return mutex;
}
/**
* Specifies whether the text component contents should flip selection on ESCAPE key press.
*
* @param comp Text component.
* @param flipTextSelectionOnEscape If <code>true</code>, the contents of the specified
* text component will flip
* selection on ESCAPE key press. Pass <code>null</code>
* to reset to the default
* behavior.
*/
public static void setFlipTextSelectionOnEscape(JTextComponent comp,
Boolean flipTextSelectionOnEscape) {
if (comp == null) {
throw new IllegalArgumentException("Component scope APIs do not accept null components");
}
comp.putClientProperty(SubstanceSynapse.TEXT_FLIP_SELECT_ON_ESCAPE,
flipTextSelectionOnEscape);
}