下面列出了怎么用javafx.scene.control.IndexRange的API类实例代码及写法,或者点击链接到github查看源代码。
/**
* Tests the case when both list and range have been modified and range
* change notification arrived first.
*/
@Test
public void testLateListNotifications() {
SuspendableList<Integer> list = new LiveArrayList<Integer>(1, 2, 3).suspendable();
SuspendableVar<IndexRange> range = Var.newSimpleVar(new IndexRange(0, 3)).suspendable();
Val<Integer> rangeSum = list.reduceRange(range, (a, b) -> a + b);
list.suspendWhile(() -> {
range.suspendWhile(() -> {
list.addAll(4, 5, 6);
range.setValue(new IndexRange(3, 6));
});
});
assertEquals(15, rangeSum.getValue().intValue());
// most importantly, this test tests that no IndexOutOfBoundsException is thrown
}
@Override
protected void setSecondAreaSelection() {
if (isSettingValues
|| displayArea == null || !contentSplitPane.getItems().contains(displayArea)) {
return;
}
isSettingValues = true;
displayArea.deselect();
final String text = mainArea.getText();
if (!text.isEmpty()) {
IndexRange hexRange = TextTools.hexIndex(text, sourceInformation.getCharset(),
sourceInformation.getLineBreakValue(), mainArea.getSelection());
int bomLen = 0;
if (sourceInformation.isWithBom()) {
bomLen = TextTools.bomHex(sourceInformation.getCharset().name()).length() + 1;
}
displayArea.selectRange(hexRange.getStart() + bomLen, hexRange.getEnd() + bomLen);
displayArea.setScrollTop(mainArea.getScrollTop());
}
isSettingValues = false;
}
/**
* Transfers the currently selected text to the clipboard,
* leaving the current selection.
*/
default void copy() {
IndexRange selection = getSelection();
if(selection.getLength() > 0) {
ClipboardContent content = new ClipboardContent();
content.putString(getSelectedText());
getStyleCodecs().ifPresent(codecs -> {
Codec<StyledDocument<PS, SEG, S>> codec = ReadOnlyStyledDocument.codec(codecs._1, codecs._2, getSegOps());
DataFormat format = dataFormat(codec.getName());
StyledDocument<PS, SEG, S> doc = subDocument(selection.getStart(), selection.getEnd());
ByteArrayOutputStream os = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(os);
try {
codec.encode(dos, doc);
content.put(format, os.toByteArray());
} catch (IOException e) {
System.err.println("Codec error: Exception in encoding '" + codec.getName() + "':");
e.printStackTrace();
}
});
Clipboard.getSystemClipboard().setContent(content);
}
}
public MarkdownPreviewPane() {
pane.getStyleClass().add("preview-pane");
previewContext = new PreviewContext() {
@Override public Renderer getRenderer() { return activeRenderer; }
@Override public String getMarkdownText() { return markdownText.get(); }
@Override public Node getMarkdownAST() { return markdownAST.get(); }
@Override public Path getPath() { return path.get(); }
@Override public IndexRange getEditorSelection() { return editorSelection.get(); }
};
path.addListener((observable, oldValue, newValue) -> update() );
markdownText.addListener((observable, oldValue, newValue) -> update() );
markdownAST.addListener((observable, oldValue, newValue) -> update() );
scrollY.addListener((observable, oldValue, newValue) -> scrollY());
editorSelection.addListener((observable, oldValue, newValue) -> editorSelectionChanged());
Options.additionalCSSProperty().addListener(new WeakChangeListener<String>(
(observable, oldValue, newValue) -> update()));
}
void replaceText(String text, StyleSpans<? extends Collection<String>> styleSpans) {
// remember old selection range and scrollY
IndexRange oldSelection = getSelection();
double oldScrollY = getEstimatedScrollY();
// replace text and styles
doReplaceText(text);
if (styleSpans != null)
setStyleSpans(0, styleSpans);
// restore old selection range and scrollY
int newLength = getLength();
selectRange(Math.min(oldSelection.getStart(), newLength), Math.min(oldSelection.getEnd(), newLength));
Platform.runLater(() -> {
estimatedScrollYProperty().setValue(oldScrollY);
});
}
/**
* If something is currently selected and the given position is outside of the selection, moves the selected
* rich-text document to the given position by deleting it from the area and re-inserting it at the given position.
* If nothing is selected, moves the caret ot that position.
*/
default void moveSelectedText(int position) {
IndexRange sel = getSelection();
if((position >= sel.getStart() && position <= sel.getEnd()) || sel.equals(GenericStyledArea.EMPTY_RANGE)) {
// no move, just position the caret
selectRange(position, position);
} else {
StyledDocument<PS, SEG, S> text = this.subDocument(sel.getStart(), sel.getEnd());
if(position > sel.getEnd())
position -= sel.getLength();
createMultiChange(2)
.deleteText(sel)
.insertAbsolutely(position, text)
.commit();
// select moved text
selectRange(position, position + text.length());
}
}
private void handleFirstPrimaryPress(MouseEvent e) {
// ensure focus
view.requestFocus();
CharacterHit hit = view.hit(e.getX(), e.getY());
view.clearTargetCaretOffset();
IndexRange selection = view.getSelection();
if(view.isEditable() &&
selection.getLength() != 0 &&
hit.getCharacterIndex().isPresent() &&
hit.getCharacterIndex().getAsInt() >= selection.getStart() &&
hit.getCharacterIndex().getAsInt() < selection.getEnd()) {
// press inside selection
dragSelection = DragState.POTENTIAL_DRAG;
dragNewSelection = DragState.NO_DRAG;
} else {
dragSelection = DragState.NO_DRAG;
dragNewSelection = DragState.NO_DRAG;
view.getOnOutsideSelectionMousePressed().handle(e);
}
}
private void moveLinesUp(KeyEvent e) {
IndexRange selRange = getSelectedLinesRange(true);
int selStart = selRange.getStart();
int selEnd = selRange.getEnd();
if (selStart == 0)
return;
int before = offsetToLine(selStart - 1);
IndexRange beforeRange = linesToRange(before, before, true);
int beforeStart = beforeRange.getStart();
int beforeEnd = beforeRange.getEnd();
String beforeText = textArea.getText(beforeStart, beforeEnd);
String selText = textArea.getText(selStart, selEnd);
if (!selText.endsWith("\n")) {
selText += "\n";
if (beforeText.endsWith("\n"))
beforeText = beforeText.substring(0, beforeText.length() - 1);
}
// Note: using single textArea.replaceText() to avoid multiple changes in undo history
replaceText(textArea, beforeStart, selEnd, selText + beforeText);
selectRange(textArea, beforeStart, beforeStart + selText.length());
}
private void duplicateLines(boolean up) {
IndexRange selRange = getSelectedLinesRange(true);
int selStart = selRange.getStart();
int selEnd = selRange.getEnd();
String selText = textArea.getText(selStart, selEnd);
if (!selText.endsWith("\n"))
selText += "\n";
replaceText(textArea, selStart, selStart, selText);
if (up)
selectRange(textArea, selStart, selStart + selText.length() - 1);
else {
int newSelStart = selStart + selText.length();
int newSelEnd = newSelStart + selText.length();
if (selText.endsWith("\n"))
newSelEnd--;
selectRange(textArea, newSelStart, newSelEnd);
}
}
@Test
public void test() {
LiveList<Integer> list = new LiveArrayList<>(1, 2, 4);
Var<IndexRange> range = Var.newSimpleVar(new IndexRange(0, 0));
Val<Integer> rangeSum = list.reduceRange(range, (a, b) -> a + b);
assertNull(rangeSum.getValue());
List<Integer> observed = new ArrayList<>();
rangeSum.values().subscribe(sum -> {
observed.add(sum);
if(sum == null) {
range.setValue(new IndexRange(0, 2));
} else if(sum == 3) {
list.addAll(1, Arrays.asList(8, 16));
} else if(sum == 9) {
range.setValue(new IndexRange(2, 4));
}
});
assertEquals(Arrays.asList(null, 3, 9, 18), observed);
}
private void moveBoundary(Direction direction, int amount, int oldBoundaryPosition,
Function<Integer, IndexRange> updatedRange) {
switch (direction) {
case LEFT:
moveBoundary(
() -> oldBoundaryPosition - amount,
(pos) -> 0 <= pos,
updatedRange
);
break;
default: case RIGHT:
moveBoundary(
() -> oldBoundaryPosition + amount,
(pos) -> pos <= area.getLength(),
updatedRange
);
}
}
SelectionPath(Val<IndexRange> range) {
setManaged(false);
this.range = range;
highlightFill.addListener( (ob,ov,nv) -> setFill( nv ) );
setFill( getHighlightFill() );
setStrokeWidth( 0.0 );
}
protected void addTextAround(String prefix, String suffix) {
IndexRange range = mainArea.getSelection();
if (range.getLength() == 0) {
String s = prefix + message("Text") + suffix;
mainArea.insertText(range.getStart(), s);
mainArea.selectRange(range.getStart() + prefix.length(),
range.getStart() + prefix.length() + message("Text").length());
} else {
mainArea.insertText(range.getStart(), prefix);
mainArea.insertText(range.getEnd() + prefix.length(), suffix);
}
mainArea.requestFocus();
}
@FXML
protected void numberedList() {
IndexRange range = mainArea.getSelection();
int start = range.getStart();
int end = range.getEnd();
addTextInFrontOfCurrentLine("1. ");
if (start == end) {
return;
}
start += 3;
end += 3;
int pos;
int count = 1;
while (true) {
pos = mainArea.getText(start, end).indexOf('\n');
if (pos < 0) {
break;
}
count++;
mainArea.insertText(start + pos + 1, count + ". ");
int nlen = 2 + (count + "").length();
start += pos + 1 + nlen;
end += nlen;
int len = mainArea.getLength();
if (start >= end || start >= len || end >= len) {
break;
}
}
mainArea.requestFocus();
}
/**
* Returns the range of homogeneous style that includes the given position.
* If {@code position} points to a boundary between two styled ranges,
* then the range preceding {@code position} is returned.
*/
public IndexRange getStyleRangeAtPosition(int position) {
Position pos = styles.offsetToPosition(position, Backward);
int start = position - pos.getMinor();
int end = start + styles.getStyleSpan(pos.getMajor()).getLength();
return new IndexRange(start, end);
}
public static int mapInt(int value, IndexRange originalRange, IndexRange newlRange) {
if (originalRange == null || newlRange == null || originalRange.getStart() > value || originalRange.getEnd() < value) {
return value;
}
int len = value - originalRange.getStart() + 1;
double ratio = newlRange.getLength() * 1.0 / originalRange.getLength();
return newlRange.getStart() + (int) Math.round(len * ratio);
}
@Override
public void editorSelectionChanged(PreviewContext context, IndexRange range) {
if (range.equals(lastEditorSelection))
return;
lastEditorSelection = range;
runWhenLoaded(() -> {
webView.getEngine().executeScript(highlightNodesAt(range));
});
}
@Override
public void editorSelectionChanged(PreviewContext context, IndexRange range) {
if (range.equals(lastEditorSelection))
return;
lastEditorSelection = range;
List<Range> sequences = context.getRenderer().findSequences(range.getStart(), range.getEnd());
// restore old styles
for (Map.Entry<Integer, StyleSpans<Collection<String>>> e : oldSelectionStylesMap.entrySet())
textArea.setStyleSpans(e.getKey(), e.getValue());
oldSelectionStylesMap.clear();
// set new selection styles
String text = textArea.getText();
for (Range sequence : sequences) {
String rangeStr = "[" + sequence.start + ", " + sequence.end;
int index = 0;
while ((index = text.indexOf(rangeStr, index)) >= 0) {
int endIndex = index + rangeStr.length() + 1;
char after = text.charAt(endIndex - 1);
if ((after == ']' || after == ',') && !oldSelectionStylesMap.containsKey(index)) {
oldSelectionStylesMap.put(index, textArea.getStyleSpans(index, endIndex));
textArea.setStyle(index, endIndex, STYLE_SELECTION);
}
index = endIndex;
}
}
}
private void right(KeyEvent ignore) {
IndexRange sel = view.getSelection();
if(sel.getLength() == 0) {
view.nextChar(SelectionPolicy.CLEAR);
} else {
view.moveTo(sel.getEnd(), SelectionPolicy.CLEAR);
}
}
public void setMarkdown(String markdown) {
// remember old selection range
IndexRange oldSelection = textArea.getSelection();
// replace text
lineSeparator = determineLineSeparator(markdown);
textArea.replaceText(markdown);
// restore old selection range
int newLength = textArea.getLength();
textArea.selectRange(Math.min(oldSelection.getStart(), newLength), Math.min(oldSelection.getEnd(), newLength));
}
List<Pair<Block, String>> formatParagraphs(Node markdownAST, int wrapLength, IndexRange selection, HashSet<BasedSequence> oldParagraphs) {
ArrayList<Pair<Block, String>> formattedParagraphs = new ArrayList<>();
NodeVisitor visitor = new NodeVisitor(Collections.emptyList()) {
@Override
public void visit(Node node) {
if (node instanceof Paragraph || node instanceof HtmlBlock) {
if (selection != null && !isNodeSelected(node, selection))
return;
if (oldParagraphs != null && oldParagraphs.contains(node.getChars()))
return; // ignore unmodified paragraphs
String newText = (node instanceof Paragraph)
? formatParagraph((Paragraph) node, wrapLength)
: formatHtmlBlock((HtmlBlock) node, wrapLength);
// append trailing line separator (if necessary)
if (node.getChars().endsWith("\n"))
newText += "\n";
if (!node.getChars().equals(newText, false))
formattedParagraphs.add(new Pair<>((Block) node, newText));
} else
visitChildren(node);
}
};
visitor.visit(markdownAST);
return formattedParagraphs;
}
@Override
public void copy() {
IndexRange oldSelection = selectLineIfEmpty();
super.copy();
if (oldSelection != null)
selectRange(oldSelection.getStart(), oldSelection.getEnd());
}
private IndexRange selectLineIfEmpty() {
IndexRange oldSelection = null;
if (getSelectedText().isEmpty()) {
oldSelection = getSelection();
selectLine();
nextChar(SelectionPolicy.ADJUST);
}
return oldSelection;
}
@Experimental
static <E> Val<E> reduceRange(
ObservableList<E> list,
ObservableValue<IndexRange> range,
BinaryOperator<E> reduction) {
return new ListRangeReduction<>(list, range, reduction);
}
public IndexRange getPresentItemsRange() {
if(getPresentCount() == 0) {
return new IndexRange(0, 0);
} else {
int lowerBound = tree.locateProgressively(Stats::getPresentCount, 0)
.map(this::locationToPosition);
int upperBound = tree.locateRegressively(Stats::getPresentCount, getPresentCount())
.map(this::locationToPosition);
return new IndexRange(lowerBound, upperBound);
}
}
private IndentSelection rememberIndentSelection() {
IndentSelection isel = new IndentSelection();
IndexRange selection = textArea.getSelection();
int start = selection.getStart();
int end = selection.getEnd();
isel.startLine = offsetToLine(start);
isel.endLine = offsetToLine(end);
isel.startOffsetFromEnd = (start == end || start - lineToStartOffset(isel.startLine) > 0)
? lineToEndOffset(isel.startLine) - start
: -1; // beginning of line
isel.endOffsetFromEnd = lineToEndOffset(isel.endLine) - end;
return isel;
}
private void moveLinesDown(KeyEvent e) {
IndexRange selRange = getSelectedLinesRange(true);
int selStart = selRange.getStart();
int selEnd = selRange.getEnd();
if (selEnd == textArea.getLength())
return;
int after = offsetToLine(selEnd);
IndexRange afterRange = linesToRange(after, after, true);
int afterStart = afterRange.getStart();
int afterEnd = afterRange.getEnd();
String selText = textArea.getText(selStart, selEnd);
String afterText = textArea.getText(afterStart, afterEnd);
if (!afterText.endsWith("\n")) {
afterText += "\n";
if (selText.endsWith("\n"))
selText = selText.substring(0, selText.length() - 1);
}
// Note: using single textArea.replaceText() to avoid multiple changes in undo history
replaceText(textArea, selStart, afterEnd, afterText + selText);
int newSelStart = selStart + afterText.length();
int newSelEnd = newSelStart + selText.length();
selectRange(textArea, newSelStart, newSelEnd);
}
private void surroundSelectionAndReplaceMarker(String leading, String trailing, String hint,
DelimitedNode node, String newOpeningMarker, String newClosingMarker)
{
IndexRange selection = textArea.getSelection();
int start = selection.getStart();
int end = selection.getEnd();
String selectedText = textArea.getSelectedText();
// remove leading and trailing whitespaces from selected text
String trimmedSelectedText = selectedText.trim();
if (trimmedSelectedText.length() < selectedText.length()) {
start += selectedText.indexOf(trimmedSelectedText);
end = start + trimmedSelectedText.length();
}
BasedSequence openingMarker = node.getOpeningMarker();
BasedSequence closingMarker = node.getClosingMarker();
int selStart = start + leading.length() + (newOpeningMarker.length() - openingMarker.length());
int selEnd = selStart + trimmedSelectedText.length();
// insert hint text if selection is empty
if (hint != null && trimmedSelectedText.isEmpty()) {
trimmedSelectedText = hint;
selEnd = selStart + hint.length();
}
// replace text and update selection
// Note: using single textArea.replaceText() to avoid multiple changes in undo history
String before = textArea.getText(openingMarker.getEndOffset(), start);
String after = textArea.getText(end, closingMarker.getStartOffset());
replaceText(textArea, openingMarker.getStartOffset(), closingMarker.getEndOffset(),
newOpeningMarker + before + leading + trimmedSelectedText + trailing + after + newClosingMarker );
selectRange(textArea, selStart, selEnd);
}
ListRangeReduction(
ObservableList<T> input,
ObservableValue<IndexRange> range,
BinaryOperator<T> reduction) {
super(input, reduction);
this.range = range;
}
/**
* Find single node that completely encloses the current selection and match a predicate.
*/
private <T extends Node> T findNodeAtSelection(FindNodePredicate predicate) {
IndexRange selection = textArea.getSelection();
int start = selection.getStart();
int end = selection.getEnd();
List<T> nodes = findNodes(start, end, predicate, false, false);
if (nodes.size() != 1)
return null;
T node = nodes.get(0);
BasedSequence text = (node instanceof DelimitedNode) ? ((DelimitedNode)node).getText() : node.getChars();
return (start >= text.getStartOffset() && end <= text.getEndOffset()) ? node : null;
}