📄 jxeditorpane.java
字号:
boolean cellHasFocus) { super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); setText((String)itemMap.get(value)); return this; } } // TODO: Should have a rendererer which does stuff like: // Paragraph, Heading 1, etc... } /** * Applys the tag to the current selection */ protected void applyTag(HTML.Tag tag) { Document doc = getDocument(); if (!(doc instanceof HTMLDocument)) { return; } HTMLDocument hdoc = (HTMLDocument)doc; int start = getSelectionStart(); int end = getSelectionEnd(); Element element = hdoc.getParagraphElement(start); MutableAttributeSet newAttrs = new SimpleAttributeSet(element.getAttributes()); newAttrs.addAttribute(StyleConstants.NameAttribute, tag); hdoc.setParagraphAttributes(start, end - start, newAttrs, true); } /** * The paste method has been overloaded to strip off the <html><body> tags * This doesn't really work. */ public void paste() { Clipboard clipboard = getToolkit().getSystemClipboard(); Transferable content = clipboard.getContents(this); if (content != null) { DataFlavor[] flavors = content.getTransferDataFlavors(); try { for (int i = 0; i < flavors.length; i++) { if (String.class.equals(flavors[i].getRepresentationClass())) { Object data = content.getTransferData(flavors[i]); if (flavors[i].isMimeTypeEqual("text/plain")) { // This works but we lose all the formatting. replaceSelection(data.toString()); break; } } } } catch (Exception ex) { ex.printStackTrace(); } } } private void find() { SearchFactory.getInstance().showFindInput(this, getSearchable()); } /** * * @returns a not-null Searchable for this editor. */ public Searchable getSearchable() { if (searchable == null) { searchable = new DocumentSearchable(); } return searchable; } /** * sets the Searchable for this editor. If null, a default * searchable will be used. * * @param searchable */ public void setSearchable(Searchable searchable) { this.searchable = searchable; } public class DocumentSearchable implements Searchable { public int search(String searchString) { return search(searchString, -1); } public int search(String searchString, int columnIndex) { return search(searchString, columnIndex, false); } public int search(String searchString, int columnIndex, boolean backward) { Pattern pattern = null; if (!isEmpty(searchString)) { pattern = Pattern.compile(searchString, 0); } return search(pattern, columnIndex, backward); } /** * checks if the searchString should be interpreted as empty. * here: returns true if string is null or has zero length. * * @param searchString * @return */ protected boolean isEmpty(String searchString) { return (searchString == null) || searchString.length() == 0; } public int search(Pattern pattern) { return search(pattern, -1); } public int search(Pattern pattern, int startIndex) { return search(pattern, startIndex, false); } int lastFoundIndex = -1; MatchResult lastMatchResult; String lastRegEx; /** * @return start position of matching string or -1 */ public int search(Pattern pattern, final int startIndex, boolean backwards) { if ((pattern == null) || (getDocument().getLength() == 0) || ((startIndex > -1) && (getDocument().getLength() < startIndex))) { updateStateAfterNotFound(); return -1; } int start = startIndex; if (maybeExtendedMatch(startIndex)) { if (foundExtendedMatch(pattern, start)) { return lastFoundIndex; } start++; } int length; if (backwards) { start = 0; if (startIndex < 0) { length = getDocument().getLength() - 1; } else { length = -1 + startIndex; } } else { // start = startIndex + 1; if (start < 0) start = 0; length = getDocument().getLength() - start; } Segment segment = new Segment(); try { getDocument().getText(start, length, segment); } catch (Exception ex) { ex.printStackTrace(); } Matcher matcher = pattern.matcher(segment.toString()); MatchResult currentResult = getMatchResult(matcher, !backwards); if (currentResult != null) { updateStateAfterFound(currentResult, start); } else { updateStateAfterNotFound(); } return lastFoundIndex; } /** * Search from same startIndex as the previous search. * Checks if the match is different from the last (either * extended/reduced) at the same position. Returns true * if the current match result represents a different match * than the last, false if no match or the same. * * @param pattern * @param start * @return */ private boolean foundExtendedMatch(Pattern pattern, int start) { // JW: logic still needs cleanup... if (pattern.pattern().equals(lastRegEx)) { return false; } int length = getDocument().getLength() - start; Segment segment = new Segment(); try { getDocument().getText(start, length, segment); } catch (Exception ex) { ex.printStackTrace(); } Matcher matcher = pattern.matcher(segment.toString()); MatchResult currentResult = getMatchResult(matcher, true); if (currentResult != null) { // JW: how to compare match results reliably? // the group().equals probably isn't the best idea... // better check pattern? if ((currentResult.start() == 0) && (!lastMatchResult.group().equals(currentResult.group()))) { updateStateAfterFound(currentResult, start); return true; } } return false; } /** * Checks if the startIndex is a candidate for trying a re-match. * * * @param startIndex * @return true if the startIndex should be re-matched, false if not. */ private boolean maybeExtendedMatch(final int startIndex) { return (startIndex >= 0) && (startIndex == lastFoundIndex); } /** * @param currentResult * @param offset * @return */ private int updateStateAfterFound(MatchResult currentResult, final int offset) { int end = currentResult.end() + offset; int found = currentResult.start() + offset; select(found, end); getCaret().setSelectionVisible(true); lastFoundIndex = found; lastMatchResult = currentResult; lastRegEx = ((Matcher) lastMatchResult).pattern().pattern(); return found; } /** * @param matcher * @return */ private MatchResult getMatchResult(Matcher matcher, boolean useFirst) { MatchResult currentResult = null; while (matcher.find()) { currentResult = matcher.toMatchResult(); if (useFirst) break; } return currentResult; } /** */ private void updateStateAfterNotFound() { lastFoundIndex = -1; lastMatchResult = null; lastRegEx = null; setCaretPosition(getSelectionEnd()); } } public boolean hasCommand(Object command) { return targetSupport.hasCommand(command); } public Object[] getCommands() { return targetSupport.getCommands(); } public boolean doCommand(Object command, Object value) { return targetSupport.doCommand(command, value); } /** * Listens to the caret placement and adjusts the editing * properties as appropriate. * * Should add more attributes as required. */ private class CaretHandler implements CaretListener { public void caretUpdate(CaretEvent evt) { StyledDocument document = (StyledDocument)getDocument(); int dot = evt.getDot(); Element elem = document.getCharacterElement(dot); AttributeSet set = elem.getAttributes(); ActionManager manager = ActionManager.getInstance(); manager.setSelected("font-bold", StyleConstants.isBold(set)); manager.setSelected("font-italic", StyleConstants.isItalic(set)); manager.setSelected("font-underline", StyleConstants.isUnderline(set)); elem = document.getParagraphElement(dot); set = elem.getAttributes(); // Update the paragraph selector if applicable. if (selector != null) { selector.setSelectedItem(set.getAttribute(StyleConstants.NameAttribute)); } switch (StyleConstants.getAlignment(set)) { // XXX There is a bug here. the setSelected method // should only affect the UI actions rather than propagate // down into the action map actions. case StyleConstants.ALIGN_LEFT: manager.setSelected("left-justify", true); break; case StyleConstants.ALIGN_CENTER: manager.setSelected("center-justify", true); break; case StyleConstants.ALIGN_RIGHT: manager.setSelected("right-justify", true); break; } } } /** * Handles sloppy HTML. This implementation currently only looks for * tags that have a / at the end (self-closing tags) and fixes them * to work with the version of HTML supported by HTMLEditorKit * <p>TODO: Need to break this functionality out so it can take pluggable * replacement code blocks, allowing people to write custom replacement * routines. The idea is that with some simple modifications a lot more * sloppy HTML can be rendered correctly. * * @author rbair */ private static final class SloppyHTMLEditorKit extends HTMLEditorKit { public void read(Reader in, Document doc, int pos) throws IOException, BadLocationException { //read the reader into a String StringBuffer buffer = new StringBuffer(); int length = -1; char[] data = new char[1024]; while ((length = in.read(data)) != -1) { buffer.append(data, 0, length); } //TODO is this regex right? StringReader reader = new StringReader(buffer.toString().replaceAll("/>", ">")); super.read(reader, doc, pos); } } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -