/*****************************************************************************
* Copyright (c) 2006, 2007 g-Eclipse Consortium
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Initial development of the original code was made for the
* g-Eclipse project founded by European Union
* project number: FP6-IST-034327 http://www.geclipse.eu/
*
* Contributors:
* Thomas Koeckerbauer GUP, JKU - initial API and implementation
*****************************************************************************/
package eu.geclipse.terminal.internal;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.widgets.Display;
class TerminalSelection implements ITextSelection, MouseMoveListener, MouseListener {
private int startRow;
private int startCol;
private int endRow;
private int endCol;
private int row1;
private int col1;
private int row2;
private int col2;
private Terminal terminal;
TerminalSelection( final Terminal terminal ) {
this.terminal = terminal;
}
void clearSelection() {
Display.getDefault().syncExec( new Runnable() {
public void run() {
clearSelection( 0, 0 );
}
} );
}
void clearSelection( final int row, final int col ) {
boolean redraw = !isEmpty();
this.row1 = row;
this.col1 = col;
this.row2 = row;
this.col2 = col;
this.startRow = row;
this.startCol = col;
this.endRow = row;
this.endCol = col;
if ( redraw ) this.terminal.redraw();
}
private void updateSelection( final int row, final int col ) {
this.row2 = row;
this.col2 = col;
if ( this.row1 < this.row2 || ( this.row1 == this.row2 && this.col1 < this.col2 ) ) {
this.startRow = this.row1;
this.startCol = this.col1;
this.endRow = row;
this.endCol = col;
} else {
this.startRow = row;
this.startCol = col;
this.endRow = this.row1;
this.endCol = this.col1;
}
}
private int getColForXPos( final int xPos ) {
int col = xPos / this.terminal.getFontWidth();
if ( col > this.terminal.getNumCols() ) {
col = this.terminal.getNumCols();
}
return col;
}
private int getRowForYPos( final int yPos ) {
int scrollbarLine = this.terminal.getScrollbarPosLine();
int row = yPos / this.terminal.getFontHeigth() + scrollbarLine;
if ( row >= this.terminal.getNumLines() + this.terminal.getHistorySize() ) {
row = this.terminal.getNumLines() + this.terminal.getHistorySize() - 1;
}
return row;
}
public int getEndLine() {
return this.endRow;
}
public int getLength() {
return getText().length();
}
public int getOffset() {
// TODO Auto-generated method stub
return 0;
}
public int getStartLine() {
return this.startRow;
}
public String getText() {
StringBuilder str = new StringBuilder();
Char[][] screenbuffer = this.terminal.getScreenBuffer();
for( int row = this.startRow; row <= this.endRow; row++ ) {
for( int col = ( ( row == this.startRow ) ? this.startCol : 0 );
col < ( ( row == this.endRow ) ? this.endCol : this.terminal.getNumCols() );
col++ ) {
char ch = screenbuffer[ row ][ col ].ch;
if ( ch != 0 ) str.append( ch );
}
if ( row != this.endRow ) str.append( '\n' );
}
return str.toString();
}
public boolean isEmpty() {
return this.startCol == this.endCol && this.startRow == this.endRow;
}
public void mouseDoubleClick( final MouseEvent event ) {
int row = getRowForYPos( event.y );
int col = getColForXPos( event.x );
int selStartCol = col;
int selEndCol = col;
char ch;
do {
ch = this.terminal.getScreenBuffer()[ row ][ selStartCol ].ch;
selStartCol--;
} while( selStartCol >= 0 && ch !=' ' && ch != 0 );
selStartCol++;
if ( ch ==' ' || ch == 0 ) selStartCol++;
do {
ch = this.terminal.getScreenBuffer()[ row ][ selEndCol ].ch;
selEndCol++;
} while( selEndCol < this.terminal.getNumCols() && ch !=' ' && ch != 0 );
if ( ch ==' ' || ch == 0 ) selEndCol--;
clearSelection( row, selStartCol );
updateSelection( row, selEndCol );
triggerRedraw( row, selStartCol, row, selEndCol );
this.terminal.fireSelectionChanged();
}
public void mouseDown( final MouseEvent event ) {
if ( event.button == 1 ) {
clearSelection( getRowForYPos( event.y ), getColForXPos( event.x ) );
}
}
public void mouseUp( final MouseEvent event ) {
// if ( event.button == 1 ) {
// updateSelection( getRowForYPos( event.y ), getColForXPos( event.x ) );
// this.terminal.fireSelectionChanged();
// }
}
public void mouseMove( final MouseEvent event ) {
if ( ( event.stateMask & SWT.BUTTON1 ) != 0 ) {
int oldStartRow = this.startRow;
int oldStartCol = this.startCol;
int oldEndRow = this.endRow;
int oldEndCol = this.endCol;
updateSelection( getRowForYPos( event.y ), getColForXPos( event.x ) );
triggerRedraw( oldStartRow, oldStartCol, this.startRow, this.startCol );
triggerRedraw( oldEndRow, oldEndCol, this.endRow, this.endCol );
this.terminal.fireSelectionChanged();
}
}
private void triggerRedraw( final int oldRow, final int oldCol,
final int newRow, final int newCol ) {
int topRow = Math.min( oldRow, newRow );
int bottomRow = Math.max( oldRow, newRow );
int leftCol = Math.min( oldCol, newCol );
int rightCol = Math.max( oldCol, newCol );
if ( topRow != bottomRow ) {
this.terminal.triggerRedraw( 0,
topRow - this.terminal.getHistorySize(),
this.terminal.getNumCols(),
bottomRow - topRow + 1 );
} else if ( leftCol != rightCol ) {
this.terminal.triggerRedraw( leftCol,
topRow - this.terminal.getHistorySize(),
rightCol - leftCol,
1 );
}
}
boolean isSelected( final int row, final int col ) {
return ( row > this.startRow && row < this.endRow)
|| ( row == this.startRow && row != this.endRow && col >= this.startCol )
|| ( row != this.startRow && row == this.endRow && col < this.endCol )
|| ( row == this.startRow && row == this.endRow && col >= this.startCol && col < this.endCol );
}
}