///////////////////////////////////////////////////////////////////////////// // Name: TextGrid Class // // Last Modified: May 7, 1997 // // Author: Michael Chu (mmchu@pobox.com) // // Purpose: TextGrid component. // // // // Copyright (C) 1997 Michael Chu // // // // This program is free software; you can redistribute it and/or modify // // it under the terms of the GNU General Public License as published by // // the Free Software Foundation; either version 2 of the License, or // // (at your option) any later version. // // // // This program is distributed in the hope that it will be useful, // // but WITHOUT ANY WARRANTY; without even the implied warranty of // // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // // GNU General Public License for more details. // // // // You should have received a copy of the GNU General Public License // // along with this program; if not, write to the Free Software // // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // // // // Contact information: Michael Chu // // mmchu@pobox.com // ///////////////////////////////////////////////////////////////////////////// // Import for windowing widgets. import java.awt.*; // Import for Vector. import java.util.Vector; // Class for the TextGrid component. public class TextGrid extends Canvas { // ***************************************************************** // **************************** ELEMENTS *************************** // ***************************************************************** // ************************ GENERAL ELEMENTS *********************** // stores the desired dimensions of the grid. private int numRows; private int numCols; // stores the color we use for the background. private Color backgroundColor; // stores the color we use for the grid lines. private Color gridLineColor; // stores the color we use for the text. private Color textColor; // stores the font we use for the text. private Font textFont; // flag for whether we are currently selecting. private boolean currentlySelecting; // flag for whether we have anything selected. private boolean currentlyHaveSelected; // stores the starting cell of the selecting. private int selectingStartRow; private int selectingStartCol; // stores the ending cell of the selecting. private int selectingEndRow; private int selectingEndCol; // the GridSpan representation of the selected region. private GridSpan selectedGridSpan; // flag for whether we should do snap-to-grid-coloring selecting. private boolean snapToGridColoringSelect; // flag for whether we have currently snap-to selected anything. private boolean haveSnapToSelected; // stores is multiple rows/columns are allowed to be selected. private boolean multiRowOK; private boolean multiColOK; // stores the color we use for selected color. private Color selectedColor; // stores the grid colorings. private Vector gridColorings; // flags if we are in middle of a select. private boolean selectionInProgress; // added to help reduce flicker. private Image offScreenImage; private Dimension offScreenSize; private Graphics offScreenGraphics; // ***************************************************************** // *************************** METHODS ***************************** // ***************************************************************** // ******************** INITIALIZATION METHODS ********************* // constructor for the TextGrid component. public TextGrid(int rows, int cols) { // set the row and column numbers. numRows = rows; numCols = cols; // by default, the background color is lightGray. backgroundColor = Color.lightGray; // by default, the grid line color is black. gridLineColor = Color.black; // by default, the text color is black. textColor = Color.black; // by default, the text font is TimesRoman, PLAIN, and point size 14. textFont = new Font("TimesRoman", Font.PLAIN, 14); // reset currentlySelecting flag. currentlySelecting = false; // reset currentlyHaveSelected flag. currentlyHaveSelected = false; // create a selectedGridSpan object. selectedGridSpan = new GridSpan(); // by default, we will not do snap-to-grid-coloring selecting. snapToGridColoringSelect = false; // by default, we do not have any snap-to selection. haveSnapToSelected = false; // by default, we can select multiple rows and columns. multiRowOK = true; multiColOK = true; // by default, the selected color is pink. selectedColor = Color.pink; // create an empty vector for grid colorings. gridColorings = new Vector(); // by default, no selection in progress. selectionInProgress = false; // clear the selected information. clearSelected(); // clear the grid coloring information. clearGridColoring(); } // allows setting of the grid dimensions. public void setNumRows(int rows) { numRows = rows; } public void setNumCols(int cols) { numCols = cols; } // allows setting of the background color. public void setBackgroundColor(Color newColor) { backgroundColor = newColor; } // allows setting of the grid line color. public void setGridLineColor(Color newColor) { gridLineColor = newColor; } // allows setting of the text color. public void setTextColor(Color newColor) { textColor = newColor; } // allows setting of the text font. public void setTextFont(Font newFont) { textFont = newFont; } // allows setting snap-to-grid-coloring selecting. public void setSnapToGridColoringSelect(boolean snapSelect) { snapToGridColoringSelect = snapSelect; } // allows setting multiple rows/columns selection. public void setMultiRowOK(boolean ok) { multiRowOK = ok; } public void setMultiColOK(boolean ok) { multiColOK = ok; } // allows setting of the selected color. public void setSelectedColor(Color newColor) { selectedColor = newColor; } // ******************* GENERAL DISPLAY METHODS ********************* // paints the grid and all appropriate information on the screen. public void paint(Graphics graphic) { // size of the component. int gridHeight; int gridWidth; // size of the individual cells. int cellHeight; int cellWidth; // counters for drawing cell separators. int currentHeightLocation; int currentWidthLocation; int currentNumHorizontal; int currentNumVertical; // store the current grid span. GridSpan currentGridSpan; // size of the grid span vector. int numGridSpans; // counter for which grid span we are filling in. int currentGridSpanIndex; // intersect color. Color intersectColor; // calculate the size of the component. gridHeight = size().height; gridWidth = size().width; // calculate the size of individual cells. cellHeight = (gridHeight - 1) / numRows; cellWidth = (gridWidth - 1) / numCols; // clear the entire area. graphic.setColor(backgroundColor); graphic.fillRect(0, 0, gridWidth, gridHeight); // we will now adjust gridHeight/gridWidth so they are perfect // for the row/column numbers we have. gridHeight = gridHeight - (gridHeight % cellHeight) + 1; gridWidth = gridWidth - (gridWidth % cellWidth) + 1; // set the color to grid line color. graphic.setColor(gridLineColor); // paint the border first. graphic.drawLine(0, 0, 0, (gridHeight - 1)); graphic.drawLine(0, (gridHeight - 1), (gridWidth - 1), (gridHeight - 1)); graphic.drawLine((gridWidth - 1), (gridHeight - 1), (gridWidth - 1), 0); graphic.drawLine((gridWidth - 1), 0, 0, 0); // draw the separators. currentHeightLocation = cellHeight; for (currentNumHorizontal = 1; currentNumHorizontal <= (numRows - 1); currentNumHorizontal++) { // draw horizontal line. graphic.drawLine(0, currentHeightLocation, (gridWidth - 1), currentHeightLocation); // increment to next location. currentHeightLocation = currentHeightLocation + cellHeight; } currentWidthLocation = cellWidth; for (currentNumVertical = 1; currentNumVertical <= (numCols - 1); currentNumVertical++) { // draw vertical line. graphic.drawLine(currentWidthLocation, 0, currentWidthLocation, (gridHeight - 1)); // increment to next location. currentWidthLocation = currentWidthLocation + cellWidth; } // if we are currently selecting or there is anything selected, // then set the background of those cells to be selected. if (currentlySelecting || currentlyHaveSelected) { // display the selectedgridSpan. displayGridSpanColor(graphic, selectedGridSpan); } // if there is anything that should be grid colored, then color them // (and set text, if applicable). if (!(gridColorings.isEmpty())) { // get the number of elements in the vector. numGridSpans = gridColorings.size(); // cycle through all the grid spans. for (currentGridSpanIndex = 0; currentGridSpanIndex <= (numGridSpans - 1); currentGridSpanIndex++) { // get the current grid span. currentGridSpan = (GridSpan) gridColorings.elementAt(currentGridSpanIndex); // display the color of the span. displayGridSpanColor(graphic, currentGridSpan); // if there was an intersection with the selected area, then // color that area differently. if ((currentlySelecting || currentlyHaveSelected) && gridSpansDoIntersect(selectedGridSpan, currentGridSpan)) { // average select color and grid color to get intersect color. intersectColor = new Color(((selectedGridSpan.spanColor.getRed() + currentGridSpan.spanColor.getRed()) / 2), ((selectedGridSpan.spanColor.getGreen() + currentGridSpan.spanColor.getGreen()) / 2), ((selectedGridSpan.spanColor.getBlue() + currentGridSpan.spanColor.getBlue()) / 2)); // display intersect section. displayGridSpanColor(graphic, intersectGridSpan(selectedGridSpan, currentGridSpan, intersectColor)); } // display the text of the span. displayGridSpanText(graphic, currentGridSpan); } } } // displays a grid span (color). private void displayGridSpanColor(Graphics graphic, GridSpan gridSpan) { // size of the component. int gridHeight; int gridWidth; // size of the individual cells. int cellHeight; int cellWidth; // calculate the size of the component. gridHeight = size().height; gridWidth = size().width; // calculate the size of individual cells. cellHeight = (gridHeight - 1) / numRows; cellWidth = (gridWidth - 1) / numCols; // set the span color. graphic.setColor(gridSpan.spanColor); // fill in the selected region. graphic.fillRect(((gridSpan.startCol * cellWidth) + 1), ((gridSpan.startRow * cellHeight) + 1), (((gridSpan.endCol - gridSpan.startCol + 1) * cellWidth) - 1), (((gridSpan.endRow - gridSpan.startRow + 1) * cellHeight) - 1)); } // displays a grid span (text). private void displayGridSpanText(Graphics graphic, GridSpan gridSpan) { // size of the component. int gridHeight; int gridWidth; // size of the individual cells. int cellHeight; int cellWidth; // adjusted font to make sure font fits in grid cell. Font adjustedFont; // adjusted string to make sure string fits in grid cell. String adjustedString; // stores the row where text should appear. int textRow; // stores the row pixel where text should appear. int textRowPixel; // stores the font metrics for the current font. FontMetrics fontMetrics; // calculate the size of the component. gridHeight = size().height; gridWidth = size().width; // calculate the size of individual cells. cellHeight = (gridHeight - 1) / numRows; cellWidth = (gridWidth - 1) / numCols; // if there is text, then print out the text. if (gridSpan.spanHasString) { // calculate the row in which text will appear. textRow = (gridSpan.startRow + gridSpan.endRow) / 2; // adjust text font to fit in grid cell. adjustedFont = new Font(textFont.getName(), textFont.getStyle(), textFont.getSize()); do { // change font to adjusted text font. graphic.setFont(adjustedFont); // get the font metrics for current font. fontMetrics = graphic.getFontMetrics(); // if this font results in text too large for the cell, then // change font size. if (fontMetrics.getHeight() > cellHeight) { // size font down by one size. adjustedFont = new Font(adjustedFont.getName(), adjustedFont.getStyle(), (adjustedFont.getSize() - 1)); } } while (fontMetrics.getHeight() > cellHeight); // adjust text string to fit in grid cell. adjustedString = new String(gridSpan.spanString); while (fontMetrics.stringWidth(adjustedString) > (cellWidth - (3 * 2))) { // remove one character from the string. adjustedString = adjustedString.substring(0, (adjustedString.length() - 2)); } // calculate the row pixel where the text should appear. textRowPixel = ((textRow + 1) * cellHeight) - ((cellHeight - fontMetrics.getAscent()) / 2); // change color to text color. graphic.setColor(textColor); // write out the text. graphic.drawString(adjustedString, ((gridSpan.startCol * cellWidth) + 3), textRowPixel); } } // This code was copied to help reduce flicker. public final synchronized void update (Graphics g) { Dimension d = size(); if ((offScreenImage == null) || (d.width != offScreenSize.width) || (d.height != offScreenSize.height)) { offScreenImage = createImage(d.width, d.height); offScreenSize = d; offScreenGraphics = offScreenImage.getGraphics(); } offScreenGraphics.clearRect(0, 0, d.width, d.height); paint(offScreenGraphics); g.drawImage(offScreenImage, 0, 0, null); } // ********************* SUPPORT METHODS ************************* // handle events in the Grid component. public boolean handleEvent(Event event) { // size of the component. int gridHeight; int gridWidth; // size of the individual cells. int cellHeight; int cellWidth; // the index of the cell mouse currently in. int mouseRowIndex; int mouseColIndex; // indicates if mouse is currently within Grid bounds. boolean mouseWithinGrid; // used to fill in the selected section. int selectLowRow; int selectLowCol; int selectHighRow; int selectHighCol; // used to check intersection of first click. GridSpan firstClickSpan; // stores the snapped-to selection. GridSpan snapToSelection; // calculate the size of the component. gridHeight = size().height - 1; gridWidth = size().width - 1; // calculate the size of individual cells. cellHeight = gridHeight / numRows; cellWidth = gridWidth / numCols; // we will now adjust gridHeight/gridWidth so they are perfect // for the row/column numbers we have. gridHeight = gridHeight - (gridHeight % cellHeight) + 1; gridWidth = gridWidth - (gridWidth % cellWidth) + 1; // handle mouse clicks and drags. if ((event.id == Event.MOUSE_DOWN) || (event.id == Event.MOUSE_UP) || (event.id == Event.MOUSE_DRAG)) { // calculate the row and column the mouse is currently in. mouseRowIndex = event.y / cellHeight; mouseColIndex = event.x / cellWidth; // check to see if mouse is within Grid bounds. if ((event.x >= 0) && (event.x <= (gridWidth - 1)) && (event.y >= 0) && (event.y <= (gridHeight - 1)) && (mouseRowIndex >= 0) && (mouseRowIndex <= (numRows - 1)) && (mouseColIndex >= 0) && (mouseColIndex <= (numCols - 1))) { mouseWithinGrid = true; } else { mouseWithinGrid = false; } // if the mouse is in the grid, then handle the possible // events. if (mouseWithinGrid) { // handle clicks and drags. if (event.id == Event.MOUSE_DOWN) { // create a span for checking click for intersections. firstClickSpan = new GridSpan(mouseRowIndex, mouseColIndex, mouseRowIndex, mouseColIndex); // set selectionInProgress. selectionInProgress = true; // if we do not intersect anyone, then just setup for more // selecting. if (!(willIntersectExistingColoring(firstClickSpan)) || !snapToGridColoringSelect) { // set the selecting flag. currentlySelecting = true; // reset the currentlyHaveSelected flag. currentlyHaveSelected = false; // reset the haveSnapToSelected flag. haveSnapToSelected = false; // set the start/end row/column of the selection. selectingStartRow = mouseRowIndex; selectingStartCol = mouseColIndex; selectingEndRow = mouseRowIndex; selectingEndCol = mouseColIndex; // set the selectedGridSpan variable. selectedGridSpan.startRow = selectingStartRow; selectedGridSpan.startCol = selectingStartCol; selectedGridSpan.endRow = selectingEndRow; selectedGridSpan.endCol = selectingEndCol; selectedGridSpan.spanColor = selectedColor; } else { // get the snap to selection. snapToSelection = intersectWhichExistingColoring(firstClickSpan); // reset the selecting flag. currentlySelecting = false; // set the currentlyHaveSelected flag. currentlyHaveSelected = true; // set the haveSnapToSelected flag. haveSnapToSelected = true; // set the start/end row/column of the selection. selectingStartRow = snapToSelection.startRow; selectingStartCol = snapToSelection.startCol; selectingEndRow = snapToSelection.endRow; selectingEndCol = snapToSelection.endCol; // set the selectedGridSpan variable. selectedGridSpan.startRow = selectingStartRow; selectedGridSpan.startCol = selectingStartCol; selectedGridSpan.endRow = selectingEndRow; selectedGridSpan.endCol = selectingEndCol; selectedGridSpan.spanColor = selectedColor; } // force repaint. repaint(); } else if (event.id == Event.MOUSE_UP) { // reset selectionInProgress. selectionInProgress = false; // if were currently selecting, then reset the flag and also // set that we now have something selected. if (currentlySelecting) { // reset currentlySelecting flag. currentlySelecting = false; // set the currentlyHaveSelected flag. currentlyHaveSelected = true; } } else if (event.id == Event.MOUSE_DRAG) { // if we are currently selecting, then consider drags. if (currentlySelecting) { // if we are not allowed to select multiple rows/columns, then // constrain the indices appropriately. if (!multiRowOK) { mouseRowIndex = selectingStartRow; } if (!multiColOK) { mouseColIndex = selectingStartCol; } // if we are not the same as the last cell we were in, then // update. if ((mouseRowIndex != selectingEndRow) || (mouseColIndex != selectingEndCol)) { // store the new ending cell. selectingEndRow = mouseRowIndex; selectingEndCol = mouseColIndex; // get the low and high ends of the selected region. if (selectingStartRow <= selectingEndRow) { selectLowRow = selectingStartRow; selectHighRow = selectingEndRow; } else { selectLowRow = selectingEndRow; selectHighRow = selectingStartRow; } if (selectingStartCol <= selectingEndCol) { selectLowCol = selectingStartCol; selectHighCol = selectingEndCol; } else { selectLowCol = selectingEndCol; selectHighCol = selectingStartCol; } // set the selectedGridSpan variable. selectedGridSpan.startRow = selectLowRow; selectedGridSpan.startCol = selectLowCol; selectedGridSpan.endRow = selectHighRow; selectedGridSpan.endCol = selectHighCol; selectedGridSpan.spanColor = selectedColor; // force repaint. repaint(); } } } } } // pass event up to higher level. return super.handleEvent(event); } // returns whether or not the two given GridSpans intersect or not. private boolean gridSpansDoIntersect(GridSpan firstSpan, GridSpan secondSpan) { // easier to test if do not intersect! if (firstSpan.startRow > secondSpan.endRow) { return false; } if (firstSpan.startCol > secondSpan.endCol) { return false; } if (firstSpan.endRow < secondSpan.startRow) { return false; } if (firstSpan.endCol < secondSpan.startCol) { return false; } // if we made it this far, then we intersect! return true; } // returns the GridSpan intersection of the two given GridSpans. // assumes that gridSpansDoIntersect() has been called already and // that they DO intersect! private GridSpan intersectGridSpan(GridSpan firstSpan, GridSpan secondSpan, Color intersectColor) { // new GridSpan. GridSpan newGridSpan; // create a new GridSpan. newGridSpan = new GridSpan(); // set the new GridSpan for intersection. if (firstSpan.startRow > secondSpan.startRow) { newGridSpan.startRow = firstSpan.startRow; } else { newGridSpan.startRow = secondSpan.startRow; } if (firstSpan.startCol > secondSpan.startCol) { newGridSpan.startCol = firstSpan.startCol; } else { newGridSpan.startCol = secondSpan.startCol; } if (firstSpan.endRow < secondSpan.endRow) { newGridSpan.endRow = firstSpan.endRow; } else { newGridSpan.endRow = secondSpan.endRow; } if (firstSpan.endCol < secondSpan.endCol) { newGridSpan.endCol = firstSpan.endCol; } else { newGridSpan.endCol = secondSpan.endCol; } newGridSpan.spanColor = intersectColor; newGridSpan.spanHasString = false; return newGridSpan; } // clear the selected cell information (flags and start/end cells) // (NOT info in the cells!). public void clearSelected() { // reset flag of currently selecting anything. currentlySelecting = false; // reset flag of having anything currently selected. currentlyHaveSelected = false; // reset flag of having anything snap-to selected. haveSnapToSelected = false; // set the selected cells information to invalid settings. selectingStartRow = -1; selectingStartCol = -1; selectingEndRow = -1; selectingEndCol = -1; } // clear the grid coloring information. public void clearGridColoring() { // remove all vector elements. gridColorings.removeAllElements(); } // clears all coloring and selections. public void clearAll() { clearSelected(); clearGridColoring(); } // add grid coloring (and also text). // we will silently discard anything which is outside the bounds of // our grid or that intersects with existing colorings. public void addGridColoring(int startRow, int startCol, int endRow, int endCol, Color spanColor) { // holds new grid span. GridSpan newGridSpan; // make sure indices are inside of grid. if ((startRow >= 0) && (startRow <= (numRows - 1)) && (startCol >= 0) && (startCol <= (numCols - 1)) && (endRow >= 0) && (endRow <= (numRows - 1)) && (endCol >= 0) && (endCol <= (numCols - 1))) { // create new grid span. newGridSpan = new GridSpan(); // set the grid span. if (startRow <= endRow) { newGridSpan.startRow = startRow; newGridSpan.endRow = endRow; } else { newGridSpan.startRow = endRow; newGridSpan.endRow = startRow; } if (startCol <= endCol) { newGridSpan.startCol = startCol; newGridSpan.endCol = endCol; } else { newGridSpan.startCol = endCol; newGridSpan.endCol = startCol; } newGridSpan.spanColor = spanColor; newGridSpan.spanHasString = false; // make sure not intersecting existing coloring. if (!(willIntersectExistingColoring(newGridSpan))) { // add the new grid span to the grid coloring. gridColorings.addElement(newGridSpan); } } } public void addGridColoring(int startRow, int startCol, int endRow, int endCol, Color spanColor, String spanString) { // holds new grid span. GridSpan newGridSpan; // make sure indices are inside of grid. if ((startRow >= 0) && (startRow <= (numRows - 1)) && (startCol >= 0) && (startCol <= (numCols - 1)) && (endRow >= 0) && (endRow <= (numRows - 1)) && (endCol >= 0) && (endCol <= (numCols - 1))) { // create new grid span. newGridSpan = new GridSpan(); // set the grid span. if (startRow <= endRow) { newGridSpan.startRow = startRow; newGridSpan.endRow = endRow; } else { newGridSpan.startRow = endRow; newGridSpan.endRow = startRow; } if (startCol <= endCol) { newGridSpan.startCol = startCol; newGridSpan.endCol = endCol; } else { newGridSpan.startCol = endCol; newGridSpan.endCol = startCol; } newGridSpan.spanColor = spanColor; newGridSpan.spanHasString = true; newGridSpan.spanString = spanString; // make sure not intersecting existing coloring. if (!(willIntersectExistingColoring(newGridSpan))) { // add the new grid span to the grid coloring. gridColorings.addElement(newGridSpan); } } } public void addGridColoring(GridSpan newSpan) { // call the other versions to make sure bounds are correct. if (newSpan.spanHasString) { addGridColoring(newSpan.startRow, newSpan.startCol, newSpan.endRow, newSpan.endCol, newSpan.spanColor, newSpan.spanString); } else { addGridColoring(newSpan.startRow, newSpan.startCol, newSpan.endRow, newSpan.endCol, newSpan.spanColor); } } // checks to see if new span will intersect any existing colorings. public boolean willIntersectExistingColoring(GridSpan testGridSpan) { // store the current grid span. GridSpan currentGridSpan; // size of the grid span vector. int numGridSpans; // counter for which grid span we are filling in. int currentGridSpanIndex; // get the number of elements in the vector. numGridSpans = gridColorings.size(); // cycle through all the grid spans. for (currentGridSpanIndex = 0; currentGridSpanIndex <= (numGridSpans - 1); currentGridSpanIndex++) { // get the current grid span. currentGridSpan = (GridSpan) gridColorings.elementAt(currentGridSpanIndex); // if there is an intersection, then return true. if (gridSpansDoIntersect(testGridSpan, currentGridSpan)) { return true; } } // if we made it this far, then no intersections! return false; } public boolean willIntersectExistingColoring(int startRow, int startCol, int endRow, int endCol) { return willIntersectExistingColoring(new GridSpan(startRow, startCol, endRow, endCol)); } // returns the span that will be intersected by given span. // we assume that we have already checked that given span DOES intersect // with coloring. otherwise, return is unspecified. public GridSpan intersectWhichExistingColoring(GridSpan testGridSpan) { // store the current grid span. GridSpan currentGridSpan; // size of the grid span vector. int numGridSpans; // counter for which grid span we are filling in. int currentGridSpanIndex; // get the number of elements in the vector. numGridSpans = gridColorings.size(); // cycle through all the grid spans. for (currentGridSpanIndex = 0; currentGridSpanIndex <= (numGridSpans - 1); currentGridSpanIndex++) { // get the current grid span. currentGridSpan = (GridSpan) gridColorings.elementAt(currentGridSpanIndex); // if there is an intersection, then return true. if (gridSpansDoIntersect(testGridSpan, currentGridSpan)) { return currentGridSpan; } } // if we made it this far, then no intersections! BAD! return testGridSpan; } public GridSpan intersectWhichExistingColoring(int startRow, int startCol, int endRow, int endCol) { return intersectWhichExistingColoring(new GridSpan(startRow, startCol, endRow, endCol)); } // allows user to find out if we are currently selecting. public boolean nowSelecting() { return currentlySelecting; } // allows user to find out if anything was selected. public boolean anySelected() { return currentlyHaveSelected; } // allows user to find out if anything was snap-to selected. public boolean anySnapToSelected() { return haveSnapToSelected; } // allows user to get the first click. public int getFirstClickRow() { return selectingStartRow; } public int getFirstClickCol() { return selectingStartCol; } // allows user to get the low/high rows/cols of selected // area (if any). // if nothing selected (by checking anySelected()) then values are // unspecified. public int getSelectedLowRow() { return selectedGridSpan.startRow; } public int getSelectedLowCol() { return selectedGridSpan.startCol; } public int getSelectedHighRow() { return selectedGridSpan.endRow; } public int getSelectedHighCol() { return selectedGridSpan.endCol; } // allows user to set the selected area. this is applicable if, say // the user implemented a scrollbar next to the textgrid. public void setSelectedArea(int startRow, int startCol, int endRow, int endCol) { // make sure indices are inside of grid. if ((startRow >= 0) && (startRow <= (numRows - 1)) && (startCol >= 0) && (startCol <= (numCols - 1)) && (endRow >= 0) && (endRow <= (numRows - 1)) && (endCol >= 0) && (endCol <= (numCols - 1))) { // get the low and high ends of the selected region. if (startRow <= endRow) { selectingStartRow = startRow; selectingEndRow = endRow; } else { selectingStartRow = endRow; selectingEndRow = startRow; } if (startCol <= endCol) { selectingStartCol = startCol; selectingEndCol = endCol; } else { selectingStartCol = endCol; selectingEndCol = startCol; } // set the selectedGridSpan variable. selectedGridSpan.startRow = selectingStartRow; selectedGridSpan.startCol = selectingStartCol; selectedGridSpan.endRow = selectingEndRow; selectedGridSpan.endCol = selectingEndCol; selectedGridSpan.spanColor = selectedColor; // set currentlyHaveSelected flag. currentlyHaveSelected = true; // reset snap-to select. haveSnapToSelected = false; } } public void setSelectedArea(GridSpan newSpan) { // call the other versions to make sure bounds are correct. setSelectedArea(newSpan.startRow, newSpan.startCol, newSpan.endRow, newSpan.endRow); } // returns the dimensions of the grid/cells. public int getNumRows() { return numRows; } public int getNumCols() { return numCols; } public int getCellWidth() { // size of the component. int gridWidth; // size of the individual cells. int cellWidth; // calculate the size of the component. gridWidth = size().width; // calculate the size of individual cells. cellWidth = (gridWidth - 1) / numCols; return cellWidth; } public int getCellHeight() { // size of the component. int gridHeight; // size of the individual cells. int cellHeight; // calculate the size of the component. gridHeight = size().height; // calculate the size of individual cells. cellHeight = (gridHeight - 1) / numRows; return cellHeight; } // returns the background color. public Color getBackgroundColor() { return backgroundColor; } // returns the grid line color. public Color getGridLineColor() { return gridLineColor; } // returns the text color. public Color getTextColor() { return textColor; } // returns the text font. public Font getTextFont() { return textFont; } // returns setting of snap-to-grid-coloring selecting. public boolean getSnapToGridColoringSelect() { return snapToGridColoringSelect; } // returns setting multiple rows/columns selection. public boolean getMultiRowOK() { return multiRowOK; } public boolean getMultiColOK() { return multiColOK; } // returns setting of the selected color. public Color getSelectedColor() { return selectedColor; } // returns if selection is in progress. public boolean isSelectionInProgress() { return selectionInProgress; } } // Class for storing grid selections spans. class GridSpan { // ***************************************************************** // **************************** ELEMENTS *************************** // ***************************************************************** // ************************ GENERAL ELEMENTS *********************** // stores the rows and columns of the start and end of selection. public int startRow; public int startCol; public int endRow; public int endCol; // stores the color of the span. public Color spanColor; // stores if there is a string for the span. public boolean spanHasString; // stores the string for the span if there is one. public String spanString; // ***************************************************************** // *************************** METHODS ***************************** // ***************************************************************** // ******************** INITIALIZATION METHODS ********************* // constructors for GridSpan. public GridSpan() { // set variable to invalid values. startRow = -1; startCol = -1; endRow = -1; endCol = -1; spanColor = Color.black; spanHasString = false; } public GridSpan(int rowStart, int colStart, int rowEnd, int colEnd) { // set variable to invalid values. startRow = rowStart; startCol = colStart; endRow = rowEnd; endCol = colEnd; spanColor = Color.black; spanHasString = false; } public GridSpan(int rowStart, int colStart, int rowEnd, int colEnd, Color color) { // set variable to invalid values. startRow = rowStart; startCol = colStart; endRow = rowEnd; endCol = colEnd; spanColor = color; spanHasString = false; } public GridSpan(int rowStart, int colStart, int rowEnd, int colEnd, Color color, String string) { // set variable to invalid values. startRow = rowStart; startCol = colStart; endRow = rowEnd; endCol = colEnd; spanColor = color; spanHasString = true; spanString = string; } }