123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440 |
- /*
- * Copyright (c) 2006-2010 Chris Smith, Shane Mc Cormack, Gregory Holmes
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
- package com.dmdirc.addons.ui_swing.textpane;
-
- import com.dmdirc.FrameContainer;
-
- import java.awt.Point;
- import java.awt.Toolkit;
- import java.awt.datatransfer.StringSelection;
- import java.awt.event.AdjustmentEvent;
- import java.awt.event.AdjustmentListener;
- import java.awt.event.MouseEvent;
- import java.awt.event.MouseMotionAdapter;
- import java.awt.event.MouseMotionListener;
- import java.awt.event.MouseWheelEvent;
- import java.awt.event.MouseWheelListener;
-
- import javax.swing.BoundedRangeModel;
- import javax.swing.DefaultBoundedRangeModel;
- import javax.swing.JComponent;
- import javax.swing.JScrollBar;
-
- import net.miginfocom.swing.MigLayout;
-
- /**
- * Styled, scrollable text pane.
- */
- public final class TextPane extends JComponent implements AdjustmentListener,
- MouseWheelListener, IRCDocumentListener {
-
- /**
- * A version number for this class. It should be changed whenever the class
- * structure is changed (or anything else that would prevent serialized
- * objects being unserialized with the new class).
- */
- private static final long serialVersionUID = 5;
- /** Scrollbar model. */
- private final BoundedRangeModel scrollModel;
- /** Canvas object, used to draw text. */
- private final TextPaneCanvas canvas;
- /** IRCDocument. */
- private final IRCDocument document;
- /** Parent Frame. */
- private final FrameContainer frame;
-
- /**
- * Creates a new instance of TextPane.
- *
- * @param frame Parent Frame
- */
- public TextPane(final FrameContainer frame) {
- super();
- setUI(new TextPaneUI());
-
- this.frame = frame;
- document = new IRCDocument(frame.getConfigManager());
- frame.getConfigManager().addChangeListener("ui", "textPaneFontName",
- document);
- frame.getConfigManager().addChangeListener("ui", "textPaneFontSize",
- document);
-
- setLayout(new MigLayout("fill"));
- canvas = new TextPaneCanvas(this, document);
- add(canvas, "dock center");
- scrollModel = new DefaultBoundedRangeModel();
- scrollModel.setMaximum(document.getNumLines());
- scrollModel.setExtent(0);
- final JScrollBar scrollBar = new JScrollBar(JScrollBar.VERTICAL);
- scrollBar.setModel(scrollModel);
- add(scrollBar, "dock east");
- scrollBar.addAdjustmentListener(this);
- scrollBar.addAdjustmentListener(canvas);
-
- addMouseWheelListener(this);
- document.addIRCDocumentListener(this);
- setAutoscrolls(true);
-
- MouseMotionListener doScrollRectToVisible = new MouseMotionAdapter() {
-
- /** {@inheritDoc} */
- @Override
- public void mouseDragged(MouseEvent e) {
- if (e.getXOnScreen() > getLocationOnScreen().getX() && e.
- getXOnScreen() < (getLocationOnScreen().
- getX() + getWidth()) && e.getModifiersEx() ==
- MouseEvent.BUTTON1_DOWN_MASK) {
- if (getLocationOnScreen().getY() > e.getYOnScreen()) {
- scrollModel.setValue(scrollBar.getValue() - 1);
- } else if (getLocationOnScreen().getY() + getHeight() <
- e.getYOnScreen()) {
- scrollModel.setValue(scrollBar.getValue() + 1);
- }
- canvas.highlightEvent(MouseEventType.DRAG, e);
- }
- }
- };
- addMouseMotionListener(doScrollRectToVisible);
- }
-
- /** {@inheritDoc} */
- @Override
- public void updateUI() {
- setUI(new TextPaneUI());
- }
-
- /**
- * Returns the last visible line in the textpane.
- *
- * @return Last visible line index
- */
- public int getLastVisibleLine() {
- return scrollModel.getValue();
- }
-
- /**
- * Sets the scrollbar's maximum position. If the current position is
- * within <code>linesAllowed</code> of the end of the document, the
- * scrollbar's current position is set to the end of the document.
- *
- * @param linesAllowed The number of lines allowed below the current position
- * @since 0.6
- */
- protected void setScrollBarMax(final int linesAllowed) {
- final int lines = document.getNumLines() - 1;
- final int currentLine = scrollModel.getValue();
- final int allowedDeviation = lines - linesAllowed;
-
- scrollModel.setMaximum(lines);
-
- boolean setToMax = currentLine == allowedDeviation;
- if (allowedDeviation == -1) {
- setToMax = true;
- }
-
- if (!scrollModel.getValueIsAdjusting() && setToMax) {
- scrollModel.setValue(lines);
- }
- canvas.recalc();
- }
-
- /**
- * Sets the new position for the scrollbar and the associated position
- * to render the text from.
- * @param position new position of the scrollbar
- */
- public void setScrollBarPosition(final int position) {
- scrollModel.setValue(position);
- }
-
- /**
- * {@inheritDoc}
- *
- * @param e Mouse wheel event
- */
- @Override
- public void adjustmentValueChanged(final AdjustmentEvent e) {
- scrollModel.setValue(e.getValue());
- }
-
- /**
- * {@inheritDoc}
- *
- * @param e Mouse wheel event
- */
- @Override
- public void mouseWheelMoved(final MouseWheelEvent e) {
- if (e.getWheelRotation() > 0) {
- scrollModel.setValue(scrollModel.getValue() + e.getScrollAmount());
- } else {
- scrollModel.setValue(scrollModel.getValue() - e.getScrollAmount());
- }
- }
-
- /**
- *
- * Returns the line information from a mouse click inside the textpane.
- *
- * @param point mouse position
- *
- * @return line number, line part, position in whole line
- */
- public LineInfo getClickPosition(final Point point) {
- return canvas.getClickPosition(point);
- }
-
- /**
- * Returns the selected text.
- *
- * <li>0 = start line</li>
- * <li>1 = start char</li>
- * <li>2 = end line</li>
- * <li>3 = end char</li>
- *
- * @return Selected text
- */
- public String getSelectedText() {
- final StringBuffer selectedText = new StringBuffer();
- final LinePosition selectedRange = canvas.getSelectedRange();
-
- if (selectedRange.getStartLine() == -1) {
- return null;
- }
-
- for (int i = selectedRange.getStartLine(); i <=
- selectedRange.getEndLine();
- i++) {
- if (i != selectedRange.getStartLine()) {
- selectedText.append('\n');
- }
- if (document.getNumLines() <= i) {
- return selectedText.toString();
- }
- final String line = document.getLine(i).getText();
- if (!line.isEmpty()) {
- if (selectedRange.getEndLine() == selectedRange.getStartLine()) {
- //loop through range
- if (selectedRange.getStartPos() != -1 && selectedRange.
- getEndPos() != -1) {
- selectedText.append(line.substring(
- selectedRange.getStartPos(),
- selectedRange.getEndPos()));
- }
- } else if (i == selectedRange.getStartLine()) {
- //loop from start of range to the end
- if (selectedRange.getStartPos() != -1) {
- selectedText.append(line.substring(
- selectedRange.getStartPos(), line.length()));
- }
- } else if (i == selectedRange.getEndLine()) {
- //loop from start to end of range
- if (selectedRange.getEndPos() != -1) {
- selectedText.append(line.substring(0, selectedRange.
- getEndPos()));
- }
- } else {
- //loop the whole line
- selectedText.append(line);
- }
- }
- }
-
- return selectedText.toString();
- }
-
- /**
- * Returns the selected range.
- *
- * @return selected range
- */
- public LinePosition getSelectedRange() {
- return canvas.getSelectedRange();
- }
-
- /**
- * Returns whether there is a selected range.
- *
- * @return true iif there is a selected range
- */
- public boolean hasSelectedRange() {
- final LinePosition selectedRange = canvas.getSelectedRange();
- return !(selectedRange.getStartLine() == selectedRange.getEndLine() &&
- selectedRange.getStartPos() == selectedRange.getEndPos());
- }
-
- /**
- * Selects the specified region of text.
- *
- * @param position Line position
- */
- public void setSelectedTexT(final LinePosition position) {
- canvas.setSelectedRange(position);
- }
-
- /**
- * Returns the type of text this click represents.
- *
- * @param lineInfo Line info of click.
- *
- * @return Click type for specified position
- */
- public ClickType getClickType(final LineInfo lineInfo) {
- return canvas.getClickType(lineInfo);
- }
-
- /**
- * Returns the surrouding word at the specified position.
- *
- * @param lineNumber Line number to get word from
- * @param index Position to get surrounding word
- *
- * @return Surrounding word
- */
- public String getWordAtIndex(final int lineNumber, final int index) {
- if (lineNumber == -1) {
- return "";
- }
- final int[] indexes =
- canvas.getSurroundingWordIndexes(document.getLine(lineNumber).
- getText(),
- index);
- return document.getLine(lineNumber).getText().substring(indexes[0],
- indexes[1]);
- }
-
- /**
- * Returns the atrriute value for the specified location.
- *
- * @param lineInfo Specified location
- *
- * @return Specified value
- */
- public Object getAttributeValueAtPoint(LineInfo lineInfo) {
- return canvas.getAttributeValueAtPoint(lineInfo);
- }
-
- /** Adds the selected text to the clipboard. */
- public void copy() {
- if (getSelectedText() != null && !getSelectedText().isEmpty()) {
- Toolkit.getDefaultToolkit().getSystemClipboard().setContents(
- new StringSelection(getSelectedText()), null);
- }
- }
-
- /** Clears the textpane. */
- public void clear() {
- document.clear();
- scrollModel.setValue(0);
- setScrollBarMax(1);
- canvas.recalc();
- }
-
- /** Clears the selection. */
- public void clearSelection() {
- canvas.clearSelection();
- }
-
- /**
- * Trims the document to the specified number of lines.
- *
- * @param numLines Number of lines to trim the document to
- */
- public void trim(final int numLines) {
- if (document.getNumLines() < numLines) {
- return;
- }
- final int trimmedLines = document.getNumLines() - numLines;
- final LinePosition selectedRange = getSelectedRange();
-
- selectedRange.setStartLine(selectedRange.getStartLine() - trimmedLines);
- selectedRange.setEndLine(selectedRange.getEndLine() - trimmedLines);
-
- if (selectedRange.getStartLine() < 0) {
- selectedRange.setStartLine(0);
- }
- if (selectedRange.getEndLine() < 0) {
- selectedRange.setEndLine(0);
- }
-
- setSelectedTexT(selectedRange);
- document.trim(numLines);
- }
-
- /** Scrolls one page up in the textpane. */
- public void pageDown() {
- scrollModel.setValue(scrollModel.getValue() + 10);
- }
-
- /** Scrolls one page down in the textpane. */
- public void pageUp() {
- scrollModel.setValue(scrollModel.getValue() - 10);
- }
-
- /** {@inheritDoc}. */
- @Override
- public void lineAdded(final int line, final int size) {
- setScrollBarMax(1);
- }
-
- /** {@inheritDoc}. */
- @Override
- public void trimmed(final int numLines) {
- setScrollBarMax(1);
- }
-
- /** {@inheritDoc}. */
- @Override
- public void cleared() {
- canvas.recalc();
- }
-
- /** {@inheritDoc}. */
- @Override
- public void linesAdded(int line, int length, int size) {
- setScrollBarMax(length);
- }
-
- /** {@inheritDoc}. */
- @Override
- public void repaintNeeded() {
- canvas.recalc();
- }
-
- /**
- * Retrieves this textpane's IRCDocument.
- *
- * @return This textpane's IRC document
- */
- public IRCDocument getDocument() {
- return document;
- }
-
- /**
- * Retrives the parent framecontainer for this textpane.
- *
- * @return Parent frame container
- */
- public FrameContainer getFrameContainer() {
- return frame;
- }
- }
|