📄 defaultstyleddocument.java
字号:
StyleContext context = (StyleContext) getAttributeContext(); Style newStyle = context.addStyle(nm, parent); // Register change listener. if (styleChangeListener == null) styleChangeListener = new StyleChangeListener(); newStyle.addChangeListener(styleChangeListener); return newStyle; } /** * Create the default root element for this kind of <code>Document</code>. * * @return the default root element for this kind of <code>Document</code> */ protected AbstractDocument.AbstractElement createDefaultRoot() { Element[] tmp; // FIXME: Create a SecionElement here instead of a BranchElement. // Use createBranchElement() and createLeafElement instead. SectionElement section = new SectionElement(); BranchElement paragraph = (BranchElement) createBranchElement(section, null); paragraph.setResolveParent(getStyle(StyleContext.DEFAULT_STYLE)); tmp = new Element[1]; tmp[0] = paragraph; section.replace(0, 0, tmp); LeafElement leaf = new LeafElement(paragraph, null, 0, 1); tmp = new Element[1]; tmp[0] = leaf; paragraph.replace(0, 0, tmp); return section; } /** * Returns the <code>Element</code> that corresponds to the character * at the specified position. * * @param position the position of which we query the corresponding * <code>Element</code> * * @return the <code>Element</code> that corresponds to the character * at the specified position */ public Element getCharacterElement(int position) { Element element = getDefaultRootElement(); while (!element.isLeaf()) { int index = element.getElementIndex(position); element = element.getElement(index); } return element; } /** * Extracts a background color from a set of attributes. * * @param attributes the attributes from which to get a background color * * @return the background color that correspond to the attributes */ public Color getBackground(AttributeSet attributes) { StyleContext context = (StyleContext) getAttributeContext(); return context.getBackground(attributes); } /** * Returns the default root element. * * @return the default root element */ public Element getDefaultRootElement() { return buffer.getRootElement(); } /** * Extracts a font from a set of attributes. * * @param attributes the attributes from which to get a font * * @return the font that correspond to the attributes */ public Font getFont(AttributeSet attributes) { StyleContext context = (StyleContext) getAttributeContext(); return context.getFont(attributes); } /** * Extracts a foreground color from a set of attributes. * * @param attributes the attributes from which to get a foreground color * * @return the foreground color that correspond to the attributes */ public Color getForeground(AttributeSet attributes) { StyleContext context = (StyleContext) getAttributeContext(); return context.getForeground(attributes); } /** * Returns the logical <code>Style</code> for the specified position. * * @param position the position from which to query to logical style * * @return the logical <code>Style</code> for the specified position */ public Style getLogicalStyle(int position) { Element paragraph = getParagraphElement(position); AttributeSet attributes = paragraph.getAttributes(); return (Style) attributes.getResolveParent(); } /** * Returns the paragraph element for the specified position. * If the position is outside the bounds of the document's root element, * then the closest element is returned. That is the last paragraph if * <code>position >= endIndex</code> or the first paragraph if * <code>position < startIndex</code>. * * @param position the position for which to query the paragraph element * * @return the paragraph element for the specified position */ public Element getParagraphElement(int position) { BranchElement root = (BranchElement) getDefaultRootElement(); int start = root.getStartOffset(); int end = root.getEndOffset(); if (position >= end) position = end - 1; else if (position < start) position = start; Element par = root.positionToElement(position); assert par != null : "The paragraph element must not be null"; return par; } /** * Looks up and returns a named <code>Style</code>. * * @param nm the name of the <code>Style</code> * * @return the found <code>Style</code> of <code>null</code> if no such * <code>Style</code> exists */ public Style getStyle(String nm) { StyleContext context = (StyleContext) getAttributeContext(); return context.getStyle(nm); } /** * Removes a named <code>Style</code> from the style hierarchy. * * @param nm the name of the <code>Style</code> to be removed */ public void removeStyle(String nm) { StyleContext context = (StyleContext) getAttributeContext(); context.removeStyle(nm); } /** * Sets text attributes for the fragment specified by <code>offset</code> * and <code>length</code>. * * @param offset the start offset of the fragment * @param length the length of the fragment * @param attributes the text attributes to set * @param replace if <code>true</code>, the attributes of the current * selection are overridden, otherwise they are merged */ public void setCharacterAttributes(int offset, int length, AttributeSet attributes, boolean replace) { DefaultDocumentEvent ev = new DefaultDocumentEvent(offset, length, DocumentEvent.EventType.CHANGE); // Modify the element structure so that the interval begins at an element // start and ends at an element end. buffer.change(offset, length, ev); Element root = getDefaultRootElement(); // Visit all paragraph elements within the specified interval int paragraphCount = root.getElementCount(); for (int pindex = 0; pindex < paragraphCount; pindex++) { Element paragraph = root.getElement(pindex); // Skip paragraphs that lie outside the interval. if ((paragraph.getStartOffset() > offset + length) || (paragraph.getEndOffset() < offset)) continue; // Visit content elements within this paragraph int contentCount = paragraph.getElementCount(); for (int cindex = 0; cindex < contentCount; cindex++) { Element content = paragraph.getElement(cindex); // Skip content that lies outside the interval. if ((content.getStartOffset() > offset + length) || (content.getEndOffset() < offset)) continue; if (content instanceof AbstractElement) { AbstractElement el = (AbstractElement) content; if (replace) el.removeAttributes(el); el.addAttributes(attributes); } else throw new AssertionError("content elements are expected to be" + "instances of " + "javax.swing.text.AbstractDocument.AbstractElement"); } } fireChangedUpdate(ev); } /** * Sets the logical style for the paragraph at the specified position. * * @param position the position at which the logical style is added * @param style the style to set for the current paragraph */ public void setLogicalStyle(int position, Style style) { Element el = getParagraphElement(position); if (el instanceof AbstractElement) { AbstractElement ael = (AbstractElement) el; ael.setResolveParent(style); } else throw new AssertionError("paragraph elements are expected to be" + "instances of javax.swing.text.AbstractDocument.AbstractElement"); } /** * Sets text attributes for the paragraph at the specified fragment. * * @param offset the beginning of the fragment * @param length the length of the fragment * @param attributes the text attributes to set * @param replace if <code>true</code>, the attributes of the current * selection are overridden, otherwise they are merged */ public void setParagraphAttributes(int offset, int length, AttributeSet attributes, boolean replace) { int index = offset; while (index < offset + length) { AbstractElement par = (AbstractElement) getParagraphElement(index); AttributeContext ctx = getAttributeContext(); if (replace) par.removeAttributes(par); par.addAttributes(attributes); index = par.getElementCount(); } } /** * Called in response to content insert actions. This is used to * update the element structure. * * @param ev the <code>DocumentEvent</code> describing the change * @param attr the attributes for the change */ protected void insertUpdate(DefaultDocumentEvent ev, AttributeSet attr) { super.insertUpdate(ev, attr); int offset = ev.getOffset(); int length = ev.getLength(); int endOffset = offset + length; Segment txt = new Segment(); try { getText(offset, length, txt); } catch (BadLocationException ex) { AssertionError ae = new AssertionError("Unexpected bad location"); ae.initCause(ex); throw ae; } int len = 0; Vector specs = new Vector(); Element prev = getCharacterElement(offset); Element next = getCharacterElement(endOffset); for (int i = offset; i < endOffset; ++i) { len++; if (txt.array[i] == '\n') { ElementSpec spec = new ElementSpec(attr, ElementSpec.ContentType, len); // If we are at the last index, then check if we could probably be // joined with the next element. if (i == endOffset - 1) { if (next.getAttributes().isEqual(attr)) spec.setDirection(ElementSpec.JoinNextDirection); } // If we are at the first new element, then check if it could be // joined with the previous element. else if (specs.size() == 0) { if (prev.getAttributes().isEqual(attr)) spec.setDirection(ElementSpec.JoinPreviousDirection); } specs.add(spec); // Add ElementSpecs for the newline. ElementSpec endTag = new ElementSpec(null, ElementSpec.EndTagType); specs.add(endTag); ElementSpec startTag = new ElementSpec(null, ElementSpec.StartTagType); startTag.setDirection(ElementSpec.JoinFractureDirection); specs.add(startTag); len = 0; offset += len; } } // Create last element if last character hasn't been a newline. if (len > 0) { ElementSpec spec = new ElementSpec(attr, ElementSpec.ContentType, len); // If we are at the first new element, then check if it could be // joined with the previous element. if (specs.size() == 0) { if (prev.getAttributes().isEqual(attr)) spec.setDirection(ElementSpec.JoinPreviousDirection); } // Check if we could probably be joined with the next element. else if (next.getAttributes().isEqual(attr)) spec.setDirection(ElementSpec.JoinNextDirection); specs.add(spec); } ElementSpec[] elSpecs = (ElementSpec[]) specs.toArray(new ElementSpec[specs.size()]); buffer.insert(offset, length, elSpecs, ev); } /** * Returns an enumeration of all style names. * * @return an enumeration of all style names */ public Enumeration getStyleNames() { StyleContext context = (StyleContext) getAttributeContext(); return context.getStyleNames(); } /** * Called when any of this document's styles changes. * * @param style the style that changed */ protected void styleChanged(Style style) { // Nothing to do here. This is intended to be overridden by subclasses. } /** * Inserts a bulk of structured content at once. * * @param offset the offset at which the content should be inserted * @param data the actual content spec to be inserted */ protected void insert(int offset, ElementSpec[] data) throws BadLocationException { writeLock(); // First we insert the content. int index = offset; for (int i = 0; i < data.length; i++) { ElementSpec spec = data[i]; if (spec.getArray() != null && spec.getLength() > 0) { String insertString = new String(spec.getArray(), spec.getOffset(), spec.getLength()); content.insertString(index, insertString); } index += spec.getLength(); } // Update the view structure. DefaultDocumentEvent ev = new DefaultDocumentEvent(offset, index - offset, DocumentEvent.EventType.INSERT); for (int i = 0; i < data.length; i++) { ElementSpec spec = data[i]; AttributeSet atts = spec.getAttributes(); if (atts != null) insertUpdate(ev, atts); } // Finally we must update the document structure and fire the insert update // event. buffer.insert(offset, index - offset, data, ev); fireInsertUpdate(ev); writeUnlock(); } /** * Initializes the <code>DefaultStyledDocument</code> with the specified * data. * * @param data the specification of the content with which the document is * initialized */ protected void create(ElementSpec[] data) { try { // Clear content. content.remove(0, content.length()); // Clear buffer and root element. buffer = new ElementBuffer(createDefaultRoot()); // Insert the data. insert(0, data); } catch (BadLocationException ex) { AssertionError err = new AssertionError("Unexpected bad location"); err.initCause(ex); throw err; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -