/*
* 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 linesAllowed
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.
*
*