/* Mesquite Class Library. Copyright 1997-2004 W. Maddison and D. Maddison.
Version 1.01, January 2004.
Disclaimer: The Mesquite source code is lengthy and we are few. There are no doubt inefficiencies and goofs in this code.
The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
Perhaps with your help we can be more than a few, and make Mesquite better.
Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
Mesquite's web site is http://mesquiteproject.org
This source code and its compiled class files are free and modifiable under the terms of
GNU Lesser General Public License. (http://www.gnu.org/copyleft/lesser.html)
*/
package mesquite.lib.table;
import java.awt.*;
import java.awt.event.*;
import java.awt.datatransfer.*;
import mesquite.lib.*;
/* ======================================================================== */
/** A base class to be extended for various spreadsheet-like tables. It provides very basic
services like shaping the components, drawing the grid, fielding scrolling events and mousedowns,
and provides hooks for superclasses to fill the cells. It is expected to be used for the type editor simple text charts,
character data editor and list windows. Almost all of the burden of the memory design and management of the cells, rows, columns,
etc. is left to the superclasses.
The table is composed of 6 panels: the column for the row names (e.g., "from" state names in type
editor or taxon names in data editor), the row for the column names (e.g., "to" state names in type editor
or character names in data editor), the little corner between them in the upper left, the main block
of cells (the scrollable matrix), and the two scroll bars for the matrix.
Currently there are not too many settable parameters to customize the appearance of the table, but in the
future it should be made possible to customize the table's appearance */
public class MesquiteTable extends MesquitePanel implements KeyListener {
protected ColumnNamesPanel columnNames = null;
protected RowNamesPanel rowNames = null;
protected MatrixPanel matrix;
protected CornerPanel cornerCell;
protected MessagePanel messagePanel;
public static final int LEFT = 0;
public static final int RIGHT = 1;
public static final int CENTERED = 2;
protected boolean columnNamesCopyPaste = true;
protected boolean rowNamesCopyPaste = true;
int baseRowHeight = 16;
int baseColumnWidth = 16;
int nameStartOffset = 5;
int focusColumn = -2;
int focusRow = -2;
int justification = CENTERED;
private Cursor handCursor;
private Cursor eastResizeCursor;
TableScroll horizScroll;
TableScroll vertScroll;
Rectangle messageBox; //just to left of horizScroll
int firstRowVisible = 0; // topmost row with current y scroll position
int firstColumnVisible =0; // leftmost column with current horiz scroll position
int numRowsVisible=0;
int numColumnsVisible=0;
int lastRowVisible = 0; // bottom row visible, even if a partial row
int lastColumnVisible =0; // rightmost column visible, even if partial column
public int numRowsTotal; //TODO: why is this used as if numRowsVisible?????
public int numColumnsTotal;
int columnGrabberWidth = 8;
int rowGrabberWidth = 8;
int columnNamesHeight = 20;
int rowNamesWidth = 50;
int matrixWidth ;
int matrixHeight;
int[] columnWidths;
int[] rowHeights;
Font oldF = null;
Font boldFont = null;
public boolean frameRowNames = true;
public boolean frameColumnNames = true;
public boolean frameMatrixCells = true;
public boolean showRowGrabbers = false;
public boolean showColumnGrabbers = false;
public boolean showRowNumbers = false;
public boolean showColumnNumbers = false;
public boolean cornerIsHeading = false;
protected boolean autosizeColumns = false;
private boolean cellsAutoEditable = false;
private boolean rowNamesAutoEditable = false;
private boolean columnNamesAutoEditable = false;
private boolean cornerAutoEditable = false;
private boolean cellsEditable = false;
private boolean rowNamesEditable = false;
private boolean columnNamesEditable = false;
private boolean cornerEditable = false;
private boolean cellsSelectable = true;
private boolean rowNamesSelectable = true;
private boolean columnNamesSelectable = true;
private boolean rowsSelectable = true;
private boolean columnsSelectable = true;
private boolean cornerSelectable = false;
private boolean quickMode = false;
public static final int NOADJUST = 0; // these constants refer to column and row user-adjust -- INSERT or RESIZE if interstitial space pulled
public static final int RESIZE = 1;
public static final int INSERT = 2;
private int userAdjustColumn = NOADJUST;
private boolean userMoveColumn = false;
private int userAdjustRow = NOADJUST;
private boolean userMoveRow = false;
public boolean adjustingColumnWidth=false;
private Bits[] rowsSelected;
private Bits[] columnsSelected;
private Bits[] cellsSelected;
private Bits[] columnNamesSelected;
private Bits[] rowNamesSelected;
private boolean[] cornerSelected;
private int numSelectTypes = 3; //0 = selection; 1 = dimming; 2 = dropdown menu
Bits rowWidthsAdjusted;
Bits columnWidthsAdjusted;
boolean rowNamesWidthAdjusted=false;
private Associable columnAssociable = null;
private Associable rowAssociable = null;
protected int colorScheme;
MesquiteCommand pasteCommand = MesquiteModule.makeCommand("paste", this);
MesquiteCommand cutCommand = MesquiteModule.makeCommand("cut", this);
MesquiteCommand clearCommand = MesquiteModule.makeCommand("clear", this);
MesquiteCommand copyCommand = MesquiteModule.makeCommand("copy", this);
MesquiteCommand copyLiteralCommand = MesquiteModule.makeCommand("copyLiteral", this);
MesquiteCommand selectAllCommand = MesquiteModule.makeCommand("selectAll", this);
public static MesquiteTimer tableTime;
static {
tableTime = new MesquiteTimer();
}
public MesquiteTable (int numRowsTotal, int numColumnsTotal, int totalWidth, int totalHeight, int rowNamesWidth, int colorScheme, boolean showRowNumbers, boolean showColumnNumbers) {
super();
tableTime.start();
this.colorScheme = colorScheme;
this.numRowsTotal= numRowsTotal;
this.numColumnsTotal= numColumnsTotal;
this.rowNamesWidth=rowNamesWidth;
this.showRowNumbers =showRowNumbers;
this.showColumnNumbers =showColumnNumbers;
if (showRowNumbers)
setRowGrabberWidth(24);
if (showColumnNumbers)
setColumnGrabberWidth(14);
matrixWidth=totalWidth-rowNamesWidth-16-rowGrabberWidth;
matrixHeight=totalHeight-columnNamesHeight-16-columnGrabberWidth;
columnWidths = new int[numColumnsTotal];
rowWidthsAdjusted = new Bits(numRowsTotal);
columnWidthsAdjusted= new Bits(numColumnsTotal);
setColumnWidthsUniform(baseColumnWidth);
rowHeights = new int[numRowsTotal];
setRowHeightsUniform(baseRowHeight);
rowsSelected = new Bits[numSelectTypes];
columnsSelected = new Bits[numSelectTypes];
cellsSelected = new Bits[numSelectTypes];
columnNamesSelected = new Bits[numSelectTypes];
rowNamesSelected = new Bits[numSelectTypes];
cornerSelected = new boolean[numSelectTypes];
for (int i = 0; i=0 && column=0 && (firstRow=0 && (firstColumn=0)
top = 0;
if (left<0 && top>=0)
left = 0;
if (top >=0 && left >=0) {
deselectAll();
for (int row = 0; row=0)
columnAssociable.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED), commandRec);
if (rowAssociable!=null && firstRow>=0)
rowAssociable.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED), commandRec);
}
else if (anyRowNameSelected()){
int first = rowNamesSelected[0].firstBitOn();
for (int row = first; row < lines.length +first; row++){
selectRowName(row);
}
}
else if (anyColumnNameSelected()){
if (lines.length==1){
int first = columnNamesSelected[0].firstBitOn();
for (int column = first; column < lines[0] +first; column++){
selectColumnName(column);
}
}
}
repaintAll();
}
/*.................................................................................................................*/
int[] getSelectedSpaces(){
// for each row, how many things are selected needs to be calculated
// first, figure out how many rows have selections in them.
int lines = 0;
if ((anyColumnNameSelected() || anyColumnSelected()) && columnNamesCopyPaste)
lines++;
if (anyColumnSelected())
lines+= numRowsTotal;
else
for (int j = 0; j0) {
result[line]=numInLine;
line++;
}
for (int j = 0; j0) {
result[line]=numInLine;
line++;
}
}
return result;
}
/*.................................................................................................................*/
boolean anyCellInRowSelected(int row){
if (!rowLegal(row))
return false;
for (int i = 0; i";
else if (s.charAt(i)=='\r')
sNew+="<^r>";
else if (s.charAt(i)=='\n')
sNew+="<^n>";
else
sNew+= s.charAt(i);
return sNew;
}
public void keyTyped(KeyEvent e){
}
public void keyPressed(KeyEvent e){
//Event queue
if (e.getKeyCode()== KeyEvent.VK_ENTER)
enterPressed(e);
else if (e.getKeyCode()== KeyEvent.VK_TAB)
tabPressed(e);
else if (e.getKeyCode()== KeyEvent.VK_RIGHT)
rightArrowPressed(e);
else if (e.getKeyCode()== KeyEvent.VK_LEFT)
leftArrowPressed(e);
else if (e.getKeyCode()== KeyEvent.VK_UP)
upArrowPressed(e);
else if (e.getKeyCode()== KeyEvent.VK_DOWN)
downArrowPressed(e);
}
public void keyReleased(KeyEvent e){
}
private EditorTextField getEditField(){
if (matrix.getEditing())
return matrix.getEditField();
if (columnNames.getEditing())
return columnNames.getEditField();
if (rowNames.getEditing())
return rowNames.getEditField();
return null;
}
private boolean getEditing(){
return matrix.getEditing() || columnNames.getEditing() || rowNames.getEditing() ;
}
public void enterPressed(KeyEvent e){
if (getEditing()) //let the edit box handle it
return;
//go to editing
if (singleTableCellSelected()) {
Dimension sel = getFirstTableCellSelected();
if (sel.width>=-1 && sel.height>=-1) {
if (sel.width == -1 && sel.height >= 0) { //rowNames
if (isRowNameEditable(sel.height))
rowNames.editCell(sel.width, sel.height);
}
else if (sel.width >= 0 && sel.height == -1) { //columnNames
if (isColumnNameEditable(sel.width))
columnNames.editCell(sel.width, sel.height);
}
else if (sel.width >= 0 && sel.height >= 0) { //within matrix
if (isCellEditable(sel.width, sel.height))
matrix.editCell(sel.width, sel.height);
}
}
}
}
public void tabPressed(KeyEvent e){
if (getEditing())
return;
rightArrowPressed(e);
}
public void downArrowPressed(KeyEvent e){
if (getEditing())
return;
if (singleTableCellSelected()) {
Dimension sel = getFirstTableCellSelected();
if (sel.width>=-1 && sel.height>=-1) {
if (sel.height +1 < numRowsTotal) {
deselectCell(sel.width, sel.height);
selectCell(sel.width, sel.height+1);
redrawCell(sel.width, sel.height);
redrawCell(sel.width, sel.height+1);
setFocusedCell(sel.width, sel.height+1);
}
else
MesquiteMessage.beep();
}
else
MesquiteMessage.beep();
}
}
public void upArrowPressed(KeyEvent e){ //
if (getEditing())
return;
if (singleTableCellSelected()) {
Dimension sel = getFirstTableCellSelected();
if (sel.width>=-1 && sel.height>=0 && sel.height -1 < numRowsTotal && (sel.width >=0 || sel.height>0)) {
deselectCell(sel.width, sel.height);
selectCell(sel.width, sel.height-1);
redrawCell(sel.width, sel.height);
redrawCell(sel.width, sel.height-1);
setFocusedCell(sel.width, sel.height-1);
}
else
MesquiteMessage.beep();
}
}
public void rightArrowPressed(KeyEvent e){
if (getEditing())
return;
if (singleTableCellSelected()) {
Dimension sel = getFirstTableCellSelected();
if (sel.width>=-1 && sel.height>=-1) {
if (sel.width +1 < numColumnsTotal) {
deselectCell(sel.width, sel.height);
selectCell(sel.width+1, sel.height);
redrawCell(sel.width, sel.height);
redrawCell(sel.width+1, sel.height);
setFocusedCell(sel.width+1, sel.height);
}
else {
MesquiteMessage.beep();
}
}
else
MesquiteMessage.beep();
}
}
public void leftArrowPressed(KeyEvent e){
if (getEditing())
return;
if (singleTableCellSelected()) {
Dimension sel = getFirstTableCellSelected();
if (sel.width>=0 && sel.height>=-1 && sel.width - 1 < numColumnsTotal && (sel.width >0 || sel.height>=0)) {
deselectCell(sel.width, sel.height);
selectCell(sel.width-1, sel.height);
redrawCell(sel.width, sel.height);
redrawCell(sel.width-1, sel.height);
setFocusedCell(sel.width-1, sel.height);
}
else
MesquiteMessage.beep();
}
}
public void defocusCell(){
int oldFC = focusColumn;
int oldFR = focusRow;
focusColumn = -2;
focusRow = -2;
if (oldFR>=-1)
rowNames.redrawCell(-1, oldFR);
if (oldFC>=-1)
columnNames.redrawCell(oldFC, -1);
if (oldFR>=0 && oldFC>=0) {
matrix.redrawCell(oldFC, oldFR);
}
}
public void setFocusedCell(int column, int row){
//can be overridden to respond to focus as in touch, edit etc. for explanation showing, but should call super.setFocusedCell(column, row);
defocusCell();
if (column < -1 || row <-1 || !singleTableCellSelected())
return;
if (column > getLastColumnVisible()) {
int newFirst = getFirstColumnVisible() + (column - getLastColumnVisible())+1;
if (newFirst<0)
newFirst = 0;
setFirstColumnVisible(newFirst);
}
else if (column < getFirstColumnVisible()) {
setFirstColumnVisible(column);
}
if (row > getLastRowVisible()) {
int newFirst = getFirstRowVisible() + (row - getLastRowVisible())+1;
if (newFirst<0)
newFirst = 0;
setFirstRowVisible(newFirst);
}
else if (row < getFirstRowVisible()) {
setFirstRowVisible(row);
}
focusColumn = column;
focusRow = row;
rowNames.redrawCell(-1, focusRow);
columnNames.redrawCell(focusColumn, -1);
if (focusRow>=0 && focusColumn>=0)
matrix.redrawCell(focusColumn, focusRow);
}
/*.................................................................................................................*/
public boolean autoSizeColumns (Graphics g) {
if (g == null)
return false;
FontMetrics fm=g.getFontMetrics(g.getFont());
int h = fm.getMaxAscent()+ fm.getMaxDescent() + MesquiteModule.textEdgeCompensationHeight; //2 + MesquiteString.riseOffset;
setRowHeightsUniform(h);
setColumnNamesHeight(h);
String s = getCornerText();
boolean changed = false;
if (StringUtil.blank(s))
s = "GGGGG";
int max = fm.stringWidth(s);
//row names
int lengthString = 0;
for (int it = 0; itmax)
max = lengthString;
}
int tableWidth = getWidth(); //build 81
if (max>tableWidth/3) //build 81
max = tableWidth/3; //build 81
int newCW = max + 2 + MesquiteModule.textEdgeCompensationHeight;
int current = getRowNamesWidth();
if (newCW != current) {
setRowNamesWidth(newCW);
changed = true;
}
//other columns
max = fm.stringWidth("G");
for (int ic = 0; icmax)
max = lengthString;
for (int it = 0; itmax)
max = lengthString;
}
newCW = max + 2 + MesquiteModule.textEdgeCompensationHeight;
current = getColumnWidth(ic);
if (newCW != current) {
setColumnWidth(ic, newCW);
changed = true;
}
}
}
return changed;
}
/*.................................................................................................................*/
private static final int NOMORE = 0;
private static final int TAB = 1;
private static final int LINE = 2;
private static final int TOKENTabBounded = 3;
private static final int TOKENReturnBounded = 4;
private static int goToNext(String s, MesquiteInteger pos){
if (s==null || pos==null || pos.getValue()<-1 || pos.getValue()+1>s.length()-1)
return NOMORE;
pos.increment();
int i= pos.getValue();
char c = s.charAt(i);
if (c=='\t')
return TAB;
if (c=='\n' || c=='\r'){
if (StringUtil.lineEnding().length()>1)
pos.increment();
return LINE;
}
while (i< s.length() && !(c=='\n' || c=='\r' || c=='\t')){
i++;
if (i= s.length()) {
pos.setValue(i);
return TOKENReturnBounded;
}
if (c=='\n' || c=='\r') {
i--;
pos.setValue(i);
return TOKENReturnBounded;
}
pos.setValue(i);
return TOKENTabBounded;
}
/*.................................................................................................................*/
public static int[] getTabbedLines(String s){
if (s==null)
return null;
int lines=0;
int token;
boolean lastIsLine=true;
MesquiteInteger pos = new MesquiteInteger(-1);
while ((token = goToNext(s, pos))!= NOMORE) {
if (token == LINE ) {
lines++;
lastIsLine = true;
}
else
lastIsLine = false;
}
if (!lastIsLine)
lines++;
int[] result = new int[lines];
int line=0;
int item=0;
int pending = 0;
pos.setValue(-1);
while ((token = goToNext(s, pos))!= NOMORE) {
if (token == LINE) {
item += pending;
if (item==0)
item = 1;
result[line++] = item;
pending =0;
item = 0;
lastIsLine = true;
}
else {
if (token == TOKENTabBounded || token == TAB) {
pending = 1;
}
else {
pending = 0;
if (token == TOKENReturnBounded)
lastIsLine = true;
else
lastIsLine = false;
}
item++;
}
}
if (lastIsLine && line=0) {
endOfToken = i;
return s.substring(startOfToken, endOfToken);
}
//i--;
}
}
else {
count++;
if (count==which)
startOfToken = i;
while (i< s.length() && (s.charAt(i)!='\t') && !isLineBreak(s, i))
i++;
if (startOfToken>=0) {
endOfToken = i;
return s.substring(startOfToken, endOfToken);
}
//i--;
}
}
return null;
}
/*.................................................................................................................*/
// this is modified from getTabbedToken which explains its strange style
public static String getNextTabbedToken(String s, MesquiteInteger pos){
if (s==null)
return null;
int which = 0;
int count=-1;
int startOfToken=-1;
int endOfToken=-1;
for (int i=pos.getValue(); i=0) {
endOfToken = i;
pos.setValue(i+1);
return s.substring(startOfToken, endOfToken);
}
}
pos.setValue(s.length());
return null;
}
static boolean isLineBreak(String s, int index){
if (s == null || index>=s.length() || index<0)
return false;
char c = s.charAt(index);
return (c== '\n' || c== '\r');
}
/*.................................................................................................................*/
public MesquiteCommand getCopyCommand() {
return copyCommand;
}
public MesquiteCommand getCopyLiteralCommand() {
return copyLiteralCommand;
}
public MesquiteCommand getPasteCommand() {
return pasteCommand;
}
public MesquiteCommand getCutCommand() {
return cutCommand;
}
public MesquiteCommand getClearCommand() {
return clearCommand;
}
public MesquiteCommand getSelectAllCommand() {
return selectAllCommand;
}
/*.................................................................................................................*/
public void setHorizScrollVisible(boolean vis){
horizScroll.setVisible(vis);
}
public void setVertScrollVisible(boolean vis){
vertScroll.setVisible(vis);
}
/*.................................................................................................................*/
public int getLastRow() {
return numRowsTotal-1;
}
/*.................................................................................................................*/
public int getLastColumn() {
return numColumnsTotal-1;
}
/*.................................................................................................................*/
public int getMatrixWidth(){
return matrixWidth;
}
public int getMatrixHeight(){
return matrixHeight;
}
private void printComponent(Graphics g, Panel c){
int shiftX =c.getBounds().x;
int shiftY = c.getBounds().y;
g.translate(shiftX, shiftY);
c.print(g);
g.translate(-shiftX, -shiftY);
}
/*...............................................................................................................*/
public void printAll(Graphics g) {
cornerCell.paint(g);
printComponent(g, rowNames);
printComponent(g, columnNames);
printComponent(g, matrix);
}
/*.................................................................................................................*/
public void printTable(MesquitePrintJob pjob, MesquiteWindow window) {
if (pjob != null) {
pjob.printComponent(this, new Dimension(getTotalColumnWidth() + getRowNamesWidth(), getTotalRowHeight() + getColumnNamesHeight()), null);
}
}
/*...............................................................................................................*/
public boolean checkResetFont(Graphics g) { //^^^
boolean doReset=false;
if (g!=null) {
Font f = g.getFont();
if (f!=null && f!=oldF) {
FontMetrics fm = g.getFontMetrics(f);
if (fm!=null) {
int height = fm.getHeight();
setGrabberSize(fm);
setColumnNamesHeight( height+MesquiteModule.textEdgeCompensationHeight);
for (int i=firstRowVisible; i< numRowsTotal; i++){
if (rowHeights[i]=0) {
int[] newColumnWidths = new int[numColumnsTotal-1];
for (int c=0; ccolumn)
newColumnWidths[c] = columnWidths[c+1];
else
newColumnWidths[c] = columnWidths[c];
columnWidths = newColumnWidths;
numColumnsTotal=numColumnsTotal-1;
for (int i = 0; i=numColumnsTotal || firstColumnVisible<0)
firstColumnVisible = 0;
if (horizScroll!=null) {
horizScroll.setValue(firstColumnVisible);
horizScroll.setMaximum(numColumnsTotal-1);
}
}
}
/*...............................................................................................................*/
public void moveColumns(int starting, int num, int justAfter){
}
/*...............................................................................................................*/
/** Sets the number of rows TOTAL (not just visible)*/
public void setNumRows(int rows) {
if (rows<0)
return;
int[] newRowHeights = new int[rows];
for (int r=0; r0)
defHeight = rowHeights[0];
if (rows>numRowsTotal)
for (int r=numRowsTotal; r=numRowsTotal || firstRowVisible<0)
firstRowVisible = 0;
if (vertScroll !=null) {
vertScroll.setValue(firstRowVisible);
vertScroll.setMaximum(numRowsTotal-1);
}
}
/*...............................................................................................................*/
/** Inserts num columns just after "starting". Calls setNumColumns*/
public void insertColumns(int starting, int num) {
int oldNumColumns = numColumnsTotal;
setNumColumns(numColumnsTotal+num);
if (startingstarting+num; c--)
columnWidths[c] = columnWidths[c-num];
for (int c=starting+1; c0)
defWidth = columnWidths[0];
if (columns>numColumnsTotal)
for (int c=numColumnsTotal; c=columns || firstColumnVisible<0)
firstColumnVisible = 0;
if (horizScroll!=null) {
horizScroll.setValue(firstColumnVisible);
horizScroll.setMaximum(numColumnsTotal-1);
}
}
}
/*...............................................................................................................*/
/** Gets the number of rows TOTAL (not just visible)*/
public int getNumRows() {
return numRowsTotal;
}
/*...............................................................................................................*/
/** Gets the number of columns TOTAL (not just visible)*/
public int getNumColumns() {
return numColumnsTotal;
}
/*...............................................................................................................*/
/** Calculates the number of visible columns, rounded up to the nearest whole number.
Also sets the value of the lastColumnVisible, and sets the appropriate page increment
for the horizontal scroll bar. */
public void resetNumColumnsVisible() {
numColumnsVisible=numColumnsTotal-firstColumnVisible+1;
int sum = 0;
for (int c=firstColumnVisible; c= matrixWidth) {
numColumnsVisible= (c-firstColumnVisible+1);
break;
}
}
horizScroll.setBlockIncrement(numColumnsVisible-1);
lastColumnVisible = firstColumnVisible+numColumnsVisible-1;
}
/*...............................................................................................................*/
/** Calculates the number of visible rows, rounded up to the nearest whole number.
Also sets the value of the lastRowVisible, and sets the appropriate page increment
for the vertical scroll bar. */
public void resetNumRowsVisible() {
numRowsVisible= (numRowsTotal-firstRowVisible+1);
int sum = 0;
for (int r=firstRowVisible; r= matrixHeight) {
numRowsVisible = (r-firstRowVisible+1);
break;
}
}
vertScroll.setBlockIncrement(numRowsVisible-1);
lastRowVisible = firstRowVisible+numRowsVisible-1;
}
/*...............................................................................................................*/
/** Gets the number of visible columns. Rounded up to the nearest whole number. */
public int getNumColumnsVisible() {
return numColumnsVisible;
}
/*...............................................................................................................*/
/** Gets the number of visible rows. Rounded up to the nearest whole number. */
public int getNumRowsVisible() {
return numRowsVisible;
}
/*...............................................................................................................*/
/** Gets the number of the last visible column. */
public int getLastColumnVisible() {
return lastColumnVisible;
}
/*...............................................................................................................*/
/** Gets the number of the last visible row. */
public int getLastRowVisible() {
return lastRowVisible;
}
/*...............................................................................................................*/
/** Gets the height of rows TOTAL (not just visible)*/
public int getTotalRowHeight() {
int sum = 0;
for (int r=0; r=c1) && (column<=c2) && (column>=nc1) && (column<=nc2) && (row>=r1) && (row<=r2) && (row>=nr1) && (row<=nr2);
}
/*...............................................................................................................*/
/** Redraw block of cells that aren't in the intersection of two blocks. */
public void redrawDifferenceBlock(int firstColumn, int newFirstColumn, int firstRow, int newFirstRow, int lastColumn, int newLastColumn, int lastRow, int newLastRow) {
if (!columnLegal(firstColumn) || !columnLegal(lastColumn) || !rowLegal(firstRow) ||!rowLegal(lastRow)||!columnLegal(newFirstColumn) || !columnLegal(newLastColumn) || !rowLegal(newFirstRow) ||!rowLegal(newLastRow))
return;
int c1 = MesquiteInteger.minimum(firstColumn, lastColumn, newFirstColumn,newLastColumn);
int c2 = MesquiteInteger.maximum(firstColumn, lastColumn, newFirstColumn,newLastColumn);
int r1 = MesquiteInteger.minimum(firstRow, lastRow,newFirstRow, newLastRow);
int r2 = MesquiteInteger.maximum(firstRow, lastRow,newFirstRow, newLastRow);
Graphics g = matrix.getGraphics();
if (g==null)
return;
for (int i = c1; i<=c2; i++)
for (int j= r1; j<=r2; j++)
if ((!cellInIntersectionOfBlocks(i,j,firstColumn, newFirstColumn,firstRow, newFirstRow,lastColumn, newLastColumn,lastRow, newLastRow)) && iw || svp>y+h){
clip = g.getClip();
g.setClip(x, y, w, h);
}
int useX;
if (justification == LEFT)
useX = x+2;
else if (justification == RIGHT)
useX = w-length - 2;
else
useX = x+(w-length)/2;
g.drawString(supplied, useX, svp);
}
if (clip!=null)
g.setClip(clip);
}
/*...............................................................................................................*/
/** ееее*/
public boolean useString(int column, int row){
return getMatrixTextForDisplay(column, row)!=null;
}
/*...............................................................................................................*/
/** Draws column name.*/
public void drawColumnNameCell(Graphics g, int x, int y, int w, int h, int column){
String supplied = getColumnNameTextForDisplay(column);
if (supplied==null)
return;
g.drawString(supplied, x+getNameStartOffset(), StringUtil.getStringVertPosition(g,y,h));
}
/*@@@...............................................................................................................*/
/** Returns in which column x lies, -1 if to left, -2 if to right.
Differs from findColumn in that*/
public int findHalfColumn(int x) {
if (x<=0)
return -1;
int cx = 0;
for (int column=firstColumnVisible; (column= numColumnsTotal)
return -1;
else if (cx>=x)
if (x+(columnWidths[column]/2) > cx) // then we are in the right half of the column
return column;
else
return column - 1;
}
return -2;
}
/*@@@...............................................................................................................*/
/** returns in which column x lies, -1 if to left, -2 if to right.*/
public int findColumn(int x) {
if (x<=0)
return -1;
int cx = 0;
for (int column=firstColumnVisible; (column= numColumnsTotal)
return -1;
else if (cx>=x)
return column;
}
return -2;
}
/*@@@...............................................................................................................*/
/** returns in which row y lies, -1 if above, -2 if below.*/
public int findRow(int y) {
if (y<=0)
return -1;
int ry = 0;
for (int row=firstRowVisible; (row= numRowsTotal)
return -1;
else if (ry>=y)
return row;
}
return -2;
}
/*...............................................................................................................*/
/** returns true if x is near the boundary of a column*/
public boolean nearColumnBoundary(int x) {
return (findOffsetInColumn(x) < 4 );
}
/*@@@...............................................................................................................*/
/** returns offset from right margin of column in which x lies, -1 if none.*/
public int findOffsetInColumn(int x) {
int cx = 0;
//int lastEdge=0;
for (int column=firstColumnVisible; (column=x)
return cx-x;
//lastEdge=cx;
}
return -1;
}
/*...............................................................................................................*/
/** returns true if y is near the boundary of a row*/
public boolean nearRowBoundary(int y) {
return (findOffsetInRow(y) < 4 );
}
/*@@@...............................................................................................................*/
/** returns offset from bottom margin of row in which y lies, -1 if none.*/
public int findOffsetInRow(int y) {
int cy = 0;
for (int row=firstRowVisible; (row=y)
return cy-y;
}
return -1;
}
/*...............................................................................................................*/
public int getNameStartOffset(){
return nameStartOffset;
}
/*...............................................................................................................*/
public void setNameStartOffset(int nameStartOffset){
this.nameStartOffset = nameStartOffset;
}
/*...............................................................................................................*/
/** Draws row name.*/
public void drawRowNameCell(Graphics g, int x, int y, int w, int h, int row){
String supplied = getRowNameTextForDisplay(row);
if (supplied==null)
return;
int svp = StringUtil.getStringVertPosition(g,y,h);
int xgnso = x+getNameStartOffset();
g.drawString(supplied, xgnso, svp);
}
/*...............................................................................................................*/
public void mouseInCell(int modifiers, int column,int row, MesquiteTool tool){
}
public void mouseExitedCell(int modifiers, int column,int row, MesquiteTool tool){
}
/*...............................................................................................................*/
/** Called if corner panel is touched. Can be overridden in subclasses to respond to touch.*/
public void cornerTouched(int x, int y, int modifiers) {
offAllEdits();
if (anythingSelected()) {
deselectAllNotify();
repaintAll();
}
}
/*...............................................................................................................*/
int rowFirstTouched=-2;
int columnFirstTouched=-2;
int rowLastTouched=0;
int columnLastTouched=0;
/*...............................................................................................................*/
/** Called if cell is touched. Can be overridden in subclasses to change response to touch.*/
public void cellTouched(int column, int row, int modifiers, int clickCount) {
if (!columnLegal(column) || !rowLegal(row))
return;
if (!cellsSelectable && !cellsEditable)
return;
/*
if ((column == columnFirstTouched && row == rowFirstTouched) && (anyCellSelected() || editingMatrixCell())) {
offEditMatrixCell();
deselectAllNotify();
selectCell(column,row);
redrawCell(column,row);
}
else
*/
if (MesquiteEvent.shiftKeyDown(modifiers) && (anyCellSelected() || editingMatrixCell())) {
offEditMatrixCell();
int firstRow = firstRowWithSelectedCell();
int lastRow = lastRowWithSelectedCell();
int firstColumn = firstColumnWithSelectedCell();
int lastColumn = lastColumnWithSelectedCell();
deselectAllNotify();
if (!columnLegal(firstColumn) || !rowLegal(firstRow)) {
selectCell(column,row);
redrawCell(column,row);
}
else {
int newFirstRow, newLastRow, newFirstColumn, newLastColumn;
if (row<=firstRow) {
newLastRow = lastRow;
newFirstRow = row;
rowFirstTouched= lastRow;
}
else {
newFirstRow = firstRow;
newLastRow = row;
rowFirstTouched= firstRow;
}
if (column<=firstColumn) {
newLastColumn = lastColumn;
newFirstColumn = column;
columnFirstTouched= lastColumn;
}
else {
newFirstColumn = firstColumn;
newLastColumn = column;
columnFirstTouched= firstColumn;
}
selectBlock(newFirstColumn,newFirstRow, newLastColumn, newLastRow);
// if (newLastColumn>lastColumn)
// if (newLastRow>lastRow)
redrawBlock(MesquiteInteger.minimum(firstColumn, newFirstColumn),MesquiteInteger.minimum(firstRow, newFirstRow),MesquiteInteger.maximum(lastColumn, newLastColumn),MesquiteInteger.maximum(lastRow, newLastRow));
//redrawBlock(columnFirstTouched,rowFirstTouched, column, row);
//redrawCell(columnFirstTouched,rowFirstTouched);
}
}
else if (MesquiteEvent.commandOrControlKeyDown(modifiers)&& (anyCellSelected() || editingMatrixCell())) {
if (isCellSelected(column, row))
deselectCell(column, row);
else
selectCell(column, row);
offEditMatrixCell();
redrawCell( column, row);
//redrawCell(columnFirstTouched,rowFirstTouched);
columnFirstTouched= column;
rowFirstTouched= row;
}
else if (anyRowSelected() || anyColumnSelected()) {
deselectAllNotify();
columnFirstTouched= column;
rowFirstTouched= row;
selectCell(column,row);
repaintAll();
}
else {
boolean wasSelected = anyCellSelected();
boolean wasOneCellSelected = (numCellsSelected()==1);
int firstRow = -1;
int lastRow = -1;
int firstColumn = -1;
int lastColumn = -1;
if (!wasOneCellSelected && wasSelected) {
firstRow = firstRowWithSelectedCell();
lastRow = lastRowWithSelectedCell();
firstColumn = firstColumnWithSelectedCell();
lastColumn = lastColumnWithSelectedCell();
}
//redrawSelectedBlock();
deselectAllNotify();
offEditMatrixCell();
//if (columnFirstTouched>=0)
// redrawBlock(columnFirstTouched,rowFirstTouched, columnLastTouched, rowLastTouched);
selectCell(column,row);
redrawCell(column,row);
if (wasSelected)
if (wasOneCellSelected) {
redrawCell(columnLastTouched, rowLastTouched);
}
else
redrawBlock(firstColumn, firstRow, lastColumn, lastRow);
columnFirstTouched= column;
rowFirstTouched= row;
}
columnLastTouched = column;
rowLastTouched =row;
}
/*...............................................................................................................*/
/** Called if mouse dragged over cell.
Can be overridden in subclasses to respond.*/
public void cellDrag(int column, int row, int modifiers) {
if (!columnLegal(column) || !rowLegal(row))
return;
if (!cellsSelectable)
return;
if ((column!=columnLastTouched || row != rowLastTouched)&& (anyCellSelected() || editingMatrixCell())) {
offEditMatrixCell();
if (!MesquiteEvent.commandOrControlKeyDown(modifiers))
deselectAllNotify();
selectBlock(columnFirstTouched,rowFirstTouched, column, row);
redrawDifferenceBlock(columnFirstTouched, columnFirstTouched, rowFirstTouched, rowFirstTouched, columnLastTouched, column, rowLastTouched, row );
//redrawBlock(columnFirstTouched,rowFirstTouched, columnLastTouched, rowLastTouched);
//redrawBlock(columnFirstTouched,rowFirstTouched, column, row);
}
columnLastTouched = column;
rowLastTouched = row;
}
/*...............................................................................................................*/
/** Called if mouse is dropped on cell.
Can be overridden in subclasses to respond.*/
public void cellDropped(int column, int row, int modifiers) {
if (!singleTableCellSelected())
defocusCell();
}
/*...............................................................................................................*/
/** Called if column name is touched. Can be overridden in subclasses to change response to touch.*/
public void columnNameTouched(int column, int modifiers, int clickCount) {
//TODO: have extension of selection if shift or command; have boolean if name editable and if selectable
if (!columnLegal(column))
return;
if (!columnNamesEditable && !columnNamesSelectable)
return;
if ((column == columnFirstTouched)&& (anyColumnNameSelected() || editingColumnName())) {
deselectAllNotify();
offAllEdits();
selectColumnName(column);
columnNames.repaint();
}
else if ((MesquiteEvent.shiftKeyDown(modifiers) || MesquiteEvent.commandOrControlKeyDown(modifiers)) && (anyColumnNameSelected() || editingColumnName())) {
if (MesquiteEvent.commandOrControlKeyDown(modifiers)) {
if (isColumnNameSelected(column))
deselectColumnName(column);
else
selectColumnName(column);
columnNames.repaint();
}
else {
deselectAllNotify();
selectColumnNames(columnFirstTouched,column);
offAllEdits();
columnNames.repaint();
}
}
else {
boolean doRepaint = (anyRowColumnSelected());
offAllEdits();
deselectAllNotify(true);
if (columnNamesAutoEditable)
editColumnNameCell(column);
else if (columnNamesSelectable)
selectColumnName(column);
if (doRepaint)
repaintAll();
else
columnNames.repaint();
columnFirstTouched = column;
}
}
/*...............................................................................................................*/
/** Called if row name is touched. Can be overridden in subclasses to change response to touch.*/
public void rowNameTouched(int row, int modifiers, int clickCount) {
if (!rowNamesEditable && !rowNamesSelectable)
return;
if (!rowLegal(row))
return;
if ((row == rowFirstTouched)&& (anyRowNameSelected() || editingRowName())) {
deselectAllNotify();
offAllEdits();
selectRowName(row);
rowNames.repaint();
}
else if ((MesquiteEvent.shiftKeyDown(modifiers) || MesquiteEvent.commandOrControlKeyDown(modifiers)) && (anyRowNameSelected() || editingRowName())) {
if (MesquiteEvent.commandOrControlKeyDown(modifiers)) {
if (isRowNameSelected(row))
deselectRowName(row);
else
selectRowName(row);
rowNames.repaint();
}
else {
deselectAllNotify();
selectRowNames(rowFirstTouched,row);
offAllEdits();
rowNames.repaint();
}
}
else {
boolean doRepaint = (anyRowColumnSelected());
offAllEdits();
deselectAllNotify(true);
if (rowNamesAutoEditable) {
editRowNameCell(row);
}
else if (rowNamesSelectable)
selectRowName(row);
if (doRepaint)
repaintAll(); // repaint section only if something in other panel had been selected (not edited)
else
rowNames.repaint();
rowFirstTouched = row;
}
}
/*...............................................................................................................*/
int firstSelectedColumn=0;
int firstSelectedRow = 0;
/** Called if column is touched. Can be overridden in subclasses to change response to touch.*/
/*...............................................................................................................*/
public void columnTouched(int column, int modifiers) {
// int[] columnsToRedraw = new int[2];
// columnsToRedraw[0] = column;
// columnsToRedraw[1] = column;
if (!columnsSelectable)
return;
if (!columnLegal(column))
return;
if (column == -1){
firstSelectedColumn = column;
offAllEdits();
deselectAllNotify();
selectRowNames(0, numRowsTotal-1);
repaintAll();
}
else if ((MesquiteEvent.shiftKeyDown(modifiers) || MesquiteEvent.commandOrControlKeyDown(modifiers)) && anyColumnSelected()) {
if (MesquiteEvent.commandOrControlKeyDown(modifiers)) {
if (isColumnSelected(column)) {
deselectColumn(column);
if (columnAssociable!=null){
columnAssociable.setSelected(column, false);
columnAssociable.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
}
}
else {
selectColumn(column);
if (columnAssociable!=null) {
columnAssociable.setSelected(column, true);
columnAssociable.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
}
}
//redrawColumnName(column);
repaintAll();
}
else { //shiftkeydown
deselectAllNotify();
selectColumns(firstSelectedColumn, column);
if (columnAssociable!=null)
columnAssociable.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
repaintAll();
}
}
else {
//redrawColumn(firstSelectedColumn);
firstSelectedColumn = column;
offAllEdits();
deselectAll();
repaintAll();
selectColumn(column);
//redrawColumn(column);
if (columnAssociable!=null) {
columnAssociable.setSelected(column, true);
columnAssociable.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
}
if (rowAssociable!=null)
rowAssociable.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
}
}
/*...............................................................................................................*/
/** Called if row is touched. Can be overridden in subclasses to change response to touch.*/
public void rowTouched(int row, int modifiers) {
if (!rowsSelectable)
return;
if (!rowLegal(row))
return;
if ((MesquiteEvent.shiftKeyDown(modifiers) || MesquiteEvent.commandOrControlKeyDown(modifiers)) && anyRowSelected()) {
if (MesquiteEvent.commandOrControlKeyDown(modifiers)) {
if (isRowSelected(row)) {
deselectRow(row);
if (rowAssociable!=null) {
rowAssociable.setSelected(row, false);
rowAssociable.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
}
}
else {
selectRow(row);
if (rowAssociable!=null) {
rowAssociable.setSelected(row, true);
rowAssociable.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
}
}
//redrawRowName(row);
repaintAll();
}
else { //shiftkeydown
deselectAll();
selectRows(firstSelectedRow, row);
if (columnAssociable!=null)
columnAssociable.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
if (rowAssociable!=null) {
rowAssociable.setSelected(row, true);
rowAssociable.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
}
repaintAll();
}
}
else {
firstSelectedRow = row;
offAllEdits();
deselectAll();
selectRow(row);
repaintAll();
if (columnAssociable!=null)
columnAssociable.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
if (rowAssociable!=null) {
rowAssociable.setSelected(row, true);
rowAssociable.notifyListeners(this, new Notification(MesquiteListener.SELECTION_CHANGED));
}
}
}
/*@@@...............................................................................................................*/
/** Called if column was dragged and dropped.
(after = -1 if dropped in front of first column; -2 if after last.)
Can be overridden in subclasses to respond. It is the responsibility of subclass
to decide if this results in moving column, or other columns were also selected and
move along too. ?Should this be called columnDragDropped?*/
public void selectedColumnsDropped(int after) {
System.out.println("Columns moved to " + after);
}
/*@@@...............................................................................................................*/
/** Called if row was dragged and dropped.
(after = -1 if dropped above first row; -2 if below last.)
Can be overridden in subclasses to respond. It is the responsibility of subclass
to decide if this results in moving a row, or other row were also selected and
move along too. ?Should this be called rowDragDropped?*/
public void selectedRowsDropped(int after) {
System.out.println("row moved to " + after);
}
/*...............................................................................................................*/
/** Returns text in cell of matrix.
Should be overridden in subclasses if text returned is appropriate. */
public String getText(int column, int row){
if (column==-1 && row == -1)
return "";
else if (column==-1)
return getRowNameText(row);
else if (row==-1)
return getColumnNameText(column);
else
return getMatrixText(column, row);
}
/*...............................................................................................................*/
/** Returns text in corner of matrix.
Should be overridden in subclasses if text returned is appropriate. */
public String getCornerText(){
return "";
}
/*...............................................................................................................*/
/** Returns text in cell of matrix, possibly adjusted to include asterisks for footnotes, etc..
Should be overridden in subclasses if text returned is appropriate. */
public String getMatrixTextForDisplay(int column, int row){
return getMatrixText(column, row);
}
/*...............................................................................................................*/
/** Returns text in cell of matrix.
Should be overridden in subclasses if text returned is appropriate. */
public String getMatrixText(int column, int row){
return "Column " + Integer.toString(column) + " Row " + Integer.toString(row);
}
/*...............................................................................................................*/
/** Returns text in column name.
Should be overridden in subclasses if text returned is appropriate. */
public String getColumnNameText(int column){
return "Column " + Integer.toString(column);
}
/*...............................................................................................................*/
/** Returns text in column heading of matrix, possibly adjusted to include asterisks for footnotes, etc..
Should be overridden in subclasses if text returned is appropriate. */
public String getColumnNameTextForDisplay(int column){
return getColumnNameText(column);
}
/*...............................................................................................................*/
/** Returns text in row name.
Should be overridden in subclasses if text returned is appropriate. */
public String getRowNameText(int row){
return "Row " + Integer.toString(row);
}
/*...............................................................................................................*/
/** Returns text in row name of matrix, possibly adjusted to include asterisks for footnotes, etc..
Should be overridden in subclasses if text returned is appropriate. */
public String getRowNameTextForDisplay(int row){
return getRowNameText(row);
}
/*...............................................................................................................*/
/** Called after editing a cell, passing the String resulting.
Can be overridden in subclasses to respond to editing.*/
public void returnedMatrixText(int column, int row, String s, CommandRecord commandRec){
System.out.println("Text [" + s + "] returned for Column " + Integer.toString(column) + " Row " + Integer.toString(row));
}
/*............................................................................................................... */
/** Called after editing a ColumnName, passing the String resulting.
Can be overridden in subclasses to respond to editing.*/
public void returnedColumnNameText(int column, String s, CommandRecord commandRec){
System.out.println("Text [" + s + "] returned for Column " + Integer.toString(column));
}
/*...............................................................................................................*/
/** Called after editing a row name, passing the String resulting.
Can be overridden in subclasses to respond to editing.*/
public void returnedRowNameText(int row, String s, CommandRecord commandRec){
System.out.println("Text [" + s + "] returned for Row " + Integer.toString(row));
}
/*...............................................................................................................*/
/** Remove all edit boxes.*/
public void offAllEdits(){
defocusCell();
matrix.offEdit();
rowNames.offEdit();
columnNames.offEdit();
}
/*...............................................................................................................*/
/** Remove all edit boxes but the one of the given panel.*/
public void offOtherEdits(EditorPanel panel){
if (panel!=matrix)
matrix.offEdit();
if (panel!=rowNames)
rowNames.offEdit();
if (panel!=columnNames)
columnNames.offEdit();
}
/*...............................................................................................................*/
/** Place text edit box in cell with current value, to allow user to edit content.*/
public void editMatrixCell(int column, int row){
if (!cellsEditable)
return;
if (columnLegal(column) && rowLegal(row)) {
deselectAllNotify();
matrix.editCell(column, row);
}
}
/*...............................................................................................................*/
/** Remove text edit box from cell.*/
public void offEditMatrixCell(){
matrix.offEdit();
}
/*...............................................................................................................*/
/** Is a matrix cell being edited?*/
public boolean editingMatrixCell(){
return matrix.getEditing();
}
/*...............................................................................................................*/
/** Requests that the column name receive a editable text field to be edited by user. NON FUNCTIONAL*/
public void editColumnNameCell(int column){
if (!columnNamesEditable)
return;
if (columnLegal(column));
columnNames.editCell(column,-1);
}
/*...............................................................................................................*/
/** Is a columnName being edited?*/
public boolean editingColumnName(){
return columnNames.getEditing();
}
/*...............................................................................................................*/
/** Requests that the row name receive a editable text field to be edited by user. NON FUNCTIONAL*/
public void editRowNameCell(int row){
if (!rowNamesEditable)
return;
if ( rowLegal(row));
rowNames.editCell(-1, row);
}
/*...............................................................................................................*/
/** Is a row name being edited?*/
public boolean editingRowName(){
return rowNames.getEditing();
}
/*...............................................................................................................*/
/** Is anything being edited?*/
public boolean editingAnything(){
return (rowNames.getEditing() || columnNames.getEditing() || matrix.getEditing());
}
/*...............................................................................................................*/
/** true if row in range of matrix.*/
public boolean rowLegal(int row){
return (row>=0 && row=0 && column c2) || (row < r1) || (row > r2)) { // not in block
if (isCellSelected(column,row)) {
deselectCell(column,row);
redrawCell(column,row);
}
}
}
}
/*...............................................................................................................*/
/** Selects column.*/
public void selectColumn(int column){
if (columnLegal(column))
columnsSelected[0].setBit(column);
}
/*...............................................................................................................*/
/** Selects columns*/
public void selectColumns(int first, int last){
if (columnLegal(first) && columnLegal(last)) {
int r1 = MesquiteInteger.minimum(first, last);
int r2 = MesquiteInteger.maximum(first, last);
for (int i = r1; i<=r2; i++) {
columnsSelected[0].setBit(i);
if (columnAssociable!=null)
columnAssociable.setSelected(i, true);
}
}
}
/*...............................................................................................................*/
/** Selects column names.*/
public void selectColumnNames(int first, int last){
if (columnLegal(first) && columnLegal(last)) {
int r1 = MesquiteInteger.minimum(first, last);
int r2 = MesquiteInteger.maximum(first, last);
for (int i = r1; i<=r2; i++) {
columnNamesSelected[0].setBit(i);
}
}
}
/*...............................................................................................................*/
/** Selects column name.*/
public void selectColumnName(int column){
if (columnLegal(column))
columnNamesSelected[0].setBit(column);
}
/*...............................................................................................................*/
/** Selects row names*/
public void selectRowNames(int first, int last){
if (rowLegal(first) && rowLegal(last)) {
int r1 = MesquiteInteger.minimum(first, last);
int r2 = MesquiteInteger.maximum(first, last);
for (int i = r1; i<=r2; i++) {
rowNamesSelected[0].setBit(i);
}
}
}
/*...............................................................................................................*/
/** Selects row name.*/
public void selectRowName(int row){
if (rowLegal(row))
rowNamesSelected[0].setBit(row);
}
/*...............................................................................................................*/
/** returns whether anything in matrix is selected.*/
public boolean anythingSelected(){
return (anyRowSelected() || anyColumnSelected() || anyRowNameSelected() || anyColumnNameSelected() || anyCellSelected());
}
/*...............................................................................................................*/
/** returns whether any cell in matrix is selected in any way.*/
public boolean anyCellSelectedAnyWay(){
return (anyRowSelected() || anyColumnSelected() || anyCellSelected());
}
/*...............................................................................................................*/
/** returns whether any row or column in matrix is selected.*/
public boolean anyRowColumnSelected(){
return (anyRowSelected() || anyColumnSelected());
}
/*...............................................................................................................*/
/** returns whether any cell in central matrix is selected.*/
public boolean anyCellSelected(){
return cellsSelected[0].anyBitsOn();
}
/*...............................................................................................................*/
/** returns whether any row name is selected.*/
public boolean anyRowNameSelected(){
return rowNamesSelected[0].anyBitsOn();
}
/*...............................................................................................................*/
/** returns whether any column name is selected.*/
public boolean anyColumnNameSelected(){
return columnNamesSelected[0].anyBitsOn();
}
/*...............................................................................................................*/
/** returns whether any row is selected.*/
public boolean anyRowSelected(){
return rowsSelected[0].anyBitsOn();
}
/*...............................................................................................................*/
/** returns whether any column is selected.*/
public boolean anyColumnSelected(){
return columnsSelected[0].anyBitsOn();
}
/*...............................................................................................................*/
/** returns whether anything in the main table (cell, row or column) is selected.*/
public boolean anyMainTableCellSelected(){
return (anyCellSelected()||anyRowSelected()||anyColumnSelected());
}
/*...............................................................................................................*/
/** returns first row selected.*/
public int firstRowSelected(){
return rowsSelected[0].firstBitOn();
}
/*...............................................................................................................*/
/** returns first column selected.*/
public int firstColumnSelected(){
return columnsSelected[0].firstBitOn();
}
/*...............................................................................................................*/
/** returns the first column in the central matrix in which there is at least one cell selected.*/
public int firstRowWithSelectedCell(){
if (cellsSelected[0].anyBitsOn()) {
for (int row = 0; row=0; row--) {
for(int column=0; column=0; column--) {
for (int row = 0; row= numColumnsTotal-1) // end of previous row
tempLastRow++;
else tempLastColumn ++;
if (tempLastRow>=numRowsTotal)
return false;
for (int i=tempLastRow; i1)
return false;
total += rowNamesSelected[0].numBitsOnPlural();
if (total>1)
return false;
total += columnNamesSelected[0].numBitsOnPlural();
if (total>1)
return false;
return ((total==1) && !anyRowSelected() && !anyColumnSelected());
}
/*...............................................................................................................*/
/** returns column and row of first cell selected (-2, -2 if none).*/
public Dimension getFirstTableCellSelected(){
if (numColumnsTotal== 0)
return new Dimension(-2, -2);
int firstCell = cellsSelected[0].firstBitOn();
if (firstCell >= 0)
return new Dimension(firstCell % numColumnsTotal, firstCell /numColumnsTotal);
firstCell = rowNamesSelected[0].firstBitOn();
if (firstCell >= 0)
return new Dimension(-1, firstCell);
firstCell = columnNamesSelected[0].firstBitOn();
if (firstCell >= 0)
return new Dimension(firstCell, -1);
return new Dimension(-2, -2);
}
/*...............................................................................................................*/
/** returns number of columns are selected.*/
public int numColumnsSelected(){
return columnsSelected[0].numBitsOn();
}
/*...............................................................................................................*/
/** returns whether cell in central matrix is selected (does not return true if whole row or column is selected).*/
public boolean isCellSelected(int column, int row){
if (columnLegal(column) && rowLegal(row))
return cellsSelected[0].isBitOn(row*numColumnsTotal + column);
return false;
}
/*...............................................................................................................*/
/** returns whether cell in central matrix is selected.*/
public boolean isCellSelectedAnyWay(int column, int row){
if (columnLegal(column) && rowLegal(row))
return (cellsSelected[0].isBitOn(row*numColumnsTotal + column)) || isRowSelected(row) || isColumnSelected(column);
return false;
}
public void synchronizeRowSelection(Associable a){
if (a==null)
return;
rowsSelected[0].clearAll