git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1870977 13f79535-47bb-0310-9956-ffa450edef68tags/REL_4_1_2
@@ -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; | |||
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(); | |||
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); | |||
} | |||
/** | |||
* 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); | |||
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; | |||
} | |||
@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); | |||
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); | |||
//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 (eastBorder && | |||
((eastBorderType == BorderStyle.THIN) || | |||
(eastBorderType == BorderStyle.MEDIUM) || | |||
(eastBorderType == BorderStyle.THICK) | |||
) | |||
) { | |||
if (northBorder && | |||
((northBorderType == BorderStyle.THIN) || | |||
(northBorderType == BorderStyle.MEDIUM) || | |||
(northBorderType == BorderStyle.THICK) | |||
) | |||
) { | |||
int thickness = getThickness(eastBorderType); | |||
int thickness = getThickness(northBorderType); | |||
g.setColor(eastColor); | |||
g.setColor(northColor); | |||
for (int k=0; k < thickness; k++) { | |||
g.drawLine(width-k,y,width-k,height); | |||
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(southBorderType); | |||
int thickness = getThickness(westBorderType); | |||
g.setColor(southColor); | |||
for (int k = 0; k < thickness; k++) { | |||
g.drawLine(x, height - k, width, height - k); | |||
} | |||
} | |||
g.setColor(westColor); | |||
if (westBorder && | |||
((westBorderType == BorderStyle.THIN) || | |||
(westBorderType == BorderStyle.MEDIUM) || | |||
(westBorderType == BorderStyle.THICK) | |||
) | |||
) { | |||
for (int k=0; k < thickness; k++) { | |||
g.drawLine(x+k,y,x+k,height); | |||
int thickness = getThickness(westBorderType); | |||
g.setColor(westColor); | |||
for (int k = 0; k < thickness; k++) { | |||
g.drawLine(x + k, y, x + k, height); | |||
} | |||
} | |||
} | |||
} | |||
/** | |||
* 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); | |||
g.setColor(northColor); | |||
for (int k=0; k < thickness; k++) { | |||
for (int xc = x; xc < width; xc=xc+2) { | |||
g.drawLine(xc,y+k,xc,y+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); | |||
g.setColor(northColor); | |||
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 (eastBorder && | |||
eastBorderType == BorderStyle.DOTTED | |||
) { | |||
if (eastBorder && | |||
eastBorderType == BorderStyle.DOTTED | |||
) { | |||
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 | |||
g.setColor(eastColor); | |||
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 yc = y; yc < height; yc = yc + 2) { | |||
g.drawLine(width - k, yc, width - k, yc); | |||
} | |||
} | |||
} | |||
} | |||
if (southBorder && | |||
southBorderType == 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); | |||
} | |||
if (southBorder && | |||
southBorderType == 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); | |||
} | |||
} | |||
} | |||
} | |||
if (westBorder && | |||
westBorderType == BorderStyle.DOTTED | |||
) { | |||
if (westBorder && | |||
westBorderType == BorderStyle.DOTTED | |||
) { | |||
int thickness = getThickness(westBorderType); | |||
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); | |||
int dashlength = 1; | |||
if (northBorderType == BorderStyle.DASHED) | |||
dashlength = 2; | |||
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); | |||
} | |||
} | |||
/** | |||
* 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; | |||
if (northBorderType == BorderStyle.DASHED) | |||
dashlength = 2; | |||
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); | |||
} | |||
} | |||
} | |||
} | |||
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) { | |||
g.setColor(northColor); | |||
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; | |||
} | |||
/** | |||
* 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); | |||
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 (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 | |||
) { | |||
g.drawLine(x,y,width,y); | |||
g.drawLine(leftx,y+2,rightx,y+2); | |||
} | |||
int thickness = getThickness(eastBorderType); | |||
thickness++; //need for dotted borders to show up east | |||
if (eastBorder && | |||
eastBorderType == BorderStyle.DOUBLE | |||
) { | |||
g.setColor(eastColor); | |||
int thickness = getThickness(eastBorderType); | |||
thickness++; //need for dotted borders to show up east | |||
int topy = y; | |||
int bottomy = height; | |||
g.setColor(eastColor); | |||
if (northBorder) { | |||
topy = y + 3; | |||
} | |||
int topy=y; | |||
int bottomy=height; | |||
if (southBorder) { | |||
bottomy = height - 3; | |||
} | |||
if (northBorder) { | |||
topy = y + 3; | |||
g.drawLine(width - 1, y, width - 1, height); | |||
g.drawLine(width - 3, topy, width - 3, bottomy); | |||
} | |||
if (southBorder) { | |||
bottomy = height - 3; | |||
} | |||
if (southBorder && | |||
southBorderType == BorderStyle.DOUBLE | |||
) { | |||
g.drawLine(width-1,y,width-1,height); | |||
g.drawLine(width-3,topy,width-3,bottomy); | |||
} | |||
g.setColor(southColor); | |||
if (southBorder && | |||
southBorderType == BorderStyle.DOUBLE | |||
) { | |||
int leftx = y; | |||
int rightx = width; | |||
g.setColor(southColor); | |||
if (westBorder) | |||
leftx = x + 3; | |||
int leftx=y; | |||
int rightx=width; | |||
if (eastBorder) | |||
rightx = width - 3; | |||
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 | |||
) { | |||
g.drawLine(x,height - 1,width,height - 1); | |||
g.drawLine(leftx,height - 3,rightx,height - 3); | |||
} | |||
int thickness = getThickness(westBorderType); | |||
// thickness++; | |||
if (westBorder && | |||
westBorderType == BorderStyle.DOUBLE | |||
) { | |||
g.setColor(westColor); | |||
int thickness = getThickness(westBorderType); | |||
// thickness++; | |||
int topy = y; | |||
int bottomy = height - 3; | |||
if (northBorder) | |||
topy = y + 2; | |||
if (southBorder) | |||
bottomy = height - 3; | |||
g.setColor(westColor); | |||
int topy=y; | |||
int bottomy=height-3; | |||
if (northBorder) | |||
topy=y+2; | |||
if (southBorder) | |||
bottomy=height-3; | |||
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); | |||
g.setColor(northColor); | |||
for (int l=x; l < width;) { | |||
l=l+drawDashDotDot(g, l, y, thickness, true, true); | |||
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); | |||
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); | |||
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)) | |||
) { | |||
if (southBorder && | |||
((southBorderType == BorderStyle.DASH_DOT_DOT) || | |||
(southBorderType == BorderStyle.MEDIUM_DASH_DOT_DOT)) | |||
) { | |||
int thickness = getThickness(southBorderType); | |||
int thickness = getThickness(southBorderType); | |||
g.setColor(southColor); | |||
g.setColor(southColor); | |||
for (int l=x; l < width;) { | |||
//System.err.println("drawing south"); | |||
l=l+drawDashDotDot(g, l, height-1, thickness, true, false); | |||
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)) | |||
) { | |||
if (westBorder && | |||
((westBorderType == BorderStyle.DASH_DOT_DOT) || | |||
(westBorderType == BorderStyle.MEDIUM_DASH_DOT_DOT)) | |||
) { | |||
int thickness = getThickness(westBorderType); | |||
int thickness = getThickness(westBorderType); | |||
g.setColor(westColor); | |||
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 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; | |||
} | |||
} | |||
} | |||
} | |||
/** | |||
* 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; | |||
} | |||
} | |||
} |
@@ -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; | |||
/** 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; | |||
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 | |||
* <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; | |||
} | |||
} | |||
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; | |||
/** | |||
* 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; | |||
} | |||
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; | |||
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; | |||
} | |||
if (sign < 0) { | |||
if (Whole == 0) { | |||
Num = -Num; | |||
} else { | |||
Whole = -Whole; | |||
} | |||
} | |||
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); | |||
} | |||
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; | |||
} | |||
throw new RuntimeException("Unexpected Case"); | |||
} | |||
if (Num == Den) { | |||
Whole++; | |||
Num = 0; | |||
Den = 0; | |||
} else if (Den == 0) { | |||
Num = 0; | |||
@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"); | |||
} | |||
if (sign < 0) { | |||
if (Whole == 0) { | |||
Num = -Num; | |||
} else { | |||
Whole = -Whole; | |||
} | |||
@Override | |||
public Object parseObject(String source, | |||
ParsePosition status) { | |||
//JMH TBD | |||
return null; | |||
} | |||
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 Object parseObject(String source) | |||
throws ParseException { | |||
//JMH TBD | |||
return null; | |||
} | |||
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 clone() { | |||
//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 clone() { | |||
//JMH TBD | |||
return null; | |||
} | |||
} |
@@ -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; | |||
public SVRowHeaderModel(HSSFSheet sheet) { | |||
this.sheet = 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; | |||
@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; | |||
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()); | |||
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 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; | |||
/** | |||
* 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()); | |||
} | |||
@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); | |||
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)); | |||
} | |||
setFixedCellWidth(50); | |||
setCellRenderer(new RowHeaderRenderer(sheet, table, extraHeight)); | |||
} | |||
} |
@@ -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 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; | |||
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); | |||
} | |||
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); | |||
/** | |||
* 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; | |||
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 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 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; | |||
@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) { | |||
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); | |||
return new HeaderCell(value, row); | |||
} | |||
} | |||
} | |||
private class FormulaDisplayListener implements ListSelectionListener { | |||
private final JTextComponent formulaDisplay; | |||
private class FormulaDisplayListener implements ListSelectionListener { | |||
private final JTextComponent formulaDisplay; | |||
public FormulaDisplayListener(JTextComponent formulaDisplay) { | |||
this.formulaDisplay = 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(); | |||
@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(); | |||
} | |||
if (formula == null) | |||
formula = ""; | |||
} | |||
formulaDisplay.setText(formula); | |||
} | |||
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); | |||
} | |||
} | |||
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); | |||
} | |||
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); | |||
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); | |||
} | |||
} | |||
} | |||
} | |||
}); | |||
} | |||
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; | |||
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("?")); | |||
} | |||
if (formulaDisplay != null) { | |||
formulaListener = new FormulaDisplayListener(formulaDisplay); | |||
rowSelMod.addListSelectionListener(formulaListener); | |||
colSelMod.addListSelectionListener(formulaListener); | |||
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 JTextComponent getFormulaDisplay() { | |||
if (formulaListener == null) | |||
return null; | |||
else | |||
return formulaListener.formulaDisplay; | |||
} | |||
public Component headerCell(String text) { | |||
return new HeaderCell(text, -1); | |||
} | |||
public Component headerCell(String text) { | |||
return new HeaderCell(text, -1); | |||
} | |||
@Override | |||
public void paintComponent(Graphics g1) { | |||
Graphics2D g = (Graphics2D) g1; | |||
@Override | |||
public void paintComponent(Graphics g1) { | |||
Graphics2D g = (Graphics2D) g1; | |||
pendingPaintings.clear(); | |||
pendingPaintings.clear(); | |||
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, | |||
RenderingHints.VALUE_ANTIALIAS_ON); | |||
super.paintComponent(g); | |||
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, | |||
RenderingHints.VALUE_ANTIALIAS_ON); | |||
super.paintComponent(g); | |||
pendingPaintings.paint(g); | |||
} | |||
pendingPaintings.paint(g); | |||
} | |||
} |
@@ -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 DecimalFormat generalNumberFormat = new DecimalFormat("0"); | |||
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"); | |||
private Format[] textFormatter; | |||
private DecimalFormat generalNumberFormat = new DecimalFormat("0"); | |||
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[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); | |||
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)); | |||
} | |||
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 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)); | |||
if (s.getFillPattern() == FillPatternType.SOLID_FOREGROUND) { | |||
setBackground(SVTableUtils.getAWTColor(s.getFillForegroundColor(), SVTableUtils.white)); | |||
} else setBackground(SVTableUtils.white); | |||
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); | |||
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); | |||
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); | |||
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")); | |||
} | |||
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(); | |||
} else if (!isBorderSet) { | |||
setBorder(noFocusBorder); | |||
} | |||
// ---- 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()); | |||
} | |||
} |
@@ -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; | |||
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(); | |||
} | |||
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(); | |||
} | |||
} | |||
} | |||
@Override | |||
public int getColumnCount() { | |||
return this.maxcol + 1; | |||
} | |||
} | |||
@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); | |||
@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"); | |||
} | |||
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"); | |||
} | |||
} |
@@ -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; | |||
} | |||
int fontheight = font.getFontHeightInPoints(); | |||
if (fontheight == 9) { | |||
//fix for stupid ol Windows | |||
fontheight = 10; | |||
} | |||
return new Font(font.getFontName(), fontstyle, fontheight); | |||
} | |||
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; | |||
/** | |||
* 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]); | |||
} | |||
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]); | |||
} | |||
/* package */ | |||
static Color getAWTColor(HSSFColorPredefined clr) { | |||
short[] rgb = clr.getTriplet(); | |||
return new Color(rgb[0], rgb[1], rgb[2]); | |||
} | |||
} |
@@ -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); | |||
} | |||
/** | |||
* 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; | |||
/** | |||
* 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; | |||
//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); | |||
} | |||
} | |||
/** | |||
* Construct the representation of the workbook | |||
*/ | |||
public SViewerPanel(HSSFWorkbook wb, boolean allowEdits) { | |||
this.wb = wb; | |||
this.allowEdits = allowEdits; | |||
//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()); | |||
initialiseGui(); | |||
} | |||
protected Action createInsertSheetAction() { | |||
return new InsertSheetAction(); | |||
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 Action createDeleteSheetAction() { | |||
return new DeleteSheetAction(); | |||
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; | |||
} | |||
protected Action createRenameSheetAction() { | |||
return new RenameSheetAction(); | |||
@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 method will display the popup if the mouseevent is a popup event | |||
* and the event occurred over a tab | |||
/** | |||
* 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 | |||
*/ | |||
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 class TabListener implements MouseListener { | |||
private final JPopupMenu popup; | |||
public TabListener() { | |||
popup = new JPopupMenu("Sheet"); | |||
popup.add(createInsertSheetAction()); | |||
popup.add(createDeleteSheetAction()); | |||
popup.add(createRenameSheetAction()); | |||
} | |||
} | |||
} | |||
@Override | |||
public void mouseClicked(MouseEvent e) { | |||
checkPopup(e); | |||
} | |||
protected Action createInsertSheetAction() { | |||
return new InsertSheetAction(); | |||
} | |||
@Override | |||
public void mousePressed(MouseEvent e) { | |||
checkPopup(e); | |||
} | |||
protected Action createDeleteSheetAction() { | |||
return new DeleteSheetAction(); | |||
} | |||
@Override | |||
public void mouseReleased(MouseEvent e) { | |||
checkPopup(e); | |||
} | |||
protected Action createRenameSheetAction() { | |||
return new RenameSheetAction(); | |||
} | |||
@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"); | |||
} | |||
/** | |||
* 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 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); | |||
@Override | |||
public void mouseClicked(MouseEvent e) { | |||
checkPopup(e); | |||
} | |||
} | |||
} | |||
} | |||
/** 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 mousePressed(MouseEvent e) { | |||
checkPopup(e); | |||
} | |||
@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); | |||
@Override | |||
public void mouseReleased(MouseEvent e) { | |||
checkPopup(e); | |||
} | |||
} | |||
} | |||
} | |||
/** 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 mouseEntered(MouseEvent e) { | |||
} | |||
@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); | |||
@Override | |||
public void mouseExited(MouseEvent e) { | |||
} | |||
} | |||
} | |||
} | |||
public boolean isEditable() { | |||
return allowEdits; | |||
} | |||
/** | |||
* This class defines the action that is performed when the sheet is renamed | |||
*/ | |||
private class RenameSheetAction extends AbstractAction { | |||
public RenameSheetAction() { | |||
super("Rename"); | |||
} | |||
/**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"); | |||
@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); | |||
} | |||
} | |||
} | |||
} | |||
try (FileInputStream in = new FileInputStream(args[0]); | |||
HSSFWorkbook wb = new HSSFWorkbook(in)) { | |||
SViewerPanel p = new SViewerPanel(wb, true); | |||
JFrame frame; | |||
frame = new JFrame() { | |||
/** | |||
* This class defines the action that is performed when a sheet is inserted | |||
*/ | |||
private class InsertSheetAction extends AbstractAction { | |||
public InsertSheetAction() { | |||
super("Insert"); | |||
} | |||
@Override | |||
protected void processWindowEvent(WindowEvent e) { | |||
super.processWindowEvent(e); | |||
if (e.getID() == WindowEvent.WINDOW_CLOSING) { | |||
System.exit(0); | |||
} | |||
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 synchronized void setTitle(String title) { | |||
super.setTitle(title); | |||
enableEvents(AWTEvent.WINDOW_EVENT_MASK); | |||
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); | |||
} | |||
} | |||
} |