alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 *			Sun Public License Notice
 *
 * The contents of this file are subject to the Sun Public License Version
 * 1.0 (the "License"). You may not use this file except in compliance
 * with the License. A copy of the License is available at
 * http://www.sun.com/
 * 
 * The Original Code is Terminal Emulator.
 * The Initial Developer of the Original Code is Sun Microsystems, Inc..
 * Portions created by Sun Microsystems, Inc. are Copyright (C) 2001.
 * All Rights Reserved.
 *
 * Contributor(s): Ivan Soleimanipour.
 */

/*
 * "Sel.java"
 * Sel.java 1.22 01/07/26
 */

package org.netbeans.lib.terminalemulator;

import java.awt.*;
import java.awt.datatransfer.*;

/**
 * Selection expert:
 * 
    *
  • Tracks gestures *
  • Retrieves actual selected text *
  • Paints the selection into a given Graphic *
* * The following actions are understood and dealt with: *
*
track() *
in general extends a selection. * It is usually connecetd to a mouse drag event. *
track() *
will initiate a character-sized selection if no selection exists. *
select_word() *
selects a "word" after which track() extends the selection by words. * It is usually connected to a left double-click. *
slect_line() *
selects a line after which track() extend the selection by lines. * It is usually connected to a left triple-click. *
done() *
stops tracking. The current selection is stuffed into the clipboard. * It is usually connected to a left release. *
extend() *
only extends an existing selection. (Doesn't start one like track) * It is usually connected to a mouse right-press. *
cancel() nulls the selection. *
*

* A Selection has two components that need tracking, the visual feedback * and the selected text. As the history scrolls out the visual feedback * will be eliminated, but we (SHOULD but don't yet) retain the text so * that copy actions still retreieve it properly. DtTerm actually * suffers from this. *

* The selection has an origin and an extent. In general the origin and * extent are not ordered (that is extent might be _before_ origin). they * get ordered as needed. */ class Sel implements ClipboardOwner { // What granularity of selection are we working with private static final int SEL_NONE = 0; private static final int SEL_CHAR = 1; private static final int SEL_WORD = 2; private static final int SEL_LINE = 3; // See intersection() for explanation. public static final int INT_NONE = 0; public static final int INT_ABOVE = 1; public static final int INT_ON = 2; public static final int INT_STRADDLES = 3; public static final int INT_BELOW = 4; private int sel_tracking; private int old_sel_tracking; // origin and extent are kept in absolute RowCol coordinates private Coord sel_origin; /* TMP private */ public Coord sel_extent; // The word that was initially selected by select_word // Used by 'track()'. private Extent initial_word; private Term term; private State state; // properties: private Color color = new Color(204, 204, 255); // swing color void setColor(Color color) { this.color = color; } Color getColor() { return color; } private Color xor_color = Color.white; void setXORColor(Color color) { xor_color = color; } Color getXORColor() { return xor_color; } Sel(Term term, State state) { this.term = term; this.state = state; } /** * Adjust the selection against 'afirstline'. *

* As the selection reaches the top of the history buffer it will get * trimmed until eventually all of it will go away. * * This form doesn't work if the selection is "split" by insertion of * lines. Maybe we SHOULD have two arguments, adjust origin and adjust * extent? */ void adjust(int afirstline, int amount, int alastline) { if (sel_origin == null) return; /* DEBUG System.out.println("Sel.adjust origin " + sel_origin.row + " " + sel_origin.col); // NOI18N System.out.println("Sel.adjust extent " + sel_extent.row + " " + sel_extent.col); // NOI18N System.out.println("Sel.adjust afirstline " + afirstline + " amount " + amount + " alastline " + alastline); // NOI18N */ if (sel_origin.compareTo(sel_extent) >= 0) { // extent before origin sel_extent.row += amount; if (sel_extent.row < afirstline) sel_extent.row = afirstline; sel_origin.row += amount; if (sel_origin.row >= alastline) { sel_origin.row = alastline-1; sel_origin.col = term.buf.totalCols(); } if (sel_origin.row < afirstline || sel_extent.row > alastline) { // it has completely vanished sel_extent = null; sel_origin = null; } } else { // origin before extent sel_origin.row += amount; if (sel_origin.row < afirstline) sel_origin.row = afirstline; sel_extent.row += amount; if (sel_extent.row >= alastline) { sel_extent.row = alastline-1; sel_extent.col = term.buf.totalCols(); } if (sel_extent.row < afirstline || sel_origin.row > alastline) { // it has completely vanished sel_origin = null; sel_extent = null; } } term.fireSelectionExtentChanged(); } void relocate(int from, int to) { if (sel_origin == null) return; int delta = to - from; sel_origin.row += delta; sel_extent.row += delta; } Extent getExtent() { if (sel_origin == null) return null; Extent x = new Extent(sel_origin, sel_extent); x.order(); return x; } void setExtent(Extent extent) { cancel(false); extent.order(); sel_origin = (Coord) extent.begin.clone(); sel_extent = (Coord) extent.end.clone(); done(/* OLD false */); // so it makes it into clipboard } public void select_word(Extent range) { sel_origin = new Coord(range.begin); sel_extent = new Coord(range.end); sel_tracking = Sel.SEL_WORD; old_sel_tracking = Sel.SEL_NONE; initial_word = range; } public void select_line(Coord coord) { // LATER coord.clip(term.buf.nlines, term.buf.totalCols(), term.firsta); sel_origin = Coord.make(coord.row, 0); sel_extent = Coord.make(coord.row, term.buf.totalCols()); sel_tracking = Sel.SEL_LINE; old_sel_tracking = Sel.SEL_NONE; } private boolean extend_work(Coord p, int tracking) { /* * return true if a screen refresh is needed */ if (tracking == Sel.SEL_NONE) { return false; } else if (tracking == Sel.SEL_CHAR) { sel_extent = p; } else if (tracking == Sel.SEL_WORD) { BExtent Bnew_range = term.buf.find_word(term.word_delineator, p.toBCoord(term.firsta)); Extent new_range = Bnew_range.toExtent(term.firsta); if (p.compareTo(initial_word.begin) < 0) { sel_origin = new Coord(new_range.begin); sel_extent = initial_word.end; } else if (p.compareTo(initial_word.end) > 0) { sel_origin = initial_word.begin; sel_extent = new Coord(new_range.end); } else { sel_origin = initial_word.begin; sel_extent = initial_word.end; } } else if (tracking == Sel.SEL_LINE) { if (p.compareTo(sel_origin) > 0) { sel_origin = Coord.make(sel_origin.row, 0); sel_extent = Coord.make(p.row, term.buf.totalCols()); } else { sel_origin = Coord.make(sel_origin.row, term.buf.totalCols()); sel_extent = Coord.make(p.row, 0); } } return true; } public void track(Coord p) { if (sel_tracking == Sel.SEL_NONE) { // initiate a selection sel_origin = p; sel_extent = p; sel_tracking = Sel.SEL_CHAR; old_sel_tracking = Sel.SEL_NONE; } extend_work(p, sel_tracking); } public boolean extend(Coord p) { // return true if a screen refresh is needed if (sel_origin == null) return false; else return extend_work(p, old_sel_tracking); } /* * Variation on cancel which doesn't update the Selection. * Used by lostOwnership() in addition to plain cancel(). */ private boolean cancelHelp(boolean and_fire) { if (sel_origin == null) return false; old_sel_tracking = Sel.SEL_NONE; sel_tracking = Sel.SEL_NONE; sel_origin = null; sel_extent = null; initial_word = null; if (and_fire) term.fireSelectionExtentChanged(); return true; } public boolean cancel(boolean and_fire) { if (!cancelHelp(and_fire)) return false; term.copyToSelection(); return true; } public void done(/* OLD boolean force_copy */) { // don't track anymore // but extend will still work old_sel_tracking = sel_tracking; sel_tracking = Sel.SEL_NONE; term.copyToSelection(); term.fireSelectionExtentChanged(); } public void lostOwnership(Clipboard cb, Transferable c) { /* * Part of the ClipboardOwner interface. * The string created in sel_done should be retained until * this function is called. */ /* DEBUG System.out.println("lostOwnership()"); // NOI18N */ if (cancelHelp(true)) term.repaint(false); } public String getSelection() { Extent x = getExtent(); if (x == null) return null; if (x.begin != null && x.end != null) { final StringBuffer text = new StringBuffer(); term.visitLines(x.begin, x.end, true, new LineVisitor() { public boolean visit(Line l, int row, int bcol, int ecol) { text.append(l.text(bcol, ecol)); return true; } } ); return text.toString(); } return ""; //NOI18N } /* * Helps decide what to do with the selection when a line is * added, removed or cleared. */ int intersection(int line) { /* DEBUG if (sel_origin == null) { System.out.println("Sel.intersection(" + line + ") no selection"); // NOI18N } else { System.out.println("Sel.intersection(" + line + ")" + // NOI18N " sel_origin.row = " + sel_origin.row + // NOI18N " sel_extent.row = " + sel_extent.row); // NOI18N } */ Extent x = getExtent(); if (x == null) return INT_NONE; x.order(); if (x.end.row < line) return INT_ABOVE; else if (x.end.row == line) return INT_ON; else if (x.begin.row > line) return INT_BELOW; else return INT_STRADDLES; } /** * Select inside one line * Rows and columns are in absolute coords. */ private void paint(Graphics g, int row, int bcol, int ecol) { // Instead of doing this SHOULD clip the Extent to what's in view // Row is outside the view if (row < state.firstx) return; if (row > state.firstx + state.rows) return; // Construct the rectangle we're going to paint BCoord begin = new BCoord(row, bcol); BCoord end = new BCoord(row, ecol); begin = term.toViewCoord(begin); end = term.toViewCoord(end); //Hotfix for issue 40189 if (begin == null || end == null) { return; } int lw; // width of last character in selection Line l = term.buf.lineAt(row); lw = l.width(term.metrics, ecol); Point pbegin = term.toPixel(begin); Point pend = term.toPixel(end); pend.y += term.metrics.height; pend.x += term.metrics.width * lw; // xterm actually doesn't do this Dimension dim = new Dimension(pend.x - pbegin.x, pend.y - pbegin.y); Rectangle rect = new Rectangle(pbegin, dim); if (term.selection_xor) g.setXORMode(xor_color); else g.setColor(color); g.fillRect(rect.x, rect.y, rect.width, rect.height); } void paint(final Graphics g) { /* * Paint the selection. */ Extent x = getExtent(); if (x == null) return; x.order(); // DEBUG System.out.println("Sel.paint extent: " + x); // NOI18N term.visitLines(x.begin, x.end, true, new LineVisitor() { public boolean visit(Line l, int row, int bcol, int ecol) { paint(g, row, bcol, ecol); return true; } } ); } }

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.