Reindent to 4 spaces - optimize imports

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1870977 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Andreas Beeker 2019-12-07 11:53:48 +00:00
parent b2a33515e9
commit de2467e9ae
8 changed files with 1393 additions and 1338 deletions

View File

@ -15,10 +15,12 @@
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.view;
import java.awt.*;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import javax.swing.border.AbstractBorder;
@ -26,532 +28,532 @@ import org.apache.poi.ss.usermodel.BorderStyle;
/**
* This is an attempt to implement Excel style borders for the SheetViewer.
* Mostly just overrides stuff so the javadoc won't appear here but will
* Mostly just overrides stuff so the javadoc won't appear here but will
* appear in the generated stuff.
*
*
* @author Andrew C. Oliver (acoliver at apache dot org)
* @author Jason Height
*/
public class SVBorder extends AbstractBorder {
private Color northColor;
private Color eastColor;
private Color southColor;
private Color westColor;
private BorderStyle northBorderType = BorderStyle.NONE;
private BorderStyle eastBorderType = BorderStyle.NONE;
private BorderStyle southBorderType = BorderStyle.NONE;
private BorderStyle westBorderType = BorderStyle.NONE;
private boolean northBorder;
private boolean eastBorder;
private boolean southBorder;
private boolean westBorder;
private boolean selected;
private Color northColor;
private Color eastColor;
private Color southColor;
private Color westColor;
private BorderStyle northBorderType = BorderStyle.NONE;
private BorderStyle eastBorderType = BorderStyle.NONE;
private BorderStyle southBorderType = BorderStyle.NONE;
private BorderStyle westBorderType = BorderStyle.NONE;
private boolean northBorder;
private boolean eastBorder;
private boolean southBorder;
private boolean westBorder;
private boolean selected;
public void setBorder(Color northColor, Color eastColor,
Color southColor, Color westColor,
BorderStyle northBorderType, BorderStyle eastBorderType,
BorderStyle southBorderType, BorderStyle westBorderType,
boolean selected) {
this.eastColor = eastColor;
this.southColor = southColor;
this.westColor = westColor;
this.northBorderType = northBorderType;
this.eastBorderType = eastBorderType;
this.southBorderType = southBorderType;
this.westBorderType = westBorderType;
this.northBorder=northBorderType != BorderStyle.NONE;
this.eastBorder=eastBorderType != BorderStyle.NONE;
this.southBorder=southBorderType != BorderStyle.NONE;
this.westBorder=westBorderType != BorderStyle.NONE;
this.selected = selected;
}
public void setBorder(Color northColor, Color eastColor,
Color southColor, Color westColor,
BorderStyle northBorderType, BorderStyle eastBorderType,
BorderStyle southBorderType, BorderStyle westBorderType,
boolean selected) {
this.eastColor = eastColor;
this.southColor = southColor;
this.westColor = westColor;
this.northBorderType = northBorderType;
this.eastBorderType = eastBorderType;
this.southBorderType = southBorderType;
this.westBorderType = westBorderType;
this.northBorder = northBorderType != BorderStyle.NONE;
this.eastBorder = eastBorderType != BorderStyle.NONE;
this.southBorder = southBorderType != BorderStyle.NONE;
this.westBorder = westBorderType != BorderStyle.NONE;
this.selected = selected;
}
@Override
public void paintBorder(Component c, Graphics g, int x, int y, int width,
int height) {
Color oldColor = g.getColor();
@Override
public void paintBorder(Component c, Graphics g, int x, int y, int width,
int height) {
Color oldColor = g.getColor();
paintSelectedBorder(g, x, y, width, height);
paintNormalBorders(g, x, y, width, height);
paintDottedBorders(g, x, y, width, height);
paintDashedBorders(g, x, y, width, height);
paintDoubleBorders(g, x, y, width, height);
paintDashDotDotBorders(g, x, y, width, height);
paintSelectedBorder(g, x, y, width, height);
paintNormalBorders(g, x, y, width, height);
paintDottedBorders(g, x, y, width, height);
paintDashedBorders(g, x, y, width, height);
paintDoubleBorders(g, x, y, width, height);
paintDashDotDotBorders(g, x, y, width, height);
g.setColor(oldColor);
}
g.setColor(oldColor);
}
/**
* Called by paintBorder to paint the border of a selected cell.
* The paramaters are the Graphics object, location and dimensions of the
* cell.
*/
private void paintSelectedBorder(Graphics g, int x, int y, int width,
int height) {
if (selected) {
//Need to setup thickness of 2
g.setColor(Color.black);
//paint the border
g.drawRect(x,y,width-1,height-1);
/**
* Called by paintBorder to paint the border of a selected cell.
* The paramaters are the Graphics object, location and dimensions of the
* cell.
*/
private void paintSelectedBorder(Graphics g, int x, int y, int width,
int height) {
if (selected) {
//Need to setup thickness of 2
g.setColor(Color.black);
//paint the border
g.drawRect(x, y, width - 1, height - 1);
//paint the filled rectangle at the bottom left hand position
g.fillRect(x+width-5, y+height-5, 5, 5);
}
}
/**
* Called by paintBorder to paint the various versions of normal line
* borders for a cell.
*/
private void paintNormalBorders(Graphics g, int x, int y, int width,
int height) {
if (northBorder &&
((northBorderType == BorderStyle.THIN) ||
(northBorderType == BorderStyle.MEDIUM) ||
(northBorderType == BorderStyle.THICK)
)
) {
int thickness = getThickness(northBorderType);
g.setColor(northColor);
for (int k=0; k < thickness; k++) {
g.drawLine(x,y+k,width,y+k);
//paint the filled rectangle at the bottom left hand position
g.fillRect(x + width - 5, y + height - 5, 5, 5);
}
}
}
if (eastBorder &&
((eastBorderType == BorderStyle.THIN) ||
(eastBorderType == BorderStyle.MEDIUM) ||
(eastBorderType == BorderStyle.THICK)
)
) {
int thickness = getThickness(eastBorderType);
/**
* Called by paintBorder to paint the various versions of normal line
* borders for a cell.
*/
private void paintNormalBorders(Graphics g, int x, int y, int width,
int height) {
g.setColor(eastColor);
if (northBorder &&
((northBorderType == BorderStyle.THIN) ||
(northBorderType == BorderStyle.MEDIUM) ||
(northBorderType == BorderStyle.THICK)
)
) {
for (int k=0; k < thickness; k++) {
g.drawLine(width-k,y,width-k,height);
int thickness = getThickness(northBorderType);
g.setColor(northColor);
for (int k = 0; k < thickness; k++) {
g.drawLine(x, y + k, width, y + k);
}
}
}
if (southBorder &&
((southBorderType == BorderStyle.THIN) ||
(southBorderType == BorderStyle.MEDIUM) ||
(southBorderType == BorderStyle.THICK)
)
) {
if (eastBorder &&
((eastBorderType == BorderStyle.THIN) ||
(eastBorderType == BorderStyle.MEDIUM) ||
(eastBorderType == BorderStyle.THICK)
)
) {
int thickness = getThickness(southBorderType);
int thickness = getThickness(eastBorderType);
g.setColor(southColor);
for (int k=0; k < thickness; k++) {
g.drawLine(x,height - k,width,height - k);
g.setColor(eastColor);
for (int k = 0; k < thickness; k++) {
g.drawLine(width - k, y, width - k, height);
}
}
}
if (westBorder &&
((westBorderType == BorderStyle.THIN) ||
(westBorderType == BorderStyle.MEDIUM) ||
(westBorderType == BorderStyle.THICK)
)
) {
if (southBorder &&
((southBorderType == BorderStyle.THIN) ||
(southBorderType == BorderStyle.MEDIUM) ||
(southBorderType == BorderStyle.THICK)
)
) {
int thickness = getThickness(westBorderType);
int thickness = getThickness(southBorderType);
g.setColor(westColor);
for (int k=0; k < thickness; k++) {
g.drawLine(x+k,y,x+k,height);
g.setColor(southColor);
for (int k = 0; k < thickness; k++) {
g.drawLine(x, height - k, width, height - k);
}
}
}
}
/**
* Called by paintBorder to paint the dotted line
* borders for a cell.
*/
private void paintDottedBorders(Graphics g, int x, int y, int width,
int height) {
if (northBorder &&
northBorderType == BorderStyle.DOTTED) {
int thickness = getThickness(northBorderType);
if (westBorder &&
((westBorderType == BorderStyle.THIN) ||
(westBorderType == BorderStyle.MEDIUM) ||
(westBorderType == BorderStyle.THICK)
)
) {
g.setColor(northColor);
int thickness = getThickness(westBorderType);
for (int k=0; k < thickness; k++) {
for (int xc = x; xc < width; xc=xc+2) {
g.drawLine(xc,y+k,xc,y+k);
}
g.setColor(westColor);
for (int k = 0; k < thickness; k++) {
g.drawLine(x + k, y, x + k, height);
}
}
}
}
if (eastBorder &&
eastBorderType == BorderStyle.DOTTED
) {
/**
* Called by paintBorder to paint the dotted line
* borders for a cell.
*/
private void paintDottedBorders(Graphics g, int x, int y, int width,
int height) {
if (northBorder &&
northBorderType == BorderStyle.DOTTED) {
int thickness = getThickness(northBorderType);
int thickness = getThickness(eastBorderType);
thickness++; //need for dotted borders to show up east
g.setColor(northColor);
g.setColor(eastColor);
for (int k=0; k < thickness; k++) {
for (int yc=y;yc < height; yc=yc+2) {
g.drawLine(width-k,yc,width-k,yc);
}
for (int k = 0; k < thickness; k++) {
for (int xc = x; xc < width; xc = xc + 2) {
g.drawLine(xc, y + k, xc, y + k);
}
}
}
}
if (southBorder &&
southBorderType == BorderStyle.DOTTED
) {
if (eastBorder &&
eastBorderType == BorderStyle.DOTTED
) {
int thickness = getThickness(southBorderType);
thickness++;
g.setColor(southColor);
for (int k=0; k < thickness; k++) {
for (int xc = x; xc < width; xc=xc+2) {
g.drawLine(xc,height-k,xc,height-k);
}
int thickness = getThickness(eastBorderType);
thickness++; //need for dotted borders to show up east
g.setColor(eastColor);
for (int k = 0; k < thickness; k++) {
for (int yc = y; yc < height; yc = yc + 2) {
g.drawLine(width - k, yc, width - k, yc);
}
}
}
}
if (westBorder &&
westBorderType == BorderStyle.DOTTED
) {
if (southBorder &&
southBorderType == BorderStyle.DOTTED
) {
int thickness = getThickness(westBorderType);
int thickness = getThickness(southBorderType);
thickness++;
g.setColor(southColor);
for (int k = 0; k < thickness; k++) {
for (int xc = x; xc < width; xc = xc + 2) {
g.drawLine(xc, height - k, xc, height - k);
}
}
}
if (westBorder &&
westBorderType == BorderStyle.DOTTED
) {
int thickness = getThickness(westBorderType);
// thickness++;
g.setColor(westColor);
g.setColor(westColor);
for (int k=0; k < thickness; k++) {
for (int yc=y;yc < height; yc=yc+2) {
g.drawLine(x+k,yc,x+k,yc);
}
for (int k = 0; k < thickness; k++) {
for (int yc = y; yc < height; yc = yc + 2) {
g.drawLine(x + k, yc, x + k, yc);
}
}
}
}
}
}
/**
* Called by paintBorder to paint the various versions of dotted line
* borders for a cell.
*/
private void paintDashedBorders(Graphics g, int x, int y, int width,
int height) {
if (northBorder &&
((northBorderType == BorderStyle.DASHED) ||
(northBorderType == BorderStyle.HAIR))
) {
int thickness = getThickness(northBorderType);
/**
* Called by paintBorder to paint the various versions of dotted line
* borders for a cell.
*/
private void paintDashedBorders(Graphics g, int x, int y, int width,
int height) {
if (northBorder &&
((northBorderType == BorderStyle.DASHED) ||
(northBorderType == BorderStyle.HAIR))
) {
int thickness = getThickness(northBorderType);
int dashlength = 1;
int dashlength = 1;
if (northBorderType == BorderStyle.DASHED)
dashlength = 2;
if (northBorderType == BorderStyle.DASHED)
dashlength = 2;
g.setColor(northColor);
g.setColor(northColor);
for (int k=0; k < thickness; k++) {
for (int xc = x; xc < width; xc=xc+5) {
g.drawLine(xc,y+k,xc+dashlength,y+k);
}
for (int k = 0; k < thickness; k++) {
for (int xc = x; xc < width; xc = xc + 5) {
g.drawLine(xc, y + k, xc + dashlength, y + k);
}
}
}
}
if (eastBorder &&
((eastBorderType == BorderStyle.DASHED) ||
(eastBorderType == BorderStyle.HAIR))
) {
if (eastBorder &&
((eastBorderType == BorderStyle.DASHED) ||
(eastBorderType == BorderStyle.HAIR))
) {
int thickness = getThickness(eastBorderType);
thickness++; //need for dotted borders to show up east
int thickness = getThickness(eastBorderType);
thickness++; //need for dotted borders to show up east
int dashlength = 1;
int dashlength = 1;
if (eastBorderType == BorderStyle.DASHED)
dashlength = 2;
if (eastBorderType == BorderStyle.DASHED)
dashlength = 2;
g.setColor(eastColor);
g.setColor(eastColor);
for (int k=0; k < thickness; k++) {
for (int yc=y;yc < height; yc=yc+5) {
g.drawLine(width-k,yc,width-k,yc+dashlength);
}
for (int k = 0; k < thickness; k++) {
for (int yc = y; yc < height; yc = yc + 5) {
g.drawLine(width - k, yc, width - k, yc + dashlength);
}
}
}
}
if (southBorder &&
((southBorderType == BorderStyle.DASHED) ||
(southBorderType == BorderStyle.HAIR))
) {
if (southBorder &&
((southBorderType == BorderStyle.DASHED) ||
(southBorderType == BorderStyle.HAIR))
) {
int thickness = getThickness(southBorderType);
thickness++;
int thickness = getThickness(southBorderType);
thickness++;
int dashlength = 1;
int dashlength = 1;
if (southBorderType == BorderStyle.DASHED)
dashlength = 2;
if (southBorderType == BorderStyle.DASHED)
dashlength = 2;
g.setColor(southColor);
for (int k=0; k < thickness; k++) {
for (int xc = x; xc < width; xc=xc+5) {
g.drawLine(xc,height-k,xc+dashlength,height-k);
}
g.setColor(southColor);
for (int k = 0; k < thickness; k++) {
for (int xc = x; xc < width; xc = xc + 5) {
g.drawLine(xc, height - k, xc + dashlength, height - k);
}
}
}
}
if (westBorder &&
((westBorderType == BorderStyle.DASHED) ||
(westBorderType == BorderStyle.HAIR))
) {
if (westBorder &&
((westBorderType == BorderStyle.DASHED) ||
(westBorderType == BorderStyle.HAIR))
) {
int thickness = getThickness(westBorderType);
int thickness = getThickness(westBorderType);
// thickness++;
int dashlength = 1;
int dashlength = 1;
if (westBorderType == BorderStyle.DASHED)
dashlength = 2;
if (westBorderType == BorderStyle.DASHED)
dashlength = 2;
g.setColor(westColor);
g.setColor(westColor);
for (int k=0; k < thickness; k++) {
for (int yc=y;yc < height; yc=yc+5) {
g.drawLine(x+k,yc,x+k,yc+dashlength);
}
for (int k = 0; k < thickness; k++) {
for (int yc = y; yc < height; yc = yc + 5) {
g.drawLine(x + k, yc, x + k, yc + dashlength);
}
}
}
}
}
}
/**
* Called by paintBorder to paint the double line
* borders for a cell.
*/
private void paintDoubleBorders(Graphics g, int x, int y, int width,
int height) {
if (northBorder &&
northBorderType == BorderStyle.DOUBLE) {
/**
* Called by paintBorder to paint the double line
* borders for a cell.
*/
private void paintDoubleBorders(Graphics g, int x, int y, int width,
int height) {
if (northBorder &&
northBorderType == BorderStyle.DOUBLE) {
g.setColor(northColor);
g.setColor(northColor);
int leftx=x;
int rightx=width;
int leftx = x;
int rightx = width;
// if there are borders on the west or east then
// the second line shouldn't cross them
if (westBorder) {
leftx = x + 3;
// if there are borders on the west or east then
// the second line shouldn't cross them
if (westBorder) {
leftx = x + 3;
}
if (eastBorder) {
rightx = width - 3;
}
g.drawLine(x, y, width, y);
g.drawLine(leftx, y + 2, rightx, y + 2);
}
if (eastBorder) {
rightx = width - 3;
if (eastBorder &&
eastBorderType == BorderStyle.DOUBLE
) {
int thickness = getThickness(eastBorderType);
thickness++; //need for dotted borders to show up east
g.setColor(eastColor);
int topy = y;
int bottomy = height;
if (northBorder) {
topy = y + 3;
}
if (southBorder) {
bottomy = height - 3;
}
g.drawLine(width - 1, y, width - 1, height);
g.drawLine(width - 3, topy, width - 3, bottomy);
}
g.drawLine(x,y,width,y);
g.drawLine(leftx,y+2,rightx,y+2);
}
if (southBorder &&
southBorderType == BorderStyle.DOUBLE
) {
if (eastBorder &&
eastBorderType == BorderStyle.DOUBLE
) {
g.setColor(southColor);
int thickness = getThickness(eastBorderType);
thickness++; //need for dotted borders to show up east
int leftx = y;
int rightx = width;
g.setColor(eastColor);
if (westBorder)
leftx = x + 3;
int topy=y;
int bottomy=height;
if (eastBorder)
rightx = width - 3;
if (northBorder) {
topy = y + 3;
g.drawLine(x, height - 1, width, height - 1);
g.drawLine(leftx, height - 3, rightx, height - 3);
}
if (southBorder) {
bottomy = height - 3;
}
if (westBorder &&
westBorderType == BorderStyle.DOUBLE
) {
g.drawLine(width-1,y,width-1,height);
g.drawLine(width-3,topy,width-3,bottomy);
}
if (southBorder &&
southBorderType == BorderStyle.DOUBLE
) {
g.setColor(southColor);
int leftx=y;
int rightx=width;
if (westBorder)
leftx=x+3;
if (eastBorder)
rightx=width-3;
g.drawLine(x,height - 1,width,height - 1);
g.drawLine(leftx,height - 3,rightx,height - 3);
}
if (westBorder &&
westBorderType == BorderStyle.DOUBLE
) {
int thickness = getThickness(westBorderType);
int thickness = getThickness(westBorderType);
// thickness++;
g.setColor(westColor);
g.setColor(westColor);
int topy=y;
int bottomy=height-3;
int topy = y;
int bottomy = height - 3;
if (northBorder)
topy=y+2;
if (northBorder)
topy = y + 2;
if (southBorder)
bottomy=height-3;
if (southBorder)
bottomy = height - 3;
g.drawLine(x,y,x,height);
g.drawLine(x+2,topy,x+2,bottomy);
}
}
g.drawLine(x, y, x, height);
g.drawLine(x + 2, topy, x + 2, bottomy);
}
}
/**
* Called by paintBorder to paint the various versions of dash dot dot line
* borders for a cell.
*/
private void paintDashDotDotBorders(Graphics g, int x, int y, int width,
int height) {
if (northBorder &&
((northBorderType == BorderStyle.DASH_DOT_DOT) ||
(northBorderType == BorderStyle.MEDIUM_DASH_DOT_DOT))
) {
int thickness = getThickness(northBorderType);
/**
* Called by paintBorder to paint the various versions of dash dot dot line
* borders for a cell.
*/
private void paintDashDotDotBorders(Graphics g, int x, int y, int width,
int height) {
if (northBorder &&
((northBorderType == BorderStyle.DASH_DOT_DOT) ||
(northBorderType == BorderStyle.MEDIUM_DASH_DOT_DOT))
) {
int thickness = getThickness(northBorderType);
g.setColor(northColor);
for (int l = x; l < width; ) {
l = l + drawDashDotDot(g, l, y, thickness, true, true);
}
g.setColor(northColor);
for (int l=x; l < width;) {
l=l+drawDashDotDot(g, l, y, thickness, true, true);
}
}
if (eastBorder &&
((eastBorderType == BorderStyle.DASH_DOT_DOT) ||
(eastBorderType == BorderStyle.MEDIUM_DASH_DOT_DOT))
) {
if (eastBorder &&
((eastBorderType == BorderStyle.DASH_DOT_DOT) ||
(eastBorderType == BorderStyle.MEDIUM_DASH_DOT_DOT))
) {
int thickness = getThickness(eastBorderType);
int thickness = getThickness(eastBorderType);
g.setColor(eastColor);
g.setColor(eastColor);
for (int l=y;l < height;) {
//System.err.println("drawing east");
l=l+drawDashDotDot(g,width-1,l,thickness,false,false);
}
}
if (southBorder &&
((southBorderType == BorderStyle.DASH_DOT_DOT) ||
(southBorderType == BorderStyle.MEDIUM_DASH_DOT_DOT))
) {
int thickness = getThickness(southBorderType);
g.setColor(southColor);
for (int l=x; l < width;) {
//System.err.println("drawing south");
l=l+drawDashDotDot(g, l, height-1, thickness, true, false);
}
}
if (westBorder &&
((westBorderType == BorderStyle.DASH_DOT_DOT) ||
(westBorderType == BorderStyle.MEDIUM_DASH_DOT_DOT))
) {
int thickness = getThickness(westBorderType);
g.setColor(westColor);
for (int l=y;l < height;) {
//System.err.println("drawing west");
l=l+drawDashDotDot(g,x,l,thickness,false,true);
for (int l = y; l < height; ) {
//System.err.println("drawing east");
l = l + drawDashDotDot(g, width - 1, l, thickness, false, false);
}
}
}
}
if (southBorder &&
((southBorderType == BorderStyle.DASH_DOT_DOT) ||
(southBorderType == BorderStyle.MEDIUM_DASH_DOT_DOT))
) {
/**
* Draws one dash dot dot horizontally or vertically with thickness drawn
* incrementally to either the right or left.
*
* @param g graphics object for drawing with
* @param x the x origin of the line
* @param y the y origin of the line
* @param thickness the thickness of the line
* @param horizontal or vertical (true for horizontal)
* @param rightBottom or left/top thickness (true for right or top),
* if true then the x or y origin will be incremented to provide
* thickness, if false, they'll be decremented. For vertical
* borders, x is incremented or decremented, for horizontal its y.
* Just set to true for north and west, and false for east and
* south.
* @return length - returns the length of the line.
*/
private int drawDashDotDot(Graphics g,int x, int y, int thickness,
boolean horizontal,
boolean rightBottom) {
int thickness = getThickness(southBorderType);
for (int t=0; t < thickness; t++) {
if (!rightBottom) {
t = 0 - t; //add negative thickness so we go the other way
//then we'll decrement instead of increment.
}
if (horizontal) {
g.drawLine(x,y+t,x+5,y+t);
g.drawLine(x+8,y+t,x+10,y+t);
g.drawLine(x+13,y+t,x+15,y+t);
} else {
g.drawLine(x+t,y,x+t,y+5);
g.drawLine(x+t,y+8,x+t,y+10);
g.drawLine(x+t,y+13,x+t,y+15);
}
}
return 18;
}
g.setColor(southColor);
/**
* @return the line thickness for a border based on border type
*/
private int getThickness(BorderStyle thickness) {
switch (thickness) {
case DASH_DOT_DOT:
case DASHED:
case HAIR:
return 1;
case THIN:
return 2;
case MEDIUM:
case MEDIUM_DASH_DOT_DOT:
return 3;
case THICK:
return 4;
default:
return 1;
}
}
for (int l = x; l < width; ) {
//System.err.println("drawing south");
l = l + drawDashDotDot(g, l, height - 1, thickness, true, false);
}
}
if (westBorder &&
((westBorderType == BorderStyle.DASH_DOT_DOT) ||
(westBorderType == BorderStyle.MEDIUM_DASH_DOT_DOT))
) {
int thickness = getThickness(westBorderType);
g.setColor(westColor);
for (int l = y; l < height; ) {
//System.err.println("drawing west");
l = l + drawDashDotDot(g, x, l, thickness, false, true);
}
}
}
/**
* Draws one dash dot dot horizontally or vertically with thickness drawn
* incrementally to either the right or left.
*
* @param g graphics object for drawing with
* @param x the x origin of the line
* @param y the y origin of the line
* @param thickness the thickness of the line
* @param horizontal or vertical (true for horizontal)
* @param rightBottom or left/top thickness (true for right or top),
* if true then the x or y origin will be incremented to provide
* thickness, if false, they'll be decremented. For vertical
* borders, x is incremented or decremented, for horizontal its y.
* Just set to true for north and west, and false for east and
* south.
* @return length - returns the length of the line.
*/
private int drawDashDotDot(Graphics g, int x, int y, int thickness,
boolean horizontal,
boolean rightBottom) {
for (int t = 0; t < thickness; t++) {
if (!rightBottom) {
t = 0 - t; //add negative thickness so we go the other way
//then we'll decrement instead of increment.
}
if (horizontal) {
g.drawLine(x, y + t, x + 5, y + t);
g.drawLine(x + 8, y + t, x + 10, y + t);
g.drawLine(x + 13, y + t, x + 15, y + t);
} else {
g.drawLine(x + t, y, x + t, y + 5);
g.drawLine(x + t, y + 8, x + t, y + 10);
g.drawLine(x + t, y + 13, x + t, y + 15);
}
}
return 18;
}
/**
* @return the line thickness for a border based on border type
*/
private int getThickness(BorderStyle thickness) {
switch (thickness) {
case DASH_DOT_DOT:
case DASHED:
case HAIR:
return 1;
case THIN:
return 2;
case MEDIUM:
case MEDIUM_DASH_DOT_DOT:
return 3;
case THICK:
return 4;
default:
return 1;
}
}
}

View File

@ -19,206 +19,211 @@
package org.apache.poi.hssf.view;
import java.text.*;
import java.text.FieldPosition;
import java.text.Format;
import java.text.ParseException;
import java.text.ParsePosition;
/**
* This class is used to format cells into their fractional format.
*
* <p>
* I cant be 100% sure that the same fractional value will be displayed as in
* excel but then again it is a lossy formating mode anyway
*
* @author Jason Height
* @since 15 July 2002
* @author Jason Height
* @since 15 July 2002
*/
public class SVFractionalFormat extends Format {
private short ONE_DIGIT = 1;
private short TWO_DIGIT = 2;
private short THREE_DIGIT = 3;
private short UNITS = 4;
private int units = 1;
private short mode = -1;
private short ONE_DIGIT = 1;
private short TWO_DIGIT = 2;
private short THREE_DIGIT = 3;
private short UNITS = 4;
private int units = 1;
private short mode = -1;
/** Constructs a new FractionalFormatter
*
* The formatStr defines how the number will be formatted
* # ?/? Up to one digit
* # ??/?? Up to two digits
* # ???/??? Up to three digits
* # ?/2 In halves
* # ?/4 In quarters
* # ?/8 In eighths
* # ?/16 In sixteenths
* # ?/10 In tenths
* # ?/100 In hundredths
*/
public SVFractionalFormat(String formatStr) {
if ("# ?/?".equals(formatStr))
mode = ONE_DIGIT;
else if ("# ??/??".equals(formatStr))
mode = TWO_DIGIT;
else if ("# ???/???".equals(formatStr))
mode = THREE_DIGIT;
else if ("# ?/2".equals(formatStr)) {
mode = UNITS;
units = 2;
} else if ("# ?/4".equals(formatStr)) {
mode = UNITS;
units = 4;
} else if ("# ?/8".equals(formatStr)) {
mode = UNITS;
units = 8;
} else if ("# ?/16".equals(formatStr)) {
mode = UNITS;
units = 16;
} else if ("# ?/10".equals(formatStr)) {
mode = UNITS;
units = 10;
} else if ("# ?/100".equals(formatStr)) {
mode = UNITS;
units = 100;
}
}
/**
* Returns a fractional string representation of a double to a maximum denominator size
*
* This code has been translated to java from the following web page.
* http://www.codeproject.com/cpp/fraction.asp
* Originally coded in c++ By Dean Wyant dwyant@mindspring.com
* The code on the web page is freely available.
*
* @param f Description of the Parameter
* @param MaxDen Description of the Parameter
* @return Description of the Return Value
*/
private String format(final double f, final int MaxDen) {
long Whole = (long)f;
int sign = 1;
if (f < 0) {
sign = -1;
}
double Precision = 0.00001;
double AllowedError = Precision;
double d = Math.abs(f);
d -= Whole;
double Frac = d;
double Diff = Frac;
long Num = 1;
long Den = 0;
long A = 0;
long B = 0;
long i = 0;
if (Frac > Precision) {
while (true) {
d = 1.0 / d;
i = (long) (d + Precision);
d -= i;
if (A > 0) {
Num = i * Num + B;
/**
* Constructs a new FractionalFormatter
* <p>
* The formatStr defines how the number will be formatted
* # ?/? Up to one digit
* # ??/?? Up to two digits
* # ???/??? Up to three digits
* # ?/2 In halves
* # ?/4 In quarters
* # ?/8 In eighths
* # ?/16 In sixteenths
* # ?/10 In tenths
* # ?/100 In hundredths
*/
public SVFractionalFormat(String formatStr) {
if ("# ?/?".equals(formatStr))
mode = ONE_DIGIT;
else if ("# ??/??".equals(formatStr))
mode = TWO_DIGIT;
else if ("# ???/???".equals(formatStr))
mode = THREE_DIGIT;
else if ("# ?/2".equals(formatStr)) {
mode = UNITS;
units = 2;
} else if ("# ?/4".equals(formatStr)) {
mode = UNITS;
units = 4;
} else if ("# ?/8".equals(formatStr)) {
mode = UNITS;
units = 8;
} else if ("# ?/16".equals(formatStr)) {
mode = UNITS;
units = 16;
} else if ("# ?/10".equals(formatStr)) {
mode = UNITS;
units = 10;
} else if ("# ?/100".equals(formatStr)) {
mode = UNITS;
units = 100;
}
Den = (long) (Num / Frac + 0.5);
Diff = Math.abs((double) Num / Den - Frac);
if (Den > MaxDen) {
if (A > 0) {
Num = A;
Den = (long) (Num / Frac + 0.5);
Diff = Math.abs((double) Num / Den - Frac);
} else {
Den = MaxDen;
Num = 1;
Diff = Math.abs((double) Num / Den - Frac);
if (Diff > Frac) {
Num = 0;
Den = 1;
// Keeps final check below from adding 1 and keeps Den from being 0
Diff = Frac;
}
/**
* Returns a fractional string representation of a double to a maximum denominator size
* <p>
* This code has been translated to java from the following web page.
* http://www.codeproject.com/cpp/fraction.asp
* Originally coded in c++ By Dean Wyant dwyant@mindspring.com
* The code on the web page is freely available.
*
* @param f Description of the Parameter
* @param MaxDen Description of the Parameter
* @return Description of the Return Value
*/
private String format(final double f, final int MaxDen) {
long Whole = (long) f;
int sign = 1;
if (f < 0) {
sign = -1;
}
double Precision = 0.00001;
double AllowedError = Precision;
double d = Math.abs(f);
d -= Whole;
double Frac = d;
double Diff = Frac;
long Num = 1;
long Den = 0;
long A = 0;
long B = 0;
long i = 0;
if (Frac > Precision) {
while (true) {
d = 1.0 / d;
i = (long) (d + Precision);
d -= i;
if (A > 0) {
Num = i * Num + B;
}
Den = (long) (Num / Frac + 0.5);
Diff = Math.abs((double) Num / Den - Frac);
if (Den > MaxDen) {
if (A > 0) {
Num = A;
Den = (long) (Num / Frac + 0.5);
Diff = Math.abs((double) Num / Den - Frac);
} else {
Den = MaxDen;
Num = 1;
Diff = Math.abs((double) Num / Den - Frac);
if (Diff > Frac) {
Num = 0;
Den = 1;
// Keeps final check below from adding 1 and keeps Den from being 0
Diff = Frac;
}
}
break;
}
if ((Diff <= AllowedError) || (d < Precision)) {
break;
}
Precision = AllowedError / Diff;
// This calculation of Precision does not always provide results within
// Allowed Error. It compensates for loss of significant digits that occurs.
// It helps to round the imprecise reciprocal values to i.
B = A;
A = Num;
}
}
break;
}
if ((Diff <= AllowedError) || (d < Precision)) {
break;
if (Num == Den) {
Whole++;
Num = 0;
Den = 0;
} else if (Den == 0) {
Num = 0;
}
Precision = AllowedError / Diff;
// This calculation of Precision does not always provide results within
// Allowed Error. It compensates for loss of significant digits that occurs.
// It helps to round the imprecise reciprocal values to i.
B = A;
A = Num;
}
if (sign < 0) {
if (Whole == 0) {
Num = -Num;
} else {
Whole = -Whole;
}
}
return new StringBuilder().append(Whole).append(" ").append(Num).append("/").append(Den).toString();
}
if (Num == Den) {
Whole++;
Num = 0;
Den = 0;
} else if (Den == 0) {
Num = 0;
/**
* This method formats the double in the units specified.
* The usints could be any number but in this current implementation it is
* halves (2), quaters (4), eigths (8) etc
*/
private String formatUnit(double f, int units) {
long Whole = (long) f;
f -= Whole;
long Num = Math.round(f * units);
return new StringBuilder().append(Whole).append(" ").append(Num).append("/").append(units).toString();
}
if (sign < 0) {
if (Whole == 0) {
Num = -Num;
} else {
Whole = -Whole;
}
public final String format(double val) {
if (mode == ONE_DIGIT) {
return format(val, 9);
} else if (mode == TWO_DIGIT) {
return format(val, 99);
} else if (mode == THREE_DIGIT) {
return format(val, 999);
} else if (mode == UNITS) {
return formatUnit(val, units);
}
throw new RuntimeException("Unexpected Case");
}
return new StringBuilder().append(Whole).append(" ").append(Num).append("/").append(Den).toString();
}
/** This method formats the double in the units specified.
* The usints could be any number but in this current implementation it is
* halves (2), quaters (4), eigths (8) etc
*/
private String formatUnit(double f, int units) {
long Whole = (long)f;
f -= Whole;
long Num = Math.round(f * units);
return new StringBuilder().append(Whole).append(" ").append(Num).append("/").append(units).toString();
}
public final String format(double val) {
if (mode == ONE_DIGIT) {
return format(val, 9);
} else if (mode == TWO_DIGIT) {
return format(val, 99);
} else if (mode == THREE_DIGIT) {
return format(val, 999);
} else if (mode == UNITS) {
return formatUnit(val , units);
@Override
public StringBuffer format(Object obj,
StringBuffer toAppendTo,
FieldPosition pos) {
if (obj instanceof Number) {
toAppendTo.append(format(((Number) obj).doubleValue()));
return toAppendTo;
}
throw new IllegalArgumentException("Can only handle Numbers");
}
throw new RuntimeException("Unexpected Case");
}
@Override
public StringBuffer format(Object obj,
StringBuffer toAppendTo,
FieldPosition pos) {
if (obj instanceof Number) {
toAppendTo.append(format(((Number)obj).doubleValue()));
return toAppendTo;
@Override
public Object parseObject(String source,
ParsePosition status) {
//JMH TBD
return null;
}
throw new IllegalArgumentException("Can only handle Numbers");
}
@Override
public Object parseObject(String source,
ParsePosition status) {
//JMH TBD
return null;
}
@Override
public Object parseObject(String source)
throws ParseException {
//JMH TBD
return null;
}
@Override
public Object parseObject(String source)
throws ParseException {
//JMH TBD
return null;
}
@Override
public Object clone() {
//JMH TBD
return null;
}
@Override
public Object clone() {
//JMH TBD
return null;
}
}

View File

@ -15,85 +15,95 @@
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.view;
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;
import java.awt.Component;
import java.awt.Dimension;
import org.apache.poi.hssf.usermodel.*;
import javax.swing.AbstractListModel;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JTable;
import javax.swing.ListCellRenderer;
import javax.swing.ListModel;
import javax.swing.UIManager;
import javax.swing.table.JTableHeader;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
/**
* This class presents the row header to the table.
*
*
* @author Jason Height
*/
public class SVRowHeader extends JList<Object> {
/** This model simply returns an integer number up to the number of rows
* that are present in the sheet.
*
*/
private class SVRowHeaderModel extends AbstractListModel<Object> {
private HSSFSheet sheet;
/**
* This model simply returns an integer number up to the number of rows
* that are present in the sheet.
*/
private class SVRowHeaderModel extends AbstractListModel<Object> {
private HSSFSheet sheet;
public SVRowHeaderModel(HSSFSheet sheet) {
this.sheet = sheet;
public SVRowHeaderModel(HSSFSheet sheet) {
this.sheet = sheet;
}
@Override
public int getSize() {
return sheet.getLastRowNum() + 1;
}
@Override
public Object getElementAt(int index) {
return Integer.toString(index + 1);
}
}
@Override
public int getSize() {
return sheet.getLastRowNum() + 1;
}
@Override
public Object getElementAt(int index) {
return Integer.toString(index+1);
}
}
/**
* Renderes the row number
*/
private class RowHeaderRenderer extends JLabel implements ListCellRenderer<Object> {
private HSSFSheet sheet;
private int extraHeight;
/** Renderes the row number*/
private class RowHeaderRenderer extends JLabel implements ListCellRenderer<Object> {
private HSSFSheet sheet;
private int extraHeight;
RowHeaderRenderer(HSSFSheet sheet, JTable table, int extraHeight) {
this.sheet = sheet;
this.extraHeight = extraHeight;
JTableHeader header = table.getTableHeader();
setOpaque(true);
setBorder(UIManager.getBorder("TableHeader.cellBorder"));
setHorizontalAlignment(CENTER);
setForeground(header.getForeground());
setBackground(header.getBackground());
setFont(header.getFont());
}
RowHeaderRenderer(HSSFSheet sheet, JTable table, int extraHeight) {
this.sheet = sheet;
this.extraHeight = extraHeight;
JTableHeader header = table.getTableHeader();
setOpaque(true);
setBorder(UIManager.getBorder("TableHeader.cellBorder"));
setHorizontalAlignment(CENTER);
setForeground(header.getForeground());
setBackground(header.getBackground());
setFont(header.getFont());
@Override
public Component getListCellRendererComponent(JList list,
Object value, int index, boolean isSelected, boolean cellHasFocus) {
Dimension d = getPreferredSize();
HSSFRow row = sheet.getRow(index);
int rowHeight;
if (row == null) {
rowHeight = (int) sheet.getDefaultRowHeightInPoints();
} else {
rowHeight = (int) row.getHeightInPoints();
}
d.height = rowHeight + extraHeight;
setPreferredSize(d);
setText((value == null) ? "" : value.toString());
return this;
}
}
@Override
public Component getListCellRendererComponent( JList list,
Object value, int index, boolean isSelected, boolean cellHasFocus) {
Dimension d = getPreferredSize();
HSSFRow row = sheet.getRow(index);
int rowHeight;
if(row == null) {
rowHeight = (int)sheet.getDefaultRowHeightInPoints();
} else {
rowHeight = (int)row.getHeightInPoints();
}
d.height = rowHeight+extraHeight;
setPreferredSize(d);
setText((value == null) ? "" : value.toString());
return this;
public SVRowHeader(HSSFSheet sheet, JTable table, int extraHeight) {
ListModel<Object> lm = new SVRowHeaderModel(sheet);
this.setModel(lm);
setFixedCellWidth(50);
setCellRenderer(new RowHeaderRenderer(sheet, table, extraHeight));
}
}
public SVRowHeader(HSSFSheet sheet, JTable table, int extraHeight) {
ListModel<Object> lm = new SVRowHeaderModel(sheet);
this.setModel(lm);
setFixedCellWidth(50);
setCellRenderer(new RowHeaderRenderer(sheet, table, extraHeight));
}
}

View File

@ -54,208 +54,208 @@ import org.apache.poi.ss.usermodel.Row;
* @author Ken Arnold, Industrious Media LLC
*/
public class SVSheetTable extends JTable {
private final HSSFSheet sheet;
private final PendingPaintings pendingPaintings;
private FormulaDisplayListener formulaListener;
private JScrollPane scroll;
private final HSSFSheet sheet;
private final PendingPaintings pendingPaintings;
private FormulaDisplayListener formulaListener;
private JScrollPane scroll;
private static final Color HEADER_BACKGROUND = new Color(235, 235, 235);
private static final Color HEADER_BACKGROUND = new Color(235, 235, 235);
/**
* This field is the magic number to convert from a Character width to a java
* pixel width.
* <p>
* When the "normal" font size in a workbook changes, this effects all of the
* heights and widths. Unfortunately there is no way to retrieve this
* information, hence the MAGIC number.
* <p>
* This number may only work for the normal style font size of Arial size 10.
*/
private static final int magicCharFactor = 7;
/**
* This field is the magic number to convert from a Character width to a java
* pixel width.
* <p>
* When the "normal" font size in a workbook changes, this effects all of the
* heights and widths. Unfortunately there is no way to retrieve this
* information, hence the MAGIC number.
* <p>
* This number may only work for the normal style font size of Arial size 10.
*/
private static final int magicCharFactor = 7;
private class HeaderCell extends JLabel {
private final int row;
private class HeaderCell extends JLabel {
private final int row;
public HeaderCell(Object value, int row) {
super(value.toString(), CENTER);
this.row = row;
setBackground(HEADER_BACKGROUND);
setOpaque(true);
setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY));
setRowSelectionAllowed(false);
}
@Override
public Dimension getPreferredSize() {
Dimension d = super.getPreferredSize();
if (row >= 0) {
d.height = getRowHeight(row);
}
return d;
}
@Override
public Dimension getMaximumSize() {
Dimension d = super.getMaximumSize();
if (row >= 0) {
d.height = getRowHeight(row);
}
return d;
}
@Override
public Dimension getMinimumSize() {
Dimension d = super.getMinimumSize();
if (row >= 0) {
d.height = getRowHeight(row);
}
return d;
}
}
private class HeaderCellRenderer implements TableCellRenderer {
@Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
return new HeaderCell(value, row);
}
}
private class FormulaDisplayListener implements ListSelectionListener {
private final JTextComponent formulaDisplay;
public FormulaDisplayListener(JTextComponent formulaDisplay) {
this.formulaDisplay = formulaDisplay;
}
@Override
public void valueChanged(ListSelectionEvent e) {
int row = getSelectedRow();
int col = getSelectedColumn();
if (row < 0 || col < 0) {
return;
}
if (e.getValueIsAdjusting()) {
return;
}
HSSFCell cell = (HSSFCell) getValueAt(row, col);
String formula = "";
if (cell != null) {
if (cell.getCellType() == CellType.FORMULA) {
formula = cell.getCellFormula();
} else {
formula = cell.toString();
public HeaderCell(Object value, int row) {
super(value.toString(), CENTER);
this.row = row;
setBackground(HEADER_BACKGROUND);
setOpaque(true);
setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY));
setRowSelectionAllowed(false);
}
if (formula == null)
formula = "";
}
formulaDisplay.setText(formula);
}
}
public SVSheetTable(HSSFSheet sheet) {
super(new SVTableModel(sheet));
this.sheet = sheet;
setIntercellSpacing(new Dimension(0, 0));
setAutoResizeMode(AUTO_RESIZE_OFF);
JTableHeader header = getTableHeader();
header.setDefaultRenderer(new HeaderCellRenderer());
pendingPaintings = new PendingPaintings(this);
//Set the columns the correct size
TableColumnModel columns = getColumnModel();
for (int i = 0; i < columns.getColumnCount(); i++) {
TableColumn column = columns.getColumn(i);
int width = sheet.getColumnWidth(i);
//256 is because the width is in 256ths of a character
column.setPreferredWidth(width / 256 * magicCharFactor);
}
Toolkit t = getToolkit();
int res = t.getScreenResolution();
TableModel model = getModel();
for (int i = 0; i < model.getRowCount(); i++) {
Row row = sheet.getRow(i - sheet.getFirstRowNum());
if (row != null) {
short h = row.getHeight();
int height = Math.toIntExact(Math.round(Math.max(1., h / (res / 70. * 20.) + 3.)));
System.out.printf("%d: %d (%d @ %d)%n", i, height, h, res);
setRowHeight(i, height);
}
}
addHierarchyListener(new HierarchyListener() {
@Override
public void hierarchyChanged(HierarchyEvent e) {
if ((e.getChangeFlags() & HierarchyEvent.PARENT_CHANGED) != 0) {
Container changedParent = e.getChangedParent();
if (changedParent instanceof JViewport) {
Container grandparent = changedParent.getParent();
if (grandparent instanceof JScrollPane) {
JScrollPane jScrollPane = (JScrollPane) grandparent;
setupScroll(jScrollPane);
@Override
public Dimension getPreferredSize() {
Dimension d = super.getPreferredSize();
if (row >= 0) {
d.height = getRowHeight(row);
}
}
return d;
}
}
});
}
public void setupScroll(JScrollPane scroll) {
if (scroll == this.scroll)
return;
@Override
public Dimension getMaximumSize() {
Dimension d = super.getMaximumSize();
if (row >= 0) {
d.height = getRowHeight(row);
}
return d;
}
this.scroll = scroll;
if (scroll == null)
return;
SVRowHeader rowHeader = new SVRowHeader(sheet, this, 0);
scroll.setRowHeaderView(rowHeader);
scroll.setCorner(JScrollPane.UPPER_LEADING_CORNER, headerCell("?"));
}
public void setFormulaDisplay(JTextComponent formulaDisplay) {
ListSelectionModel rowSelMod = getSelectionModel();
ListSelectionModel colSelMod = getColumnModel().getSelectionModel();
if (formulaDisplay == null) {
rowSelMod.removeListSelectionListener(formulaListener);
colSelMod.removeListSelectionListener(formulaListener);
formulaListener = null;
@Override
public Dimension getMinimumSize() {
Dimension d = super.getMinimumSize();
if (row >= 0) {
d.height = getRowHeight(row);
}
return d;
}
}
if (formulaDisplay != null) {
formulaListener = new FormulaDisplayListener(formulaDisplay);
rowSelMod.addListSelectionListener(formulaListener);
colSelMod.addListSelectionListener(formulaListener);
private class HeaderCellRenderer implements TableCellRenderer {
@Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
return new HeaderCell(value, row);
}
}
}
public JTextComponent getFormulaDisplay() {
if (formulaListener == null)
return null;
else
return formulaListener.formulaDisplay;
}
private class FormulaDisplayListener implements ListSelectionListener {
private final JTextComponent formulaDisplay;
public Component headerCell(String text) {
return new HeaderCell(text, -1);
}
public FormulaDisplayListener(JTextComponent formulaDisplay) {
this.formulaDisplay = formulaDisplay;
}
@Override
public void paintComponent(Graphics g1) {
Graphics2D g = (Graphics2D) g1;
@Override
public void valueChanged(ListSelectionEvent e) {
int row = getSelectedRow();
int col = getSelectedColumn();
if (row < 0 || col < 0) {
return;
}
pendingPaintings.clear();
if (e.getValueIsAdjusting()) {
return;
}
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
super.paintComponent(g);
HSSFCell cell = (HSSFCell) getValueAt(row, col);
String formula = "";
if (cell != null) {
if (cell.getCellType() == CellType.FORMULA) {
formula = cell.getCellFormula();
} else {
formula = cell.toString();
}
if (formula == null)
formula = "";
}
formulaDisplay.setText(formula);
}
}
pendingPaintings.paint(g);
}
public SVSheetTable(HSSFSheet sheet) {
super(new SVTableModel(sheet));
this.sheet = sheet;
setIntercellSpacing(new Dimension(0, 0));
setAutoResizeMode(AUTO_RESIZE_OFF);
JTableHeader header = getTableHeader();
header.setDefaultRenderer(new HeaderCellRenderer());
pendingPaintings = new PendingPaintings(this);
//Set the columns the correct size
TableColumnModel columns = getColumnModel();
for (int i = 0; i < columns.getColumnCount(); i++) {
TableColumn column = columns.getColumn(i);
int width = sheet.getColumnWidth(i);
//256 is because the width is in 256ths of a character
column.setPreferredWidth(width / 256 * magicCharFactor);
}
Toolkit t = getToolkit();
int res = t.getScreenResolution();
TableModel model = getModel();
for (int i = 0; i < model.getRowCount(); i++) {
Row row = sheet.getRow(i - sheet.getFirstRowNum());
if (row != null) {
short h = row.getHeight();
int height = Math.toIntExact(Math.round(Math.max(1., h / (res / 70. * 20.) + 3.)));
System.out.printf("%d: %d (%d @ %d)%n", i, height, h, res);
setRowHeight(i, height);
}
}
addHierarchyListener(new HierarchyListener() {
@Override
public void hierarchyChanged(HierarchyEvent e) {
if ((e.getChangeFlags() & HierarchyEvent.PARENT_CHANGED) != 0) {
Container changedParent = e.getChangedParent();
if (changedParent instanceof JViewport) {
Container grandparent = changedParent.getParent();
if (grandparent instanceof JScrollPane) {
JScrollPane jScrollPane = (JScrollPane) grandparent;
setupScroll(jScrollPane);
}
}
}
}
});
}
public void setupScroll(JScrollPane scroll) {
if (scroll == this.scroll)
return;
this.scroll = scroll;
if (scroll == null)
return;
SVRowHeader rowHeader = new SVRowHeader(sheet, this, 0);
scroll.setRowHeaderView(rowHeader);
scroll.setCorner(JScrollPane.UPPER_LEADING_CORNER, headerCell("?"));
}
public void setFormulaDisplay(JTextComponent formulaDisplay) {
ListSelectionModel rowSelMod = getSelectionModel();
ListSelectionModel colSelMod = getColumnModel().getSelectionModel();
if (formulaDisplay == null) {
rowSelMod.removeListSelectionListener(formulaListener);
colSelMod.removeListSelectionListener(formulaListener);
formulaListener = null;
}
if (formulaDisplay != null) {
formulaListener = new FormulaDisplayListener(formulaDisplay);
rowSelMod.addListSelectionListener(formulaListener);
colSelMod.addListSelectionListener(formulaListener);
}
}
public JTextComponent getFormulaDisplay() {
if (formulaListener == null)
return null;
else
return formulaListener.formulaDisplay;
}
public Component headerCell(String text) {
return new HeaderCell(text, -1);
}
@Override
public void paintComponent(Graphics g1) {
Graphics2D g = (Graphics2D) g1;
pendingPaintings.clear();
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
super.paintComponent(g);
pendingPaintings.paint(g);
}
}

View File

@ -15,7 +15,7 @@
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.view;
@ -50,234 +50,237 @@ import org.apache.poi.ss.usermodel.FillPatternType;
* @author Andrew C. Oliver
*/
public class SVTableCellRenderer extends JLabel
implements TableCellRenderer, Serializable
{
implements TableCellRenderer, Serializable {
protected static final Border noFocusBorder = new EmptyBorder(1, 1, 1, 1);
protected SVBorder cellBorder = new SVBorder();
private HSSFWorkbook wb;
/** This class holds the references to the predefined cell formats.
/**
* This class holds the references to the predefined cell formats.
*/
private class CellFormatter {
private Format[] textFormatter;
private Format[] textFormatter;
private DecimalFormat generalNumberFormat = new DecimalFormat("0");
private DecimalFormat generalNumberFormat = new DecimalFormat("0");
public CellFormatter() {
textFormatter = new Format[0x31];
public CellFormatter() {
textFormatter = new Format[0x31];
textFormatter[0x01] = new DecimalFormat("0");
textFormatter[0x02] = new DecimalFormat("0.00");
textFormatter[0x03] = new DecimalFormat("#,##0");
textFormatter[0x04] = new DecimalFormat("#,##0.00");
textFormatter[0x05] = new DecimalFormat("$#,##0;$#,##0");
textFormatter[0x06] = new DecimalFormat("$#,##0;$#,##0");
textFormatter[0x07] = new DecimalFormat("$#,##0.00;$#,##0.00");
textFormatter[0x08] = new DecimalFormat("$#,##0.00;$#,##0.00");
textFormatter[0x09] = new DecimalFormat("0%");
textFormatter[0x0A] = new DecimalFormat("0.00%");
textFormatter[0x0B] = new DecimalFormat("0.00E0");
textFormatter[0x0C] = new SVFractionalFormat("# ?/?");
textFormatter[0x0D] = new SVFractionalFormat("# ??/??");
textFormatter[0x0E] = new SimpleDateFormat("M/d/yy");
textFormatter[0x0F] = new SimpleDateFormat("d-MMM-yy");
textFormatter[0x10] = new SimpleDateFormat("d-MMM");
textFormatter[0x11] = new SimpleDateFormat("MMM-yy");
textFormatter[0x12] = new SimpleDateFormat("h:mm a");
textFormatter[0x13] = new SimpleDateFormat("h:mm:ss a");
textFormatter[0x14] = new SimpleDateFormat("h:mm");
textFormatter[0x15] = new SimpleDateFormat("h:mm:ss");
textFormatter[0x16] = new SimpleDateFormat("M/d/yy h:mm");
// 0x17 - 0x24 reserved for international and undocumented 0x25, "(#,##0_);(#,##0)"
//start at 0x26
//jmh need to do colour
//"(#,##0_);[Red](#,##0)"
textFormatter[0x26] = new DecimalFormat("#,##0;#,##0");
//jmh need to do colour
//(#,##0.00_);(#,##0.00)
textFormatter[0x27] = new DecimalFormat("#,##0.00;#,##0.00");
textFormatter[0x28] = new DecimalFormat("#,##0.00;#,##0.00");
textFormatter[0x01] = new DecimalFormat("0");
textFormatter[0x02] = new DecimalFormat("0.00");
textFormatter[0x03] = new DecimalFormat("#,##0");
textFormatter[0x04] = new DecimalFormat("#,##0.00");
textFormatter[0x05] = new DecimalFormat("$#,##0;$#,##0");
textFormatter[0x06] = new DecimalFormat("$#,##0;$#,##0");
textFormatter[0x07] = new DecimalFormat("$#,##0.00;$#,##0.00");
textFormatter[0x08] = new DecimalFormat("$#,##0.00;$#,##0.00");
textFormatter[0x09] = new DecimalFormat("0%");
textFormatter[0x0A] = new DecimalFormat("0.00%");
textFormatter[0x0B] = new DecimalFormat("0.00E0");
textFormatter[0x0C] = new SVFractionalFormat("# ?/?");
textFormatter[0x0D] = new SVFractionalFormat("# ??/??");
textFormatter[0x0E] = new SimpleDateFormat("M/d/yy");
textFormatter[0x0F] = new SimpleDateFormat("d-MMM-yy");
textFormatter[0x10] = new SimpleDateFormat("d-MMM");
textFormatter[0x11] = new SimpleDateFormat("MMM-yy");
textFormatter[0x12] = new SimpleDateFormat("h:mm a");
textFormatter[0x13] = new SimpleDateFormat("h:mm:ss a");
textFormatter[0x14] = new SimpleDateFormat("h:mm");
textFormatter[0x15] = new SimpleDateFormat("h:mm:ss");
textFormatter[0x16] = new SimpleDateFormat("M/d/yy h:mm");
// 0x17 - 0x24 reserved for international and undocumented 0x25, "(#,##0_);(#,##0)"
//start at 0x26
//jmh need to do colour
//"(#,##0_);[Red](#,##0)"
textFormatter[0x26] = new DecimalFormat("#,##0;#,##0");
//jmh need to do colour
//(#,##0.00_);(#,##0.00)
textFormatter[0x27] = new DecimalFormat("#,##0.00;#,##0.00");
textFormatter[0x28] = new DecimalFormat("#,##0.00;#,##0.00");
//?? textFormatter[0x29] = new DecimalFormat("_(*#,##0_);_(*(#,##0);_(* \"-\"_);_(@_)");
//?? textFormatter[0x2A] = new DecimalFormat("_($*#,##0_);_($*(#,##0);_($* \"-\"_);_(@_)");
//?? textFormatter[0x2B] = new DecimalFormat("_(*#,##0.00_);_(*(#,##0.00);_(*\"-\"??_);_(@_)");
//?? textFormatter[0x2C] = new DecimalFormat("_($*#,##0.00_);_($*(#,##0.00);_($*\"-\"??_);_(@_)");
textFormatter[0x2D] = new SimpleDateFormat("mm:ss");
textFormatter[0x2D] = new SimpleDateFormat("mm:ss");
//?? textFormatter[0x2E] = new SimpleDateFormat("[h]:mm:ss");
textFormatter[0x2F] = new SimpleDateFormat("mm:ss.0");
textFormatter[0x30] = new DecimalFormat("##0.0E0");
}
public String format(short index, double value) {
if ( index <= 0 )
return generalNumberFormat.format(value);
if (textFormatter[index] == null)
throw new RuntimeException("Sorry. I cant handle the format code :"+Integer.toHexString(index));
if (textFormatter[index] instanceof DecimalFormat) {
return ((DecimalFormat)textFormatter[index]).format(value);
textFormatter[0x2F] = new SimpleDateFormat("mm:ss.0");
textFormatter[0x30] = new DecimalFormat("##0.0E0");
}
if (textFormatter[index] instanceof SVFractionalFormat) {
return ((SVFractionalFormat)textFormatter[index]).format(value);
}
throw new RuntimeException("Sorry. I cant handle a non decimal formatter for a decimal value :"+Integer.toHexString(index));
}
public boolean useRedColor(short index, double value) {
return (((index == 0x06)||(index == 0x08)||(index == 0x26) || (index == 0x27)) && (value < 0));
}
public String format(short index, double value) {
if (index <= 0)
return generalNumberFormat.format(value);
if (textFormatter[index] == null)
throw new RuntimeException("Sorry. I cant handle the format code :" + Integer.toHexString(index));
if (textFormatter[index] instanceof DecimalFormat) {
return ((DecimalFormat) textFormatter[index]).format(value);
}
if (textFormatter[index] instanceof SVFractionalFormat) {
return ((SVFractionalFormat) textFormatter[index]).format(value);
}
throw new RuntimeException("Sorry. I cant handle a non decimal formatter for a decimal value :" + Integer.toHexString(index));
}
public boolean useRedColor(short index, double value) {
return (((index == 0x06) || (index == 0x08) || (index == 0x26) || (index == 0x27)) && (value < 0));
}
}
private final CellFormatter cellFormatter = new CellFormatter();
public SVTableCellRenderer(HSSFWorkbook wb) {
super();
setOpaque(true);
super();
setOpaque(true);
setBorder(noFocusBorder);
this.wb = wb;
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
boolean isBorderSet = false;
boolean isSelected, boolean hasFocus, int row, int column) {
boolean isBorderSet = false;
//If the JTables default cell renderer has been setup correctly the
//value will be the HSSFCell that we are trying to render
HSSFCell c = (HSSFCell)value;
HSSFCell c = (HSSFCell) value;
if (c != null) {
HSSFCellStyle s = c.getCellStyle();
HSSFFont f = wb.getFontAt(s.getFontIndexAsInt());
setFont(SVTableUtils.makeFont(f));
HSSFCellStyle s = c.getCellStyle();
HSSFFont f = wb.getFontAt(s.getFontIndexAsInt());
setFont(SVTableUtils.makeFont(f));
if (s.getFillPattern() == FillPatternType.SOLID_FOREGROUND) {
setBackground(SVTableUtils.getAWTColor(s.getFillForegroundColor(), SVTableUtils.white));
} else setBackground(SVTableUtils.white);
if (s.getFillPattern() == FillPatternType.SOLID_FOREGROUND) {
setBackground(SVTableUtils.getAWTColor(s.getFillForegroundColor(), SVTableUtils.white));
} else setBackground(SVTableUtils.white);
setForeground(SVTableUtils.getAWTColor(f.getColor(), SVTableUtils.black));
setForeground(SVTableUtils.getAWTColor(f.getColor(), SVTableUtils.black));
cellBorder.setBorder(SVTableUtils.getAWTColor(s.getTopBorderColor(), SVTableUtils.black),
SVTableUtils.getAWTColor(s.getRightBorderColor(), SVTableUtils.black),
SVTableUtils.getAWTColor(s.getBottomBorderColor(), SVTableUtils.black),
SVTableUtils.getAWTColor(s.getLeftBorderColor(), SVTableUtils.black),
s.getBorderTop(), s.getBorderRight(),
s.getBorderBottom(), s.getBorderLeft(),
hasFocus);
cellBorder.setBorder(SVTableUtils.getAWTColor(s.getTopBorderColor(), SVTableUtils.black),
SVTableUtils.getAWTColor(s.getRightBorderColor(), SVTableUtils.black),
SVTableUtils.getAWTColor(s.getBottomBorderColor(), SVTableUtils.black),
SVTableUtils.getAWTColor(s.getLeftBorderColor(), SVTableUtils.black),
s.getBorderTop(), s.getBorderRight(),
s.getBorderBottom(), s.getBorderLeft(),
hasFocus);
setBorder(cellBorder);
isBorderSet=true;
isBorderSet = true;
//Set the value that is rendered for the cell
switch (c.getCellType()) {
case BLANK:
setValue("");
break;
case BOOLEAN:
if (c.getBooleanCellValue()) {
setValue("true");
} else {
setValue("false");
}
break;
case NUMERIC:
short format = s.getDataFormat();
double numericValue = c.getNumericCellValue();
if (cellFormatter.useRedColor(format, numericValue))
setForeground(Color.red);
else setForeground(null);
setValue(cellFormatter.format(format, c.getNumericCellValue()));
break;
case STRING:
setValue(c.getRichStringCellValue().getString());
break;
case FORMULA:
default:
setValue("?");
case BLANK:
setValue("");
break;
case BOOLEAN:
if (c.getBooleanCellValue()) {
setValue("true");
} else {
setValue("false");
}
break;
case NUMERIC:
short format = s.getDataFormat();
double numericValue = c.getNumericCellValue();
if (cellFormatter.useRedColor(format, numericValue))
setForeground(Color.red);
else setForeground(null);
setValue(cellFormatter.format(format, c.getNumericCellValue()));
break;
case STRING:
setValue(c.getRichStringCellValue().getString());
break;
case FORMULA:
default:
setValue("?");
}
//Set the text alignment of the cell
switch (s.getAlignment()) {
case LEFT:
case JUSTIFY:
case FILL:
setHorizontalAlignment(SwingConstants.LEFT);
break;
case CENTER:
case CENTER_SELECTION:
setHorizontalAlignment(SwingConstants.CENTER);
break;
case GENERAL:
case RIGHT:
setHorizontalAlignment(SwingConstants.RIGHT);
break;
default:
setHorizontalAlignment(SwingConstants.LEFT);
break;
case LEFT:
case JUSTIFY:
case FILL:
setHorizontalAlignment(SwingConstants.LEFT);
break;
case CENTER:
case CENTER_SELECTION:
setHorizontalAlignment(SwingConstants.CENTER);
break;
case GENERAL:
case RIGHT:
setHorizontalAlignment(SwingConstants.RIGHT);
break;
default:
setHorizontalAlignment(SwingConstants.LEFT);
break;
}
} else {
setValue("");
setBackground(SVTableUtils.white);
setValue("");
setBackground(SVTableUtils.white);
}
if (hasFocus) {
if (hasFocus) {
if (!isBorderSet) {
//This is the border to paint when there is no border
//and the cell has focus
cellBorder.setBorder(SVTableUtils.black,
SVTableUtils.black,
SVTableUtils.black,
SVTableUtils.black,
BorderStyle.NONE,
BorderStyle.NONE,
BorderStyle.NONE,
BorderStyle.NONE,
isSelected);
setBorder(cellBorder);
//This is the border to paint when there is no border
//and the cell has focus
cellBorder.setBorder(SVTableUtils.black,
SVTableUtils.black,
SVTableUtils.black,
SVTableUtils.black,
BorderStyle.NONE,
BorderStyle.NONE,
BorderStyle.NONE,
BorderStyle.NONE,
isSelected);
setBorder(cellBorder);
}
if (table.isCellEditable(row, column)) {
setForeground( UIManager.getColor("Table.focusCellForeground") );
setBackground( UIManager.getColor("Table.focusCellBackground") );
}
} else if (!isBorderSet) {
setBorder(noFocusBorder);
}
if (table.isCellEditable(row, column)) {
setForeground(UIManager.getColor("Table.focusCellForeground"));
setBackground(UIManager.getColor("Table.focusCellBackground"));
}
} else if (!isBorderSet) {
setBorder(noFocusBorder);
}
// ---- begin optimization to avoid painting background ----
Color back = getBackground();
boolean colorMatch = (back != null) && ( back.equals(table.getBackground()) ) && table.isOpaque();
// ---- begin optimization to avoid painting background ----
Color back = getBackground();
boolean colorMatch = (back != null) && (back.equals(table.getBackground())) && table.isOpaque();
setOpaque(!colorMatch);
// ---- end optimization to aviod painting background ----
return this;
// ---- end optimization to aviod painting background ----
return this;
}
@Override
public void validate() {}
public void validate() {
}
@Override
public void revalidate() {}
public void revalidate() {
}
@Override
public void repaint(long tm, int x, int y, int width, int height) {}
public void repaint(long tm, int x, int y, int width, int height) {
}
@Override
public void repaint(Rectangle r) { }
public void repaint(Rectangle r) {
}
@Override
protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
// Strings get interned...
if (propertyName=="text") {
super.firePropertyChange(propertyName, oldValue, newValue);
}
// Strings get interned...
if (propertyName == "text") {
super.firePropertyChange(propertyName, oldValue, newValue);
}
}
@Override
public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) { }
public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) {
}
/**
* Sets the string to either the value or "" if the value is null.
*
*/
protected void setValue(Object value) {
setText((value == null) ? "" : value.toString());
setText((value == null) ? "" : value.toString());
}
}

View File

@ -15,80 +15,83 @@
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.view;
import java.util.Iterator;
import javax.swing.table.*;
import javax.swing.table.AbstractTableModel;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.hssf.usermodel.HSSFCell;
/**
* Sheet Viewer Table Model - The model for the Sheet Viewer just overrides things.
*
* @author Andrew C. Oliver
*/
public class SVTableModel extends AbstractTableModel {
private HSSFSheet st;
int maxcol;
private HSSFSheet st;
int maxcol;
public SVTableModel(HSSFSheet st, int maxcol) {
this.st = st;
this.maxcol=maxcol;
}
public SVTableModel(HSSFSheet st) {
this.st = st;
Iterator<Row> i = st.rowIterator();
while (i.hasNext()) {
HSSFRow row = (HSSFRow)i.next();
if (maxcol < (row.getLastCellNum()+1)) {
this.maxcol = row.getLastCellNum();
}
public SVTableModel(HSSFSheet st, int maxcol) {
this.st = st;
this.maxcol = maxcol;
}
}
public SVTableModel(HSSFSheet st) {
this.st = st;
Iterator<Row> i = st.rowIterator();
@Override
public int getColumnCount() {
return this.maxcol+1;
}
@Override
public Object getValueAt(int row, int col) {
HSSFRow r = st.getRow(row);
HSSFCell c = null;
if (r != null) {
c = r.getCell(col);
while (i.hasNext()) {
HSSFRow row = (HSSFRow) i.next();
if (maxcol < (row.getLastCellNum() + 1)) {
this.maxcol = row.getLastCellNum();
}
}
}
return c;
}
@Override
public int getRowCount() {
return st.getLastRowNum() + 1;
}
@Override
public Class<?> getColumnClass(int c) {
return HSSFCell.class;
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return true;
}
@Override
public int getColumnCount() {
return this.maxcol + 1;
}
@Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
if (aValue != null)
System.out.println("SVTableModel.setValueAt. value type = "+aValue.getClass().getName());
else System.out.println("SVTableModel.setValueAt. value type = null");
}
@Override
public Object getValueAt(int row, int col) {
HSSFRow r = st.getRow(row);
HSSFCell c = null;
if (r != null) {
c = r.getCell(col);
}
return c;
}
@Override
public int getRowCount() {
return st.getLastRowNum() + 1;
}
@Override
public Class<?> getColumnClass(int c) {
return HSSFCell.class;
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return true;
}
@Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
if (aValue != null)
System.out.println("SVTableModel.setValueAt. value type = " + aValue.getClass().getName());
else System.out.println("SVTableModel.setValueAt. value type = null");
}
}

View File

@ -32,55 +32,63 @@ import org.apache.poi.hssf.util.HSSFColor.HSSFColorPredefined;
/**
* SVTableCell Editor and Renderer helper functions.
*
* @author Jason Height
* @author Jason Height
*/
public class SVTableUtils {
private final static Map<Integer,HSSFColor> colors = HSSFColor.getIndexHash();
/** Description of the Field */
public final static Color black = getAWTColor(HSSFColorPredefined.BLACK);
/** Description of the Field */
public final static Color white = getAWTColor(HSSFColorPredefined.WHITE);
/** Description of the Field */
public static final Border noFocusBorder = new EmptyBorder(1, 1, 1, 1);
private final static Map<Integer, HSSFColor> colors = HSSFColor.getIndexHash();
/**
* Description of the Field
*/
public final static Color black = getAWTColor(HSSFColorPredefined.BLACK);
/**
* Description of the Field
*/
public final static Color white = getAWTColor(HSSFColorPredefined.WHITE);
/**
* Description of the Field
*/
public static final Border noFocusBorder = new EmptyBorder(1, 1, 1, 1);
/**
* Creates a new font for a specific cell style
*/
public static Font makeFont(HSSFFont font) {
boolean isbold = font.getBold();
boolean isitalics = font.getItalic();
int fontstyle = Font.PLAIN;
if (isbold) {
fontstyle = Font.BOLD;
}
if (isitalics) {
fontstyle = fontstyle | Font.ITALIC;
/**
* Creates a new font for a specific cell style
*/
public static Font makeFont(HSSFFont font) {
boolean isbold = font.getBold();
boolean isitalics = font.getItalic();
int fontstyle = Font.PLAIN;
if (isbold) {
fontstyle = Font.BOLD;
}
if (isitalics) {
fontstyle = fontstyle | Font.ITALIC;
}
int fontheight = font.getFontHeightInPoints();
if (fontheight == 9) {
//fix for stupid ol Windows
fontheight = 10;
}
return new Font(font.getFontName(), fontstyle, fontheight);
}
int fontheight = font.getFontHeightInPoints();
if (fontheight == 9) {
//fix for stupid ol Windows
fontheight = 10;
/**
* This method retrieves the AWT Color representation from the colour hash table
*/
/* package */
static Color getAWTColor(int index, Color deflt) {
HSSFColor clr = colors.get(index);
if (clr == null) {
return deflt;
}
short[] rgb = clr.getTriplet();
return new Color(rgb[0], rgb[1], rgb[2]);
}
return new Font(font.getFontName(), fontstyle, fontheight);
}
/** This method retrieves the AWT Color representation from the colour hash table
*
*/
/* package */ static Color getAWTColor(int index, Color deflt) {
HSSFColor clr = colors.get(index);
if (clr == null) {
return deflt;
/* package */
static Color getAWTColor(HSSFColorPredefined clr) {
short[] rgb = clr.getTriplet();
return new Color(rgb[0], rgb[1], rgb[2]);
}
short[] rgb = clr.getTriplet();
return new Color(rgb[0],rgb[1],rgb[2]);
}
/* package */ static Color getAWTColor(HSSFColorPredefined clr) {
short[] rgb = clr.getTriplet();
return new Color(rgb[0],rgb[1],rgb[2]);
}
}

View File

@ -53,267 +53,291 @@ import org.apache.poi.hssf.usermodel.HSSFWorkbook;
* This class presents the sheets to the user.
*/
public class SViewerPanel extends JPanel {
/** This field is the magic number to convert from a Character width to a
* java pixel width.
*
* When the "normal" font size in a workbook changes, this effects all
* of the heights and widths. Unfortunately there is no way to retrieve this
* information, hence the MAGIC number.
*
* This number may only work for the normal style font size of Arial size 10.
*
*/
private static final int magicCharFactor = 7;
/** Reference to the wookbook that is being displayed*/
/* package */ HSSFWorkbook wb;
/** Reference to the tabs component*/
/* package */ JTabbedPane sheetPane;
/** Reference to the cell renderer that is used to render all cells*/
private SVTableCellRenderer cellRenderer;
/** Reference to the cell editor that is used to edit all cells.
* Only constructed if editing is allowed
*/
private SVTableCellEditor cellEditor;
/** Flag indicating if editing is allowed. Otherwise the viewer is in
* view only mode.
*/
private boolean allowEdits;
/**Construct the representation of the workbook*/
public SViewerPanel(HSSFWorkbook wb, boolean allowEdits) {
this.wb = wb;
this.allowEdits = allowEdits;
initialiseGui();
}
private void initialiseGui() {
cellRenderer = new SVTableCellRenderer(this.wb);
if (allowEdits)
cellEditor = new SVTableCellEditor(this.wb);
//Initialise the Panel
sheetPane = new JTabbedPane(JTabbedPane.BOTTOM);
if (allowEdits)
sheetPane.addMouseListener(createTabListener());
int sheetCount = wb.getNumberOfSheets();
for (int i=0; i<sheetCount;i++) {
String sheetName = wb.getSheetName(i);
//Add the new sheet to the tabbed pane
sheetPane.addTab(sheetName, makeSheetView(wb.getSheetAt(i)));
}
setLayout(new BorderLayout());
add(sheetPane, BorderLayout.CENTER);
}
protected JComponent makeSheetView(HSSFSheet sheet) {
JTable sheetView = new JTable(new SVTableModel(sheet));
sheetView.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
sheetView.setDefaultRenderer(HSSFCell.class, cellRenderer);
if (allowEdits)
sheetView.setDefaultEditor(HSSFCell.class, cellEditor);
JTableHeader header = sheetView.getTableHeader();
//Dont allow column reordering
header.setReorderingAllowed(false);
//Only allow column resizing if editing is allowed
header.setResizingAllowed(allowEdits);
//Set the columns the correct size
TableColumnModel columns = sheetView.getColumnModel();
for (int i=0; i< columns.getColumnCount(); i++) {
TableColumn column = columns.getColumn(i);
int width = sheet.getColumnWidth(i);
//256 is because the width is in 256ths of a character
column.setPreferredWidth(width/256*magicCharFactor);
}
//Set the rows to the correct size
int rows = sheet.getPhysicalNumberOfRows();
Insets insets = cellRenderer.getInsets();
//Need to include the insets in the calculation of the row height to use.
int extraHeight = insets.bottom+insets.top;
for (int i=0; i< rows; i++) {
HSSFRow row = sheet.getRow(i);
if (row == null) {
sheetView.setRowHeight(i, (int)sheet.getDefaultRowHeightInPoints()+extraHeight);
} else {
sheetView.setRowHeight(i, (int)row.getHeightInPoints()+extraHeight);
}
}
//Add the row header to the sheet
SVRowHeader rowHeader = new SVRowHeader(sheet, sheetView, extraHeight);
JScrollPane scroll = new JScrollPane( sheetView );
scroll.setRowHeaderView(rowHeader);
return scroll;
}
@Override
public void paint(Graphics g) {
//JMH I am only overriding this to get a picture of the time taken to paint
long start = System.currentTimeMillis();
super.paint(g);
long elapsed = System.currentTimeMillis()-start;
System.out.println("Paint time = "+elapsed);
}
protected MouseListener createTabListener() {
return new TabListener();
}
/** This class defines the default MouseListener that listens to
* mouse events in the tabbed pane
*
* The default is to popup a menu when the event occurs over a tab
*/
private class TabListener implements MouseListener {
private final JPopupMenu popup;
public TabListener() {
popup = new JPopupMenu("Sheet");
popup.add(createInsertSheetAction());
popup.add(createDeleteSheetAction());
popup.add(createRenameSheetAction());
}
protected Action createInsertSheetAction() {
return new InsertSheetAction();
}
protected Action createDeleteSheetAction() {
return new DeleteSheetAction();
}
protected Action createRenameSheetAction() {
return new RenameSheetAction();
}
/** This method will display the popup if the mouseevent is a popup event
* and the event occurred over a tab
/**
* This field is the magic number to convert from a Character width to a
* java pixel width.
* <p>
* When the "normal" font size in a workbook changes, this effects all
* of the heights and widths. Unfortunately there is no way to retrieve this
* information, hence the MAGIC number.
* <p>
* This number may only work for the normal style font size of Arial size 10.
*/
protected void checkPopup(MouseEvent e) {
if (e.isPopupTrigger()) {
int tab = sheetPane.getUI().tabForCoordinate(sheetPane, e.getX(), e.getY());
if (tab != -1) {
popup.show(sheetPane, e.getX(), e.getY());
private static final int magicCharFactor = 7;
/**
* Reference to the wookbook that is being displayed
*/
/* package */ HSSFWorkbook wb;
/**
* Reference to the tabs component
*/
/* package */ JTabbedPane sheetPane;
/**
* Reference to the cell renderer that is used to render all cells
*/
private SVTableCellRenderer cellRenderer;
/**
* Reference to the cell editor that is used to edit all cells.
* Only constructed if editing is allowed
*/
private SVTableCellEditor cellEditor;
/**
* Flag indicating if editing is allowed. Otherwise the viewer is in
* view only mode.
*/
private boolean allowEdits;
/**
* Construct the representation of the workbook
*/
public SViewerPanel(HSSFWorkbook wb, boolean allowEdits) {
this.wb = wb;
this.allowEdits = allowEdits;
initialiseGui();
}
private void initialiseGui() {
cellRenderer = new SVTableCellRenderer(this.wb);
if (allowEdits)
cellEditor = new SVTableCellEditor(this.wb);
//Initialise the Panel
sheetPane = new JTabbedPane(JTabbedPane.BOTTOM);
if (allowEdits)
sheetPane.addMouseListener(createTabListener());
int sheetCount = wb.getNumberOfSheets();
for (int i = 0; i < sheetCount; i++) {
String sheetName = wb.getSheetName(i);
//Add the new sheet to the tabbed pane
sheetPane.addTab(sheetName, makeSheetView(wb.getSheetAt(i)));
}
}
setLayout(new BorderLayout());
add(sheetPane, BorderLayout.CENTER);
}
@Override
public void mouseClicked(MouseEvent e) {
checkPopup(e);
}
protected JComponent makeSheetView(HSSFSheet sheet) {
JTable sheetView = new JTable(new SVTableModel(sheet));
sheetView.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
sheetView.setDefaultRenderer(HSSFCell.class, cellRenderer);
if (allowEdits)
sheetView.setDefaultEditor(HSSFCell.class, cellEditor);
JTableHeader header = sheetView.getTableHeader();
//Dont allow column reordering
header.setReorderingAllowed(false);
//Only allow column resizing if editing is allowed
header.setResizingAllowed(allowEdits);
@Override
public void mousePressed(MouseEvent e) {
checkPopup(e);
}
@Override
public void mouseReleased(MouseEvent e) {
checkPopup(e);
}
@Override
public void mouseEntered(MouseEvent e) {}
@Override
public void mouseExited(MouseEvent e) {}
}
/** This class defines the action that is performed when the sheet is renamed*/
private class RenameSheetAction extends AbstractAction {
public RenameSheetAction() {
super("Rename");
}
@Override
public void actionPerformed(ActionEvent e) {
int tabIndex = sheetPane.getSelectedIndex();
if (tabIndex != -1) {
String newSheetName = JOptionPane.showInputDialog(sheetPane, "Enter a new Sheetname", "Rename Sheet", JOptionPane.QUESTION_MESSAGE);
if (newSheetName != null) {
wb.setSheetName(tabIndex, newSheetName);
sheetPane.setTitleAt(tabIndex, newSheetName);
//Set the columns the correct size
TableColumnModel columns = sheetView.getColumnModel();
for (int i = 0; i < columns.getColumnCount(); i++) {
TableColumn column = columns.getColumn(i);
int width = sheet.getColumnWidth(i);
//256 is because the width is in 256ths of a character
column.setPreferredWidth(width / 256 * magicCharFactor);
}
}
}
}
/** This class defines the action that is performed when a sheet is inserted*/
private class InsertSheetAction extends AbstractAction {
public InsertSheetAction() {
super("Insert");
//Set the rows to the correct size
int rows = sheet.getPhysicalNumberOfRows();
Insets insets = cellRenderer.getInsets();
//Need to include the insets in the calculation of the row height to use.
int extraHeight = insets.bottom + insets.top;
for (int i = 0; i < rows; i++) {
HSSFRow row = sheet.getRow(i);
if (row == null) {
sheetView.setRowHeight(i, (int) sheet.getDefaultRowHeightInPoints() + extraHeight);
} else {
sheetView.setRowHeight(i, (int) row.getHeightInPoints() + extraHeight);
}
}
//Add the row header to the sheet
SVRowHeader rowHeader = new SVRowHeader(sheet, sheetView, extraHeight);
JScrollPane scroll = new JScrollPane(sheetView);
scroll.setRowHeaderView(rowHeader);
return scroll;
}
@Override
public void actionPerformed(ActionEvent e) {
//Create a new sheet then search for the sheet and make sure that the
//sheetPane shows it.
HSSFSheet newSheet = wb.createSheet();
for (int i=0; i<wb.getNumberOfSheets();i++) {
HSSFSheet sheet = wb.getSheetAt(i);
if (newSheet == sheet) {
sheetPane.insertTab(wb.getSheetName(i), null, makeSheetView(sheet), null, i);
public void paint(Graphics g) {
//JMH I am only overriding this to get a picture of the time taken to paint
long start = System.currentTimeMillis();
super.paint(g);
long elapsed = System.currentTimeMillis() - start;
System.out.println("Paint time = " + elapsed);
}
protected MouseListener createTabListener() {
return new TabListener();
}
/**
* This class defines the default MouseListener that listens to
* mouse events in the tabbed pane
* <p>
* The default is to popup a menu when the event occurs over a tab
*/
private class TabListener implements MouseListener {
private final JPopupMenu popup;
public TabListener() {
popup = new JPopupMenu("Sheet");
popup.add(createInsertSheetAction());
popup.add(createDeleteSheetAction());
popup.add(createRenameSheetAction());
}
}
}
}
/** This class defines the action that is performed when the sheet is deleted*/
private class DeleteSheetAction extends AbstractAction {
public DeleteSheetAction() {
super("Delete");
}
@Override
public void actionPerformed(ActionEvent e) {
int tabIndex = sheetPane.getSelectedIndex();
if (tabIndex != -1) {
if (JOptionPane.showConfirmDialog(sheetPane, "Are you sure that you want to delete the selected sheet", "Delete Sheet?", JOptionPane.OK_CANCEL_OPTION) == JOptionPane.OK_OPTION) {
wb.removeSheetAt(tabIndex);
sheetPane.remove(tabIndex);
protected Action createInsertSheetAction() {
return new InsertSheetAction();
}
}
}
}
public boolean isEditable() {
return allowEdits;
}
protected Action createDeleteSheetAction() {
return new DeleteSheetAction();
}
/**Main method*/
public static void main(String[] args) throws IOException {
if (args.length < 1) {
throw new IllegalArgumentException("A filename to view must be supplied as the first argument, but none was given");
}
protected Action createRenameSheetAction() {
return new RenameSheetAction();
}
try (FileInputStream in = new FileInputStream(args[0]);
HSSFWorkbook wb = new HSSFWorkbook(in)) {
SViewerPanel p = new SViewerPanel(wb, true);
JFrame frame;
frame = new JFrame() {
@Override
protected void processWindowEvent(WindowEvent e) {
super.processWindowEvent(e);
if (e.getID() == WindowEvent.WINDOW_CLOSING) {
System.exit(0);
}
/**
* This method will display the popup if the mouseevent is a popup event
* and the event occurred over a tab
*/
protected void checkPopup(MouseEvent e) {
if (e.isPopupTrigger()) {
int tab = sheetPane.getUI().tabForCoordinate(sheetPane, e.getX(), e.getY());
if (tab != -1) {
popup.show(sheetPane, e.getX(), e.getY());
}
}
}
@Override
public synchronized void setTitle(String title) {
super.setTitle(title);
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
public void mouseClicked(MouseEvent e) {
checkPopup(e);
}
@Override
public void mousePressed(MouseEvent e) {
checkPopup(e);
}
@Override
public void mouseReleased(MouseEvent e) {
checkPopup(e);
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
}
/**
* This class defines the action that is performed when the sheet is renamed
*/
private class RenameSheetAction extends AbstractAction {
public RenameSheetAction() {
super("Rename");
}
@Override
public void actionPerformed(ActionEvent e) {
int tabIndex = sheetPane.getSelectedIndex();
if (tabIndex != -1) {
String newSheetName = JOptionPane.showInputDialog(sheetPane, "Enter a new Sheetname", "Rename Sheet", JOptionPane.QUESTION_MESSAGE);
if (newSheetName != null) {
wb.setSheetName(tabIndex, newSheetName);
sheetPane.setTitleAt(tabIndex, newSheetName);
}
}
}
}
/**
* This class defines the action that is performed when a sheet is inserted
*/
private class InsertSheetAction extends AbstractAction {
public InsertSheetAction() {
super("Insert");
}
@Override
public void actionPerformed(ActionEvent e) {
//Create a new sheet then search for the sheet and make sure that the
//sheetPane shows it.
HSSFSheet newSheet = wb.createSheet();
for (int i = 0; i < wb.getNumberOfSheets(); i++) {
HSSFSheet sheet = wb.getSheetAt(i);
if (newSheet == sheet) {
sheetPane.insertTab(wb.getSheetName(i), null, makeSheetView(sheet), null, i);
}
}
}
}
/**
* This class defines the action that is performed when the sheet is deleted
*/
private class DeleteSheetAction extends AbstractAction {
public DeleteSheetAction() {
super("Delete");
}
@Override
public void actionPerformed(ActionEvent e) {
int tabIndex = sheetPane.getSelectedIndex();
if (tabIndex != -1) {
if (JOptionPane.showConfirmDialog(sheetPane, "Are you sure that you want to delete the selected sheet", "Delete Sheet?", JOptionPane.OK_CANCEL_OPTION) == JOptionPane.OK_OPTION) {
wb.removeSheetAt(tabIndex);
sheetPane.remove(tabIndex);
}
}
}
}
public boolean isEditable() {
return allowEdits;
}
/**
* Main method
*/
public static void main(String[] args) throws IOException {
if (args.length < 1) {
throw new IllegalArgumentException("A filename to view must be supplied as the first argument, but none was given");
}
try (FileInputStream in = new FileInputStream(args[0]);
HSSFWorkbook wb = new HSSFWorkbook(in)) {
SViewerPanel p = new SViewerPanel(wb, true);
JFrame frame;
frame = new JFrame() {
@Override
protected void processWindowEvent(WindowEvent e) {
super.processWindowEvent(e);
if (e.getID() == WindowEvent.WINDOW_CLOSING) {
System.exit(0);
}
}
@Override
public synchronized void setTitle(String title) {
super.setTitle(title);
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
}
};
frame.setTitle("Viewer Frame");
frame.getContentPane().add(p, BorderLayout.CENTER);
frame.setSize(800, 640);
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
frame.setLocation((d.width - frame.getSize().width) / 2, (d.height - frame.getSize().height) / 2);
frame.setVisible(true);
}
};
frame.setTitle("Viewer Frame");
frame.getContentPane().add(p, BorderLayout.CENTER);
frame.setSize(800, 640);
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
frame.setLocation((d.width - frame.getSize().width) / 2, (d.height - frame.getSize().height) / 2);
frame.setVisible(true);
}
}
}