TransferableScribblePanepublic class TransferableScribblePane extends JComponent This rewrite of ScribblePane allows individual PolyLine lines to be
selected, cut, copied, pasted, dragged, and dropped. |
Fields Summary |
---|
List | lines | je3.graphics.PolyLine | currentLine | je3.graphics.PolyLine | selectedLine | boolean | canDragImage | static Stroke | stroke | static Stroke | selectedStroke | static Border | normalBorder | static Border | canDropBorder | public DragGestureListener | dragGestureListenerThis DragGestureListener is notified when the user initiates a drag.
We passed it to the DragGestureRecognizer we created in the constructor. | public DragSourceListener | dragSourceListenerIf this component is the source of a drag, then this DragSourceListener
will receive notifications about the progress of the drag. The only
one we use here is dragDropEnd() which is called after a drop occurs.
We could use the other methods to change cursors or perform other
"drag over effects" | public DropTargetListener | dropTargetListenerThis DropTargetListener is notified when something is dragged over
this component. |
Constructors Summary |
---|
public TransferableScribblePane()
// The constructor method
setPreferredSize(new Dimension(450,200)); // We need a default size
setBorder(normalBorder); // and a border.
lines = new ArrayList(); // Start with an empty list of lines
// Register interest in mouse button and mouse motion events.
enableEvents(AWTEvent.MOUSE_EVENT_MASK |
AWTEvent.MOUSE_MOTION_EVENT_MASK);
// Enable drag-and-drop by specifying a listener that will be
// notified when a drag begins. dragGestureListener is defined later.
DragSource dragSource = DragSource.getDefaultDragSource();
dragSource.createDefaultDragGestureRecognizer(this,
DnDConstants.ACTION_COPY_OR_MOVE,
dragGestureListener);
// Enable drops on this component by registering a listener to
// be notified when something is dragged or dropped over us.
this.setDropTarget(new DropTarget(this, dropTargetListener));
// Check whether the system allows us to drag an image of the line
canDragImage = dragSource.isDragImageSupported();
|
Methods Summary |
---|
public void | clear()Erase all lines and repaint.
lines.clear();
repaint();
| public void | copy()Copy the selected line to the clipboard
if (selectedLine == null) return; // Only works if a line is selected
// Get the system Clipboard object.
Clipboard c = this.getToolkit().getSystemClipboard();
// Wrap the selected line in a TransferablePolyLine object
// and pass it to the clipboard, with an object to receive notification
// when some other application takes ownership of the clipboard
c.setContents(new TransferablePolyLine((PolyLine)selectedLine.clone()),
new ClipboardOwner() {
public void lostOwnership(Clipboard c,Transferable t){
// This method is called when something else
// is copied to the clipboard. We could use it
// to deselect the selected line, if we wanted.
}
});
| public void | cut()Copy the selected line to the clipboard, then delete it
if (selectedLine == null) return; // Only works if a line is selected
copy(); // Do a Copy operation...
lines.remove(selectedLine); // and then erase the selected line
selectedLine = null;
repaint(); // Repaint because a line was removed
| public void | paintComponent(java.awt.Graphics g)We override this method to draw ourselves.
// Let the superclass do its painting first
super.paintComponent(g);
// Make a copy of the Graphics context so we can modify it
Graphics2D g2 = (Graphics2D) (g.create());
// Our superclass doesn't paint the background, so do this ourselves.
g2.setColor(getBackground());
g2.fillRect(0, 0, getWidth(), getHeight());
// Set the line width and color to use for the foreground
g2.setStroke(stroke);
g2.setColor(this.getForeground());
// Now loop through the PolyLine shapes and draw them all
int numlines = lines.size();
for(int i = 0; i < numlines; i++) {
PolyLine line = (PolyLine)lines.get(i);
if (line == selectedLine) { // If it is the selected line
g2.setStroke(selectedStroke); // Set dash pattern
g2.draw(line); // Draw the line
g2.setStroke(stroke); // Revert to solid lines
}
else g2.draw(line); // Otherwise just draw the line
}
| public void | paste()Get a PolyLine from the clipboard, if one exists, and display it
// Get the system Clipboard and ask for its Transferable contents
Clipboard c = this.getToolkit().getSystemClipboard();
Transferable t = c.getContents(this);
// See if we can extract a PolyLine from the Transferable object
PolyLine line;
try {
line = (PolyLine)t.getTransferData(TransferablePolyLine.FLAVOR);
}
catch(Exception e) { // UnsupportedFlavorException or IOException
// If we get here, the clipboard doesn't hold a PolyLine we can use
getToolkit().beep(); // So beep to indicate the error
return;
}
lines.add(line); // We got a line from the clipboard, so add it to list
repaint(); // And repaint to make the line appear
| public void | processMouseEvent(java.awt.event.MouseEvent e)This method is called on mouse button events. It begins a new line
or tries to select an existing line.
if (e.getButton() == MouseEvent.BUTTON1) { // Left mouse button
if (e.getID() == MouseEvent.MOUSE_PRESSED) { // Pressed down
if (e.isShiftDown()) { // with Shift key
// If the shift key is down, try to select a line
int x = e.getX();
int y = e.getY();
// Loop through the lines checking to see if we hit one
PolyLine selection = null;
int numlines = lines.size();
for(int i = 0; i < numlines; i++) {
PolyLine line = (PolyLine)lines.get(i);
if (line.intersects(x-2, y-2, 4, 4)) {
selection = line;
e.consume();
break;
}
}
// If we found an intersecting line, save it and repaint
if (selection != selectedLine) { // If selection changed
selectedLine = selection; // remember which is selected
repaint(); // will make selection dashed
}
}
else if (!e.isControlDown()) { // no shift key or ctrl key
// Start a new line on mouse down without shift or ctrl
currentLine = new PolyLine(e.getX(), e.getY());
lines.add(currentLine);
e.consume();
}
}
else if (e.getID() == MouseEvent.MOUSE_RELEASED) {// Left Button Up
// End the line on mouse up
if (currentLine != null) {
currentLine = null;
e.consume();
}
}
}
// The superclass method dispatches to registered event listeners
super.processMouseEvent(e);
| public void | processMouseMotionEvent(java.awt.event.MouseEvent e)This method is called for mouse motion events.
We don't have to detect gestures that initiate a drag in this method.
That is the job of the DragGestureRecognizer we created in the
constructor: it will notify the DragGestureListener defined below.
if (e.getID() == MouseEvent.MOUSE_DRAGGED && // If we're dragging
currentLine != null) { // and a line exists
currentLine.addSegment(e.getX(), e.getY()); // Add a line segment
e.consume(); // Eat the event
repaint(); // Redisplay all lines
}
super.processMouseMotionEvent(e); // Invoke any listeners
|
|