merge GSoC code with trunk

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1371663 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Yegor Kozlov 2012-08-10 11:30:42 +00:00
commit c91082dc80
70 changed files with 8806 additions and 2360 deletions

View File

@ -632,6 +632,7 @@ under the License.
<syspropertyset refid="junit.properties"/> <syspropertyset refid="junit.properties"/>
<jvmarg value="${poi.test.locale}"/> <jvmarg value="${poi.test.locale}"/>
<jvmarg value="-ea"/> <jvmarg value="-ea"/>
<jvmarg value="-Xmx256m"/>
<formatter type="plain"/> <formatter type="plain"/>
<batchtest todir="${main.reports.test}"> <batchtest todir="${main.reports.test}">
<fileset dir="${main.src.test}"> <fileset dir="${main.src.test}">

View File

@ -16,10 +16,7 @@
==================================================================== */ ==================================================================== */
package org.apache.poi.ddf; package org.apache.poi.ddf;
import java.util.ArrayList; import java.util.*;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import org.apache.poi.util.HexDump; import org.apache.poi.util.HexDump;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
@ -139,6 +136,33 @@ public abstract class AbstractEscherOptRecord extends EscherRecord
} ); } );
} }
/**
* Set an escher property. If a property with given propId already
exists it is replaced.
*
* @param value the property to set.
*/
public void setEscherProperty(EscherProperty value){
for ( Iterator<EscherProperty> iterator =
properties.iterator(); iterator.hasNext(); ) {
EscherProperty prop = iterator.next();
if (prop.getId() == value.getId()){
iterator.remove();
}
}
properties.add( value );
sortProperties();
}
public void removeEscherProperty(int num){
for ( Iterator<EscherProperty> iterator = getEscherProperties().iterator(); iterator.hasNext(); ) {
EscherProperty prop = iterator.next();
if (prop.getPropertyNumber() == num){
iterator.remove();
}
}
}
/** /**
* Retrieve the string representation of this record. * Retrieve the string representation of this record.
*/ */

View File

@ -65,8 +65,7 @@ public class DefaultEscherRecordFactory implements EscherRecordFactory {
// However, EscherTextboxRecord are containers of records for the // However, EscherTextboxRecord are containers of records for the
// host application, not of other Escher records, so treat them // host application, not of other Escher records, so treat them
// differently // differently
if ( ( options & (short) 0x000F ) == (short) 0x000F if (isContainer(options, recordId)) {
&& recordId != EscherTextboxRecord.RECORD_ID ) {
EscherContainerRecord r = new EscherContainerRecord(); EscherContainerRecord r = new EscherContainerRecord();
r.setRecordId( recordId ); r.setRecordId( recordId );
r.setOptions( options ); r.setOptions( options );
@ -145,4 +144,17 @@ public class DefaultEscherRecordFactory implements EscherRecordFactory {
} }
return result; return result;
} }
public static boolean isContainer(short options, short recordId){
if(recordId >= EscherContainerRecord.DGG_CONTAINER && recordId
<= EscherContainerRecord.SOLVER_CONTAINER){
return true;
} else {
if (recordId == EscherTextboxRecord.RECORD_ID) {
return false;
} else {
return ( options & (short) 0x000F ) == (short) 0x000F;
}
}
}
} }

View File

@ -62,6 +62,9 @@ public final class EscherArrayProperty extends EscherComplexProperty {
} }
public int getNumberOfElementsInArray() { public int getNumberOfElementsInArray() {
if (emptyComplexPart){
return 0;
}
return LittleEndian.getUShort(_complexData, 0); return LittleEndian.getUShort(_complexData, 0);
} }

View File

@ -70,7 +70,7 @@ public class EscherBoolProperty
public String toXml(String tab){ public String toXml(String tab){
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
builder.append(tab).append("<").append(getClass().getSimpleName()).append(" id=\"0x").append(HexDump.toHex(getId())) builder.append(tab).append("<").append(getClass().getSimpleName()).append(" id=\"0x").append(HexDump.toHex(getId()))
.append("\" name=\"").append(getName()).append("\" blipId=\"") .append("\" name=\"").append(getName()).append("\" simpleValue=\"").append(getPropertyValue()).append("\" blipId=\"")
.append(isBlipId()).append("\" value=\"").append(isTrue()).append("\"").append("/>\n"); .append(isBlipId()).append("\" value=\"").append(isTrue()).append("\"").append("/>\n");
return builder.toString(); return builder.toString();
} }

View File

@ -1,4 +1,3 @@
/* ==================================================================== /* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with contributor license agreements. See the NOTICE file distributed with
@ -38,6 +37,14 @@ public class EscherClientAnchorRecord
public static final short RECORD_ID = (short) 0xF010; public static final short RECORD_ID = (short) 0xF010;
public static final String RECORD_DESCRIPTION = "MsofbtClientAnchor"; public static final String RECORD_DESCRIPTION = "MsofbtClientAnchor";
/**
* bit[0] - fMove (1 bit): A bit that specifies whether the shape will be kept intact when the cells are moved.
* bit[1] - fSize (1 bit): A bit that specifies whether the shape will be kept intact when the cells are resized. If fMove is 1, the value MUST be 1.
* bit[2-4] - reserved, MUST be 0 and MUST be ignored
* bit[5-15]- Undefined and MUST be ignored.
*
* it can take values: 0, 2, 3
*/
private short field_1_flag; private short field_1_flag;
private short field_2_col1; private short field_2_col1;
private short field_3_dx1; private short field_3_dx1;

View File

@ -25,6 +25,8 @@ import java.util.NoSuchElementException;
import org.apache.poi.util.HexDump; import org.apache.poi.util.HexDump;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
/** /**
* Escher container records store other escher records as children. * Escher container records store other escher records as children.
@ -42,6 +44,32 @@ public final class EscherContainerRecord extends EscherRecord {
public static final short SP_CONTAINER = (short)0xF004; public static final short SP_CONTAINER = (short)0xF004;
public static final short SOLVER_CONTAINER = (short)0xF005; public static final short SOLVER_CONTAINER = (short)0xF005;
private static POILogger log = POILogFactory.getLogger(EscherContainerRecord.class);
/**
* in case if document contains any charts we have such document structure:
* BOF
* ...
* DrawingRecord
* ...
* ObjRecord|TxtObjRecord
* ...
* EOF
* ...
* BOF(Chart begin)
* ...
* DrawingRecord
* ...
* ObjRecord|TxtObjRecord
* ...
* EOF
* So, when we call EscherAggregate.createAggregate() we have not all needed data.
* When we got warning "WARNING: " + bytesRemaining + " bytes remaining but no space left"
* we should save value of bytesRemaining
* and add it to container size when we serialize it
*/
private int _remainingLength;
private final List<EscherRecord> _childRecords = new ArrayList<EscherRecord>(); private final List<EscherRecord> _childRecords = new ArrayList<EscherRecord>();
public int fillFields(byte[] data, int pOffset, EscherRecordFactory recordFactory) { public int fillFields(byte[] data, int pOffset, EscherRecordFactory recordFactory) {
@ -56,7 +84,8 @@ public final class EscherContainerRecord extends EscherRecord {
bytesRemaining -= childBytesWritten; bytesRemaining -= childBytesWritten;
addChildRecord(child); addChildRecord(child);
if (offset >= data.length && bytesRemaining > 0) { if (offset >= data.length && bytesRemaining > 0) {
System.out.println("WARNING: " + bytesRemaining + " bytes remaining but no space left"); _remainingLength = bytesRemaining;
log.log(POILogger.WARN, "Not enough Escher data: " + bytesRemaining + " bytes remaining but no space left");
} }
} }
return bytesWritten; return bytesWritten;
@ -74,6 +103,7 @@ public final class EscherContainerRecord extends EscherRecord {
EscherRecord r = iterator.next(); EscherRecord r = iterator.next();
remainingBytes += r.getRecordSize(); remainingBytes += r.getRecordSize();
} }
remainingBytes += _remainingLength;
LittleEndian.putInt(data, offset+4, remainingBytes); LittleEndian.putInt(data, offset+4, remainingBytes);
int pos = offset+8; int pos = offset+8;
iterator = _childRecords.iterator(); iterator = _childRecords.iterator();

View File

@ -311,7 +311,7 @@ public abstract class EscherRecord {
protected String formatXmlRecordHeader(String className, String recordId, String version, String instance){ protected String formatXmlRecordHeader(String className, String recordId, String version, String instance){
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
builder.append("<").append(className).append(" recordId=\"0x").append(recordId).append("\" version=\"0x") builder.append("<").append(className).append(" recordId=\"0x").append(recordId).append("\" version=\"0x")
.append(version).append("\" instance=\"0x").append(instance).append("\">\n"); .append(version).append("\" instance=\"0x").append(instance).append("\" size=\"").append(getRecordSize()).append("\">\n");
return builder.toString(); return builder.toString();
} }

View File

@ -119,7 +119,7 @@ public class EscherSpRecord
public String toXml(String tab) { public String toXml(String tab) {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
builder.append(tab).append(formatXmlRecordHeader(getClass().getSimpleName(), HexDump.toHex(getRecordId()), HexDump.toHex(getVersion()), HexDump.toHex(getInstance()))) builder.append(tab).append(formatXmlRecordHeader(getClass().getSimpleName(), HexDump.toHex(getRecordId()), HexDump.toHex(getVersion()), HexDump.toHex(getInstance())))
.append(tab).append("\t").append("<ShapeType>").append(HexDump.toHex(getShapeType())).append("</ShapeType>\n") .append(tab).append("\t").append("<ShapeType>0x").append(HexDump.toHex(getShapeType())).append("</ShapeType>\n")
.append(tab).append("\t").append("<ShapeId>").append(field_1_shapeId).append("</ShapeId>\n") .append(tab).append("\t").append("<ShapeId>").append(field_1_shapeId).append("</ShapeId>\n")
.append(tab).append("\t").append("<Flags>").append(decodeFlags(field_2_flags) + " (0x" + HexDump.toHex(field_2_flags) + ")").append("</Flags>\n"); .append(tab).append("\t").append("<Flags>").append(decodeFlags(field_2_flags) + " (0x" + HexDump.toHex(field_2_flags) + ")").append("</Flags>\n");
builder.append(tab).append("</").append(getClass().getSimpleName()).append(">\n"); builder.append(tab).append("</").append(getClass().getSimpleName()).append(">\n");

View File

@ -0,0 +1,63 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.poi.hssf.dev;
import org.apache.poi.hssf.usermodel.HSSFPatriarch;
import org.apache.poi.hssf.usermodel.HSSFShape;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import java.io.FileInputStream;
import java.io.FileOutputStream;
/**
* Utility to test that POI produces readable output
* after re-saving xls files.
*
* Usage: ReSave [-dg] input.xls
* -dg initialize drawings, causes to re-build escher aggregates in all sheets
*/
public class ReSave {
public static void main(String[] args) throws Exception {
boolean initDrawing = false;
for(String arg : args) {
if(arg.equals("-dg")) initDrawing = true;
else {
System.out.print("reading " + arg + "...");
FileInputStream is = new FileInputStream(arg);
HSSFWorkbook wb = new HSSFWorkbook(is);
is.close();
System.out.println("done");
for(int i = 0; i < wb.getNumberOfSheets(); i++){
HSSFSheet sheet = wb.getSheetAt(i);
if(initDrawing) {
HSSFPatriarch dg = sheet.getDrawingPatriarch();
}
}
String outputFile = arg.replace(".xls", "-saved.xls");
System.out.print("saving to " + outputFile + "...");
FileOutputStream out = new FileOutputStream(outputFile);
wb.write(out);
out.close();
System.out.println("done");
}
}
}
}

View File

@ -26,6 +26,7 @@ import org.apache.poi.hssf.usermodel.*;
* *
* @author Glen Stampoultzis (glens at apache.org) * @author Glen Stampoultzis (glens at apache.org)
*/ */
@Deprecated
public abstract class AbstractShape public abstract class AbstractShape
{ {
/** /**

View File

@ -27,6 +27,7 @@ import org.apache.poi.hssf.usermodel.*;
* *
* @author Yegor Kozlov * @author Yegor Kozlov
*/ */
@Deprecated
public class ComboboxShape public class ComboboxShape
extends AbstractShape { extends AbstractShape {
private EscherContainerRecord spContainer; private EscherContainerRecord spContainer;

View File

@ -39,6 +39,7 @@ import org.apache.poi.hssf.usermodel.HSSFShape;
* *
* @author Yegor Kozlov * @author Yegor Kozlov
*/ */
@Deprecated
public final class CommentShape extends TextboxShape { public final class CommentShape extends TextboxShape {
private NoteRecord _note; private NoteRecord _note;

View File

@ -112,7 +112,7 @@ public class DrawingManager2
/** /**
* Finds the next available (1 based) drawing group id * Finds the next available (1 based) drawing group id
*/ */
short findNewDrawingGroupId() public short findNewDrawingGroupId()
{ {
short dgId = 1; short dgId = 1;
while ( drawingGroupExists( dgId ) ) while ( drawingGroupExists( dgId ) )
@ -147,4 +147,7 @@ public class DrawingManager2
return dgg; return dgg;
} }
public void incrementDrawingsSaved(){
dgg.setDrawingsSaved(dgg.getDrawingsSaved()+1);
}
} }

View File

@ -21,43 +21,7 @@ import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import org.apache.poi.hssf.record.BOFRecord; import org.apache.poi.hssf.record.*;
import org.apache.poi.hssf.record.CFHeaderRecord;
import org.apache.poi.hssf.record.CalcCountRecord;
import org.apache.poi.hssf.record.CalcModeRecord;
import org.apache.poi.hssf.record.CellValueRecordInterface;
import org.apache.poi.hssf.record.ColumnInfoRecord;
import org.apache.poi.hssf.record.DVALRecord;
import org.apache.poi.hssf.record.DefaultColWidthRecord;
import org.apache.poi.hssf.record.DefaultRowHeightRecord;
import org.apache.poi.hssf.record.DeltaRecord;
import org.apache.poi.hssf.record.DimensionsRecord;
import org.apache.poi.hssf.record.DrawingRecord;
import org.apache.poi.hssf.record.EOFRecord;
import org.apache.poi.hssf.record.EscherAggregate;
import org.apache.poi.hssf.record.FeatHdrRecord;
import org.apache.poi.hssf.record.FeatRecord;
import org.apache.poi.hssf.record.GridsetRecord;
import org.apache.poi.hssf.record.GutsRecord;
import org.apache.poi.hssf.record.IndexRecord;
import org.apache.poi.hssf.record.IterationRecord;
import org.apache.poi.hssf.record.MergeCellsRecord;
import org.apache.poi.hssf.record.NoteRecord;
import org.apache.poi.hssf.record.ObjRecord;
import org.apache.poi.hssf.record.PaneRecord;
import org.apache.poi.hssf.record.PrintGridlinesRecord;
import org.apache.poi.hssf.record.PrintHeadersRecord;
import org.apache.poi.hssf.record.Record;
import org.apache.poi.hssf.record.RecordBase;
import org.apache.poi.hssf.record.RefModeRecord;
import org.apache.poi.hssf.record.RowRecord;
import org.apache.poi.hssf.record.SCLRecord;
import org.apache.poi.hssf.record.SaveRecalcRecord;
import org.apache.poi.hssf.record.SelectionRecord;
import org.apache.poi.hssf.record.TextObjectRecord;
import org.apache.poi.hssf.record.UncalcedRecord;
import org.apache.poi.hssf.record.WSBoolRecord;
import org.apache.poi.hssf.record.WindowTwoRecord;
import org.apache.poi.hssf.record.aggregates.ChartSubstreamRecordAggregate; import org.apache.poi.hssf.record.aggregates.ChartSubstreamRecordAggregate;
import org.apache.poi.hssf.record.aggregates.ColumnInfoRecordsAggregate; import org.apache.poi.hssf.record.aggregates.ColumnInfoRecordsAggregate;
import org.apache.poi.hssf.record.aggregates.ConditionalFormattingTable; import org.apache.poi.hssf.record.aggregates.ConditionalFormattingTable;
@ -387,12 +351,10 @@ public final class InternalSheet {
continue; continue;
} }
if (rb instanceof EscherAggregate){ if (rb instanceof EscherAggregate){
// EscherAggregate is used only as a container for SODRAWING and OBJ record combinations /**
// So, if the container is empty, there is no reason to clone this record * this record will be removed after reading actual data from EscherAggregate
// See https://issues.apache.org/bugzilla/show_bug.cgi?id=49529 */
if (0 == rb.getRecordSize()){ rb = new DrawingRecord();
continue;
}
} }
Record rec = (Record) ((Record) rb).clone(); Record rec = (Record) ((Record) rb).clone();
clonedRecords.add(rec); clonedRecords.add(rec);
@ -1523,6 +1485,7 @@ public final class InternalSheet {
* if none currently exist * if none currently exist
* @param drawingManager The DrawingManager2 for our workbook * @param drawingManager The DrawingManager2 for our workbook
* @param createIfMissing Should one be created if missing? * @param createIfMissing Should one be created if missing?
* @return location of EscherAggregate record. if no EscherAggregate record is found return -1
*/ */
public int aggregateDrawingRecords(DrawingManager2 drawingManager, boolean createIfMissing) { public int aggregateDrawingRecords(DrawingManager2 drawingManager, boolean createIfMissing) {
int loc = findFirstRecordLocBySid(DrawingRecord.sid); int loc = findFirstRecordLocBySid(DrawingRecord.sid);
@ -1533,7 +1496,7 @@ public final class InternalSheet {
return -1; return -1;
} }
EscherAggregate aggregate = new EscherAggregate( drawingManager ); EscherAggregate aggregate = new EscherAggregate();
loc = findFirstRecordLocBySid(EscherAggregate.sid); loc = findFirstRecordLocBySid(EscherAggregate.sid);
if (loc == -1) { if (loc == -1) {
loc = findFirstRecordLocBySid( WindowTwoRecord.sid ); loc = findFirstRecordLocBySid( WindowTwoRecord.sid );
@ -1544,23 +1507,10 @@ public final class InternalSheet {
return loc; return loc;
} }
List<RecordBase> records = getRecords(); List<RecordBase> records = getRecords();
EscherAggregate r = EscherAggregate.createAggregate( records, loc, drawingManager );
int startloc = loc;
while ( loc + 1 < records.size()
&& records.get( loc ) instanceof DrawingRecord
&& (records.get( loc + 1 ) instanceof ObjRecord ||
records.get( loc + 1 ) instanceof TextObjectRecord) )
{
loc += 2;
if (records.get( loc ) instanceof NoteRecord) loc ++;
}
int endloc = loc-1; EscherAggregate.createAggregate( records, loc, drawingManager );
for(int i = 0; i < (endloc - startloc + 1); i++)
records.remove(startloc);
records.add(startloc, r);
return startloc; return loc;
} }
/** /**

View File

@ -27,6 +27,7 @@ import org.apache.poi.hssf.usermodel.*;
* *
* @author Glen Stampoultzis (glens at apache.org) * @author Glen Stampoultzis (glens at apache.org)
*/ */
@Deprecated
public class LineShape public class LineShape
extends AbstractShape extends AbstractShape
{ {

View File

@ -27,6 +27,7 @@ import org.apache.poi.hssf.usermodel.HSSFShape;
import org.apache.poi.hssf.usermodel.HSSFPolygon; import org.apache.poi.hssf.usermodel.HSSFPolygon;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
@Deprecated
public class PolygonShape public class PolygonShape
extends AbstractShape extends AbstractShape
{ {
@ -63,7 +64,7 @@ public class PolygonShape
spContainer.setRecordId( EscherContainerRecord.SP_CONTAINER ); spContainer.setRecordId( EscherContainerRecord.SP_CONTAINER );
spContainer.setOptions( (short) 0x000F ); spContainer.setOptions( (short) 0x000F );
sp.setRecordId( EscherSpRecord.RECORD_ID ); sp.setRecordId( EscherSpRecord.RECORD_ID );
sp.setOptions( (short) ( ( EscherAggregate.ST_DONUT << 4 ) | 0x2 ) ); sp.setOptions( (short) ( ( EscherAggregate.ST_NOT_PRIMATIVE << 4 ) | 0x2 ) );
sp.setShapeId( shapeId ); sp.setShapeId( shapeId );
if (hssfShape.getParent() == null) if (hssfShape.getParent() == null)
sp.setFlags( EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HASSHAPETYPE ); sp.setFlags( EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HASSHAPETYPE );

View File

@ -25,6 +25,7 @@ import org.apache.poi.hssf.record.EndSubRecord;
import org.apache.poi.hssf.usermodel.HSSFSimpleShape; import org.apache.poi.hssf.usermodel.HSSFSimpleShape;
import org.apache.poi.hssf.usermodel.HSSFShape; import org.apache.poi.hssf.usermodel.HSSFShape;
@Deprecated
public class SimpleFilledShape public class SimpleFilledShape
extends AbstractShape extends AbstractShape
{ {

View File

@ -28,6 +28,7 @@ import org.apache.poi.hssf.usermodel.*;
* *
* @author Glen Stampoultzis (glens at apache.org) * @author Glen Stampoultzis (glens at apache.org)
*/ */
@Deprecated
public class TextboxShape public class TextboxShape
extends AbstractShape extends AbstractShape
{ {

View File

@ -20,24 +20,24 @@ package org.apache.poi.hssf.record;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
/** /**
* DrawingRecord (0x00EC)<p/> * DrawingRecord (0x00EC)<p/>
*
*/ */
public final class DrawingRecord extends StandardRecord { public final class DrawingRecord extends StandardRecord {
public static final short sid = 0x00EC; public static final short sid = 0x00EC;
private static final byte[] EMPTY_BYTE_ARRAY = { }; private static final byte[] EMPTY_BYTE_ARRAY = {};
private byte[] recordData; private byte[] recordData;
private byte[] contd; private byte[] contd;
public DrawingRecord() { public DrawingRecord() {
recordData = EMPTY_BYTE_ARRAY; recordData = EMPTY_BYTE_ARRAY;
} }
public DrawingRecord(RecordInputStream in) { public DrawingRecord(RecordInputStream in) {
recordData = in.readRemainder(); recordData = in.readRemainder();
} }
@Deprecated
public void processContinueRecord(byte[] record) { public void processContinueRecord(byte[] record) {
//don't merge continue record with the drawing record, it must be serialized separately //don't merge continue record with the drawing record, it must be serialized separately
contd = record; contd = record;
@ -46,6 +46,7 @@ public final class DrawingRecord extends StandardRecord {
public void serialize(LittleEndianOutput out) { public void serialize(LittleEndianOutput out) {
out.write(recordData); out.write(recordData);
} }
protected int getDataSize() { protected int getDataSize() {
return recordData.length; return recordData.length;
} }
@ -54,32 +55,39 @@ public final class DrawingRecord extends StandardRecord {
return sid; return sid;
} }
@Deprecated
public byte[] getData() { public byte[] getData() {
if(contd != null) { return recordData;
byte[] newBuffer = new byte[ recordData.length + contd.length ]; }
System.arraycopy( recordData, 0, newBuffer, 0, recordData.length );
System.arraycopy( contd, 0, newBuffer, recordData.length, contd.length); public byte[] getRecordData(){
return newBuffer;
}
return recordData; return recordData;
} }
public void setData(byte[] thedata) { public void setData(byte[] thedata) {
if (thedata == null) { if (thedata == null) {
throw new IllegalArgumentException("data must not be null"); throw new IllegalArgumentException("data must not be null");
} }
recordData = thedata; recordData = thedata;
} }
/**
* Cloning of drawing records must be executed through HSSFPatriarch, because all id's must be changed
* @return cloned drawing records
*/
public Object clone() { public Object clone() {
DrawingRecord rec = new DrawingRecord(); DrawingRecord rec = new DrawingRecord();
rec.recordData = recordData.clone();
rec.recordData = recordData.clone(); if (contd != null) {
if (contd != null) { // TODO - this code probably never executes
// TODO - this code probably never executes rec.contd = contd.clone();
rec.contd = contd.clone(); }
}
return rec;
return rec;
} }
}
@Override
public String toString() {
return "DrawingRecord["+recordData.length+"]";
}
}

File diff suppressed because it is too large Load Diff

View File

@ -338,14 +338,14 @@ public final class RecordFactoryInputStream {
} }
if (_lastRecord instanceof DrawingGroupRecord) { if (_lastRecord instanceof DrawingGroupRecord) {
((DrawingGroupRecord) _lastRecord).processContinueRecord(contRec.getData()); ((DrawingGroupRecord) _lastRecord).processContinueRecord(contRec.getData());
return null; return null;
} }
if (_lastRecord instanceof DrawingRecord) { if (_lastRecord instanceof DrawingRecord) {
((DrawingRecord) _lastRecord).processContinueRecord(contRec.getData()); // ((DrawingRecord) _lastRecord).appendContinueRecord(contRec.getData());
return null; return contRec;
} }
if (_lastRecord instanceof UnknownRecord) { if (_lastRecord instanceof UnknownRecord) {
//Gracefully handle records that we don't know about, //Gracefully handle records that we don't know about,
//that happen to be continued //that happen to be continued
return record; return record;
} }

View File

@ -286,9 +286,9 @@ public final class PageSettingsBlock extends RecordAggregate {
pls.visitContainedRecords(rv); pls.visitContainedRecords(rv);
} }
visitIfPresent(_printSetup, rv); visitIfPresent(_printSetup, rv);
visitIfPresent(_bitmap, rv);
visitIfPresent(_printSize, rv); visitIfPresent(_printSize, rv);
visitIfPresent(_headerFooter, rv); visitIfPresent(_headerFooter, rv);
visitIfPresent(_bitmap, rv);
} }
private static void visitIfPresent(Record r, RecordVisitor rv) { private static void visitIfPresent(Record r, RecordVisitor rv) {
if (r != null) { if (r != null) {

View File

@ -349,6 +349,7 @@ public class EscherGraphics
shape.setLineStyle(HSSFShape.LINESTYLE_NONE); shape.setLineStyle(HSSFShape.LINESTYLE_NONE);
shape.setFillColor(foreground.getRed(), foreground.getGreen(), foreground.getBlue()); shape.setFillColor(foreground.getRed(), foreground.getGreen(), foreground.getBlue());
shape.setLineStyleColor(foreground.getRed(), foreground.getGreen(), foreground.getBlue()); shape.setLineStyleColor(foreground.getRed(), foreground.getGreen(), foreground.getBlue());
shape.setNoFill(false);
} }
/** /**

View File

@ -18,40 +18,96 @@
package org.apache.poi.hssf.usermodel; package org.apache.poi.hssf.usermodel;
import org.apache.poi.ddf.EscherChildAnchorRecord;
import org.apache.poi.ddf.EscherClientAnchorRecord;
import org.apache.poi.ddf.EscherContainerRecord;
import org.apache.poi.ddf.EscherRecord;
/** /**
* An anchor is what specifics the position of a shape within a client object * An anchor is what specifics the position of a shape within a client object
* or within another containing shape. * or within another containing shape.
* *
* @author Glen Stampoultzis (glens at apache.org) * @author Glen Stampoultzis (glens at apache.org)
*/ */
public abstract class HSSFAnchor public abstract class HSSFAnchor {
{
int dx1;
int dy1;
int dx2;
int dy2;
public HSSFAnchor() protected boolean _isHorizontallyFlipped = false;
{ protected boolean _isVerticallyFlipped = false;
public HSSFAnchor() {
createEscherAnchor();
} }
public HSSFAnchor( int dx1, int dy1, int dx2, int dy2 ) public HSSFAnchor(int dx1, int dy1, int dx2, int dy2) {
{ createEscherAnchor();
this.dx1 = dx1; setDx1(dx1);
this.dy1 = dy1; setDy1(dy1);
this.dx2 = dx2; setDx2(dx2);
this.dy2 = dy2; setDy2(dy2);
} }
public int getDx1(){ return dx1; } public static HSSFAnchor createAnchorFromEscher(EscherContainerRecord container){
public void setDx1( int dx1 ){ this.dx1 = dx1; } if (null != container.getChildById(EscherChildAnchorRecord.RECORD_ID)){
public int getDy1(){ return dy1; } return new HSSFChildAnchor((EscherChildAnchorRecord) container.getChildById(EscherChildAnchorRecord.RECORD_ID));
public void setDy1( int dy1 ){ this.dy1 = dy1; } } else {
public int getDy2(){ return dy2; } if (null != container.getChildById(EscherClientAnchorRecord.RECORD_ID)){
public void setDy2( int dy2 ){ this.dy2 = dy2; } return new HSSFClientAnchor((EscherClientAnchorRecord) container.getChildById(EscherClientAnchorRecord.RECORD_ID));
public int getDx2(){ return dx2; } }
public void setDx2( int dx2 ){ this.dx2 = dx2; } return null;
}
}
/**
* @return x coordinate of the left up corner
*/
public abstract int getDx1();
/**
* @param dx1 x coordinate of the left up corner
*/
public abstract void setDx1(int dx1);
/**
* @return y coordinate of the left up corner
*/
public abstract int getDy1();
/**
* @param dy1 y coordinate of the left up corner
*/
public abstract void setDy1(int dy1);
/**
* @return y coordinate of the right down corner
*/
public abstract int getDy2();
/**
* @param dy2 y coordinate of the right down corner
*/
public abstract void setDy2(int dy2);
/**
* @return x coordinate of the right down corner
*/
public abstract int getDx2();
/**
* @param dx2 x coordinate of the right down corner
*/
public abstract void setDx2(int dx2);
/**
* @return whether this shape is horizontally flipped
*/
public abstract boolean isHorizontallyFlipped(); public abstract boolean isHorizontallyFlipped();
/**
* @return whether this shape is vertically flipped
*/
public abstract boolean isVerticallyFlipped(); public abstract boolean isVerticallyFlipped();
protected abstract EscherRecord getEscherAnchor();
protected abstract void createEscherAnchor();
} }

View File

@ -1021,7 +1021,7 @@ public class HSSFCell implements Cell {
*/ */
public HSSFComment getCellComment(){ public HSSFComment getCellComment(){
if (_comment == null) { if (_comment == null) {
_comment = findCellComment(_sheet.getSheet(), _record.getRow(), _record.getColumn()); _comment = _sheet.findCellComment(_record.getRow(), _record.getColumn());
} }
return _comment; return _comment;
} }
@ -1033,98 +1033,12 @@ public class HSSFCell implements Cell {
* all comments after performing this action! * all comments after performing this action!
*/ */
public void removeCellComment() { public void removeCellComment() {
HSSFComment comment = findCellComment(_sheet.getSheet(), _record.getRow(), _record.getColumn()); HSSFComment comment = _sheet.findCellComment(_record.getRow(), _record.getColumn());
_comment = null; _comment = null;
if (null == comment){
if(comment == null) {
// Nothing to do
return; return;
} }
_sheet.getDrawingPatriarch().removeShape(comment);
// Zap the underlying NoteRecord
List<RecordBase> sheetRecords = _sheet.getSheet().getRecords();
sheetRecords.remove(comment.getNoteRecord());
// If we have a TextObjectRecord, is should
// be proceeed by:
// MSODRAWING with container
// OBJ
// MSODRAWING with EscherTextboxRecord
if(comment.getTextObjectRecord() != null) {
TextObjectRecord txo = comment.getTextObjectRecord();
int txoAt = sheetRecords.indexOf(txo);
if(sheetRecords.get(txoAt-3) instanceof DrawingRecord &&
sheetRecords.get(txoAt-2) instanceof ObjRecord &&
sheetRecords.get(txoAt-1) instanceof DrawingRecord) {
// Zap these, in reverse order
sheetRecords.remove(txoAt-1);
sheetRecords.remove(txoAt-2);
sheetRecords.remove(txoAt-3);
} else {
throw new IllegalStateException("Found the wrong records before the TextObjectRecord, can't remove comment");
}
// Now remove the text record
sheetRecords.remove(txo);
}
}
/**
* Cell comment finder.
* Returns cell comment for the specified sheet, row and column.
*
* @return cell comment or <code>null</code> if not found
*/
protected static HSSFComment findCellComment(InternalSheet sheet, int row, int column) {
// TODO - optimise this code by searching backwards, find NoteRecord first, quit if not found. Find one TXO by id
HSSFComment comment = null;
Map<Integer, TextObjectRecord> noteTxo =
new HashMap<Integer, TextObjectRecord>();
int i = 0;
for (Iterator<RecordBase> it = sheet.getRecords().iterator(); it.hasNext();) {
RecordBase rec = it.next();
if (rec instanceof NoteRecord) {
NoteRecord note = (NoteRecord) rec;
if (note.getRow() == row && note.getColumn() == column) {
if(i < noteTxo.size()) {
TextObjectRecord txo = noteTxo.get(note.getShapeId());
if(txo != null){
comment = new HSSFComment(note, txo);
comment.setRow(note.getRow());
comment.setColumn(note.getColumn());
comment.setAuthor(note.getAuthor());
comment.setVisible(note.getFlags() == NoteRecord.NOTE_VISIBLE);
comment.setString(txo.getStr());
} else{
log.log(POILogger.WARN, "Failed to match NoteRecord and TextObjectRecord, row: " + row + ", column: " + column);
}
} else {
log.log(POILogger.WARN, "Failed to match NoteRecord and TextObjectRecord, row: " + row + ", column: " + column);
}
break;
}
i++;
} else if (rec instanceof ObjRecord) {
ObjRecord obj = (ObjRecord) rec;
SubRecord sub = obj.getSubRecords().get(0);
if (sub instanceof CommonObjectDataSubRecord) {
CommonObjectDataSubRecord cmo = (CommonObjectDataSubRecord) sub;
if (cmo.getObjectType() == CommonObjectDataSubRecord.OBJECT_TYPE_COMMENT) {
//map ObjectId and corresponding TextObjectRecord,
//it will be used to match NoteRecord and TextObjectRecord
while (it.hasNext()) {
rec = it.next();
if (rec instanceof TextObjectRecord) {
noteTxo.put(cmo.getObjectId(), (TextObjectRecord) rec);
break;
}
}
}
}
}
}
return comment;
} }
/** /**

View File

@ -18,31 +18,126 @@
package org.apache.poi.hssf.usermodel; package org.apache.poi.hssf.usermodel;
import org.apache.poi.ddf.EscherChildAnchorRecord;
import org.apache.poi.ddf.EscherRecord;
public final class HSSFChildAnchor extends HSSFAnchor { public final class HSSFChildAnchor extends HSSFAnchor {
public HSSFChildAnchor()
{ private EscherChildAnchorRecord _escherChildAnchor;
/**
* create anchor from existing file
* @param escherChildAnchorRecord
*/
public HSSFChildAnchor(EscherChildAnchorRecord escherChildAnchorRecord) {
this._escherChildAnchor = escherChildAnchorRecord;
} }
public HSSFChildAnchor( int dx1, int dy1, int dx2, int dy2 ) public HSSFChildAnchor() {
{ _escherChildAnchor = new EscherChildAnchorRecord();
super( dx1, dy1, dx2, dy2 );
} }
public void setAnchor(int dx1, int dy1, int dx2, int dy2) /**
{ * create anchor from scratch
this.dx1 = dx1; * @param dx1 x coordinate of the left up corner
this.dy1 = dy1; * @param dy1 y coordinate of the left up corner
this.dx2 = dx2; * @param dx2 x coordinate of the right down corner
this.dy2 = dy2; * @param dy2 y coordinate of the right down corner
*/
public HSSFChildAnchor(int dx1, int dy1, int dx2, int dy2) {
super(Math.min(dx1, dx2), Math.min(dy1, dy2), Math.max(dx1, dx2), Math.max(dy1, dy2));
if (dx1 > dx2){
_isHorizontallyFlipped = true;
}
if (dy1 > dy2){
_isVerticallyFlipped = true;
}
} }
public boolean isHorizontallyFlipped() @Override
{ public int getDx1() {
return dx1 > dx2; return _escherChildAnchor.getDx1();
} }
public boolean isVerticallyFlipped() @Override
{ public void setDx1(int dx1) {
return dy1 > dy2; _escherChildAnchor.setDx1(dx1);
}
@Override
public int getDy1() {
return _escherChildAnchor.getDy1();
}
@Override
public void setDy1(int dy1) {
_escherChildAnchor.setDy1(dy1);
}
@Override
public int getDy2() {
return _escherChildAnchor.getDy2();
}
@Override
public void setDy2(int dy2) {
_escherChildAnchor.setDy2(dy2);
}
@Override
public int getDx2() {
return _escherChildAnchor.getDx2();
}
@Override
public void setDx2(int dx2) {
_escherChildAnchor.setDx2(dx2);
}
/**
* @param dx1 x coordinate of the left up corner
* @param dy1 y coordinate of the left up corner
* @param dx2 x coordinate of the right down corner
* @param dy2 y coordinate of the right down corner
*/
public void setAnchor(int dx1, int dy1, int dx2, int dy2) {
setDx1(Math.min(dx1, dx2));
setDy1(Math.min(dy1, dy2));
setDx2(Math.max(dx1, dx2));
setDy2(Math.max(dy1, dy2));
}
public boolean isHorizontallyFlipped() {
return _isHorizontallyFlipped;
}
public boolean isVerticallyFlipped() {
return _isVerticallyFlipped;
}
@Override
protected EscherRecord getEscherAnchor() {
return _escherChildAnchor;
}
@Override
protected void createEscherAnchor() {
_escherChildAnchor = new EscherChildAnchorRecord();
}
@Override
public boolean equals(Object obj) {
if (obj == null)
return false;
if (obj == this)
return true;
if (obj.getClass() != getClass())
return false;
HSSFChildAnchor anchor = (HSSFChildAnchor) obj;
return anchor.getDx1() == getDx1() && anchor.getDx2() == getDx2() && anchor.getDy1() == getDy1()
&& anchor.getDy2() == getDy2();
} }
} }

View File

@ -17,9 +17,10 @@
package org.apache.poi.hssf.usermodel; package org.apache.poi.hssf.usermodel;
import org.apache.poi.ddf.EscherClientAnchorRecord;
import org.apache.poi.ddf.EscherRecord;
import org.apache.poi.ss.usermodel.ClientAnchor; import org.apache.poi.ss.usermodel.ClientAnchor;
/** /**
* A client anchor is attached to an excel worksheet. It anchors against a * A client anchor is attached to an excel worksheet. It anchors against a
* top-left and buttom-right cell. * top-left and buttom-right cell.
@ -27,35 +28,34 @@ import org.apache.poi.ss.usermodel.ClientAnchor;
* @author Glen Stampoultzis (glens at apache.org) * @author Glen Stampoultzis (glens at apache.org)
*/ */
public final class HSSFClientAnchor extends HSSFAnchor implements ClientAnchor { public final class HSSFClientAnchor extends HSSFAnchor implements ClientAnchor {
short col1;
int row1; private EscherClientAnchorRecord _escherClientAnchor;
short col2;
int row2; public HSSFClientAnchor(EscherClientAnchorRecord escherClientAnchorRecord) {
int anchorType; this._escherClientAnchor = escherClientAnchorRecord;
}
/** /**
* Creates a new client anchor and defaults all the anchor positions to 0. * Creates a new client anchor and defaults all the anchor positions to 0.
*/ */
public HSSFClientAnchor() public HSSFClientAnchor() {
{
} }
/** /**
* Creates a new client anchor and sets the top-left and bottom-right * Creates a new client anchor and sets the top-left and bottom-right
* coordinates of the anchor. * coordinates of the anchor.
* *
* @param dx1 the x coordinate within the first cell. * @param dx1 the x coordinate within the first cell.
* @param dy1 the y coordinate within the first cell. * @param dy1 the y coordinate within the first cell.
* @param dx2 the x coordinate within the second cell. * @param dx2 the x coordinate within the second cell.
* @param dy2 the y coordinate within the second cell. * @param dy2 the y coordinate within the second cell.
* @param col1 the column (0 based) of the first cell. * @param col1 the column (0 based) of the first cell.
* @param row1 the row (0 based) of the first cell. * @param row1 the row (0 based) of the first cell.
* @param col2 the column (0 based) of the second cell. * @param col2 the column (0 based) of the second cell.
* @param row2 the row (0 based) of the second cell. * @param row2 the row (0 based) of the second cell.
*/ */
public HSSFClientAnchor( int dx1, int dy1, int dx2, int dy2, short col1, int row1, short col2, int row2 ) public HSSFClientAnchor(int dx1, int dy1, int dx2, int dy2, short col1, int row1, short col2, int row2) {
{ super(dx1, dy1, dx2, dy2);
super( dx1, dy1, dx2, dy2 );
checkRange(dx1, 0, 1023, "dx1"); checkRange(dx1, 0, 1023, "dx1");
checkRange(dx2, 0, 1023, "dx2"); checkRange(dx2, 0, 1023, "dx2");
@ -66,35 +66,37 @@ public final class HSSFClientAnchor extends HSSFAnchor implements ClientAnchor {
checkRange(row1, 0, 255 * 256, "row1"); checkRange(row1, 0, 255 * 256, "row1");
checkRange(row2, 0, 255 * 256, "row2"); checkRange(row2, 0, 255 * 256, "row2");
this.col1 = col1; setCol1((short) Math.min(col1, col2));
this.row1 = row1; setCol2((short) Math.max(col1, col2));
this.col2 = col2; setRow1((short) Math.min(row1, row2));
this.row2 = row2; setRow2((short) Math.max(row1, row2));
if (col1 > col2){
_isHorizontallyFlipped = true;
}
if (row1 > row2){
_isVerticallyFlipped = true;
}
} }
/** /**
* Calculates the height of a client anchor in points. * Calculates the height of a client anchor in points.
* *
* @param sheet the sheet the anchor will be attached to * @param sheet the sheet the anchor will be attached to
* @return the shape height. * @return the shape height.
*/ */
public float getAnchorHeightInPoints(HSSFSheet sheet ) public float getAnchorHeightInPoints(HSSFSheet sheet) {
{
int y1 = getDy1(); int y1 = getDy1();
int y2 = getDy2(); int y2 = getDy2();
int row1 = Math.min( getRow1(), getRow2() ); int row1 = Math.min(getRow1(), getRow2());
int row2 = Math.max( getRow1(), getRow2() ); int row2 = Math.max(getRow1(), getRow2());
float points = 0; float points = 0;
if (row1 == row2) if (row1 == row2) {
{
points = ((y2 - y1) / 256.0f) * getRowHeightInPoints(sheet, row2); points = ((y2 - y1) / 256.0f) * getRowHeightInPoints(sheet, row2);
} } else {
else
{
points += ((256.0f - y1) / 256.0f) * getRowHeightInPoints(sheet, row1); points += ((256.0f - y1) / 256.0f) * getRowHeightInPoints(sheet, row1);
for (int i = row1 + 1; i < row2; i++) for (int i = row1 + 1; i < row2; i++) {
{
points += getRowHeightInPoints(sheet, i); points += getRowHeightInPoints(sheet, i);
} }
points += (y2 / 256.0f) * getRowHeightInPoints(sheet, row2); points += (y2 / 256.0f) * getRowHeightInPoints(sheet, row2);
@ -103,8 +105,7 @@ public final class HSSFClientAnchor extends HSSFAnchor implements ClientAnchor {
return points; return points;
} }
private float getRowHeightInPoints(HSSFSheet sheet, int rowNum) private float getRowHeightInPoints(HSSFSheet sheet, int rowNum) {
{
HSSFRow row = sheet.getRow(rowNum); HSSFRow row = sheet.getRow(rowNum);
if (row == null) { if (row == null) {
return sheet.getDefaultRowHeightInPoints(); return sheet.getDefaultRowHeightInPoints();
@ -112,55 +113,78 @@ public final class HSSFClientAnchor extends HSSFAnchor implements ClientAnchor {
return row.getHeightInPoints(); return row.getHeightInPoints();
} }
public short getCol1() /**
{ * @return the column(0 based) of the first cell.
return col1; */
public short getCol1() {
return _escherClientAnchor.getCol1();
} }
public void setCol1( short col1 ) /**
{ * @param col1 the column(0 based) of the first cell.
*/
public void setCol1(short col1) {
checkRange(col1, 0, 255, "col1"); checkRange(col1, 0, 255, "col1");
this.col1 = col1; _escherClientAnchor.setCol1(col1);
}
public void setCol1( int col1 ){
setCol1((short)col1);
} }
public short getCol2() /**
{ * @param col1 0-based column of the first cell.
return col2; */
public void setCol1(int col1) {
setCol1((short) col1);
} }
public void setCol2( short col2 ) /**
{ * @return the column(0 based) of the first cell.
*/
public short getCol2() {
return _escherClientAnchor.getCol2();
}
/**
* @param col2 the column(0 based) of the second cell.
*/
public void setCol2(short col2) {
checkRange(col2, 0, 255, "col2"); checkRange(col2, 0, 255, "col2");
this.col2 = col2; _escherClientAnchor.setCol2(col2);
} }
public void setCol2( int col2 ){ /**
setCol2((short)col2); * @param col2 the column(0 based) of the second cell.
*/
public void setCol2(int col2) {
setCol2((short) col2);
} }
public int getRow1() /**
{ * @return the row(0 based) of the first cell.
return row1; */
public int getRow1() {
return _escherClientAnchor.getRow1();
} }
public void setRow1( int row1 ) /**
{ * @param row1 0-based row of the first cell.
*/
public void setRow1(int row1) {
checkRange(row1, 0, 256 * 256, "row1"); checkRange(row1, 0, 256 * 256, "row1");
this.row1 = row1; _escherClientAnchor.setRow1(Integer.valueOf(row1).shortValue());
} }
public int getRow2() /**
{ * @return the row(0 based) of the second cell.
return row2; */
public int getRow2() {
return _escherClientAnchor.getRow2();
} }
public void setRow2( int row2 ) /**
{ * @return the row(0 based) of the second cell.
*/
public void setRow2(int row2) {
checkRange(row2, 0, 256 * 256, "row2"); checkRange(row2, 0, 256 * 256, "row2");
this.row2 = row2; _escherClientAnchor.setRow2(Integer.valueOf(row2).shortValue());
} }
/** /**
@ -171,79 +195,124 @@ public final class HSSFClientAnchor extends HSSFAnchor implements ClientAnchor {
* @param y1 the y coordinate within the first cell. * @param y1 the y coordinate within the first cell.
* @param x2 the x coordinate within the second cell. * @param x2 the x coordinate within the second cell.
* @param y2 the y coordinate within the second cell. * @param y2 the y coordinate within the second cell.
* @param col1 the column (0 based) of the first cell. * @param col1 the column (0 based) of the first cell.
* @param row1 the row (0 based) of the first cell. * @param row1 the row (0 based) of the first cell.
* @param col2 the column (0 based) of the second cell. * @param col2 the column (0 based) of the second cell.
* @param row2 the row (0 based) of the second cell. * @param row2 the row (0 based) of the second cell.
*/ */
public void setAnchor( short col1, int row1, int x1, int y1, short col2, int row2, int x2, int y2 ) public void setAnchor(short col1, int row1, int x1, int y1, short col2, int row2, int x2, int y2) {
{ checkRange(getDx1(), 0, 1023, "dx1");
checkRange(dx1, 0, 1023, "dx1"); checkRange(getDx2(), 0, 1023, "dx2");
checkRange(dx2, 0, 1023, "dx2"); checkRange(getDy1(), 0, 255, "dy1");
checkRange(dy1, 0, 255, "dy1"); checkRange(getDy2(), 0, 255, "dy2");
checkRange(dy2, 0, 255, "dy2"); checkRange(getCol1(), 0, 255, "col1");
checkRange(col1, 0, 255, "col1"); checkRange(getCol2(), 0, 255, "col2");
checkRange(col2, 0, 255, "col2"); checkRange(getRow1(), 0, 255 * 256, "row1");
checkRange(row1, 0, 255 * 256, "row1"); checkRange(getRow2(), 0, 255 * 256, "row2");
checkRange(row2, 0, 255 * 256, "row2");
this.col1 = col1; setCol1(col1);
this.row1 = row1; setRow1(row1);
this.dx1 = x1; setDx1(x1);
this.dy1 = y1; setDy1(y1);
this.col2 = col2; setCol2(col2);
this.row2 = row2; setRow2(row2);
this.dx2 = x2; setDx2(x2);
this.dy2 = y2; setDy2(y2);
} }
/** public boolean isHorizontallyFlipped() {
* @return true if the anchor goes from right to left. return _isHorizontallyFlipped;
*/
public boolean isHorizontallyFlipped()
{
if (col1 == col2) {
return dx1 > dx2;
}
return col1 > col2;
} }
/** public boolean isVerticallyFlipped() {
* @return true if the anchor goes from bottom to top. return _isVerticallyFlipped;
*/ }
public boolean isVerticallyFlipped()
{ @Override
if (row1 == row2) { protected EscherRecord getEscherAnchor() {
return dy1 > dy2; return _escherClientAnchor;
} }
return row1 > row2;
@Override
protected void createEscherAnchor() {
_escherClientAnchor = new EscherClientAnchorRecord();
} }
/** /**
* Gets the anchor type * Gets the anchor type
* <p> * <p/>
* 0 = Move and size with Cells, 2 = Move but don't size with cells, 3 = Don't move or size with cells. * 0 = Move and size with Cells, 2 = Move but don't size with cells, 3 = Don't move or size with cells.
*/ */
public int getAnchorType() public int getAnchorType() {
{ return _escherClientAnchor.getFlag();
return anchorType;
} }
/** /**
* Sets the anchor type * Sets the anchor type
* <p> * <p/>
* 0 = Move and size with Cells, 2 = Move but don't size with cells, 3 = Don't move or size with cells. * 0 = Move and size with Cells, 2 = Move but don't size with cells, 3 = Don't move or size with cells.
*/ */
public void setAnchorType( int anchorType ) public void setAnchorType(int anchorType) {
{ _escherClientAnchor.setFlag(Integer.valueOf(anchorType).shortValue());
this.anchorType = anchorType;
} }
private void checkRange( int value, int minRange, int maxRange, String varName ) private void checkRange(int value, int minRange, int maxRange, String varName) {
{
if (value < minRange || value > maxRange) if (value < minRange || value > maxRange)
throw new IllegalArgumentException(varName + " must be between " + minRange + " and " + maxRange); throw new IllegalArgumentException(varName + " must be between " + minRange + " and " + maxRange);
} }
@Override
public boolean equals(Object obj) {
if (obj == null)
return false;
if (obj == this)
return true;
if (obj.getClass() != getClass())
return false;
HSSFClientAnchor anchor = (HSSFClientAnchor) obj;
return anchor.getCol1() == getCol1() && anchor.getCol2() == getCol2() && anchor.getDx1() == getDx1()
&& anchor.getDx2() == getDx2() && anchor.getDy1() == getDy1() && anchor.getDy2() == getDy2()
&& anchor.getRow1() == getRow1() && anchor.getRow2() == getRow2() && anchor.getAnchorType() == getAnchorType();
}
@Override
public int getDx1() {
return _escherClientAnchor.getDx1();
}
@Override
public void setDx1(int dx1) {
_escherClientAnchor.setDx1(Integer.valueOf(dx1).shortValue());
}
@Override
public int getDy1() {
return _escherClientAnchor.getDy1();
}
@Override
public void setDy1(int dy1) {
_escherClientAnchor.setDy1(Integer.valueOf(dy1).shortValue());
}
@Override
public int getDy2() {
return _escherClientAnchor.getDy2();
}
@Override
public void setDy2(int dy2) {
_escherClientAnchor.setDy2(Integer.valueOf(dy2).shortValue());
}
@Override
public int getDx2() {
return _escherClientAnchor.getDx2();
}
@Override
public void setDx2(int dx2) {
_escherClientAnchor.setDx2(Integer.valueOf(dx2).shortValue());
}
} }

View File

@ -0,0 +1,101 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.usermodel;
import org.apache.poi.ddf.*;
import org.apache.poi.hssf.record.*;
/**
* @author Evgeniy Berlog
* @date 12.07.12
*/
public class HSSFCombobox extends HSSFSimpleShape {
public HSSFCombobox(EscherContainerRecord spContainer, ObjRecord objRecord) {
super(spContainer, objRecord);
}
public HSSFCombobox(HSSFShape parent, HSSFAnchor anchor) {
super(parent, anchor);
super.setShapeType(OBJECT_TYPE_COMBO_BOX);
CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) getObjRecord().getSubRecords().get(0);
cod.setObjectType(CommonObjectDataSubRecord.OBJECT_TYPE_COMBO_BOX);
}
@Override
protected TextObjectRecord createTextObjRecord() {
return null;
}
@Override
protected EscherContainerRecord createSpContainer() {
EscherContainerRecord spContainer = new EscherContainerRecord();
EscherSpRecord sp = new EscherSpRecord();
EscherOptRecord opt = new EscherOptRecord();
EscherClientDataRecord clientData = new EscherClientDataRecord();
spContainer.setRecordId(EscherContainerRecord.SP_CONTAINER);
spContainer.setOptions((short) 0x000F);
sp.setRecordId(EscherSpRecord.RECORD_ID);
sp.setOptions((short) ((EscherAggregate.ST_HOSTCONTROL << 4) | 0x2));
sp.setFlags(EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HASSHAPETYPE);
opt.setRecordId(EscherOptRecord.RECORD_ID);
opt.addEscherProperty(new EscherBoolProperty(EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 17039620));
opt.addEscherProperty(new EscherBoolProperty(EscherProperties.TEXT__SIZE_TEXT_TO_FIT_SHAPE, 0x00080008));
opt.addEscherProperty(new EscherBoolProperty(EscherProperties.LINESTYLE__NOLINEDRAWDASH, 0x00080000));
opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.GROUPSHAPE__PRINT, 0x00020000));
HSSFClientAnchor userAnchor = (HSSFClientAnchor) getAnchor();
userAnchor.setAnchorType(1);
EscherRecord anchor = userAnchor.getEscherAnchor();
clientData.setRecordId(EscherClientDataRecord.RECORD_ID);
clientData.setOptions((short) 0x0000);
spContainer.addChildRecord(sp);
spContainer.addChildRecord(opt);
spContainer.addChildRecord(anchor);
spContainer.addChildRecord(clientData);
return spContainer;
}
@Override
protected ObjRecord createObjRecord() {
ObjRecord obj = new ObjRecord();
CommonObjectDataSubRecord c = new CommonObjectDataSubRecord();
c.setObjectType(HSSFSimpleShape.OBJECT_TYPE_COMBO_BOX);
c.setLocked(true);
c.setPrintable(false);
c.setAutofill(true);
c.setAutoline(false);
FtCblsSubRecord f = new FtCblsSubRecord();
LbsDataSubRecord l = LbsDataSubRecord.newAutoFilterInstance();
EndSubRecord e = new EndSubRecord();
obj.addSubRecord(c);
obj.addSubRecord(f);
obj.addSubRecord(l);
obj.addSubRecord(e);
return obj;
}
@Override
public void setShapeType(int shapeType) {
throw new IllegalStateException("Shape type can not be changed in "+this.getClass().getSimpleName());
}
}

View File

@ -16,10 +16,9 @@
==================================================================== */ ==================================================================== */
package org.apache.poi.hssf.usermodel; package org.apache.poi.hssf.usermodel;
import org.apache.poi.hssf.record.NoteRecord; import org.apache.poi.ddf.*;
import org.apache.poi.hssf.record.TextObjectRecord; import org.apache.poi.hssf.record.*;
import org.apache.poi.ss.usermodel.Comment; import org.apache.poi.ss.usermodel.Comment;
import org.apache.poi.ss.usermodel.RichTextString;
/** /**
* Represents a cell comment - a sticky note associated with a cell. * Represents a cell comment - a sticky note associated with a cell.
@ -28,59 +27,108 @@ import org.apache.poi.ss.usermodel.RichTextString;
*/ */
public class HSSFComment extends HSSFTextbox implements Comment { public class HSSFComment extends HSSFTextbox implements Comment {
/* private final static int FILL_TYPE_SOLID = 0;
* TODO - make HSSFComment more consistent when created vs read from file. private final static int FILL_TYPE_PICTURE = 3;
* Currently HSSFComment has two main forms (corresponding to the two constructors). There
* are certain operations that only work on comment objects in one of the forms (e.g. deleting /*
* comments). * TODO - make HSSFComment more consistent when created vs read from file.
* POI is also deficient in its management of RowRecord fields firstCol and lastCol. Those * Currently HSSFComment has two main forms (corresponding to the two constructors). There
* fields are supposed to take comments into account, but POI does not do this yet (feb 2009). * are certain operations that only work on comment objects in one of the forms (e.g. deleting
* It seems like HSSFRow should manage a collection of local HSSFComments * comments).
*/ * POI is also deficient in its management of RowRecord fields firstCol and lastCol. Those
* fields are supposed to take comments into account, but POI does not do this yet (feb 2009).
private boolean _visible; * It seems like HSSFRow should manage a collection of local HSSFComments
private int _row; */
private int _col;
private String _author;
private NoteRecord _note; private NoteRecord _note;
private TextObjectRecord _txo;
public HSSFComment(EscherContainerRecord spContainer, ObjRecord objRecord, TextObjectRecord textObjectRecord, NoteRecord _note) {
super(spContainer, objRecord, textObjectRecord);
this._note = _note;
}
/** /**
* Construct a new comment with the given parent and anchor. * Construct a new comment with the given parent and anchor.
* *
* @param parent * @param parent
* @param anchor defines position of this anchor in the sheet * @param anchor defines position of this anchor in the sheet
*/ */
public HSSFComment(HSSFShape parent, HSSFAnchor anchor) { public HSSFComment(HSSFShape parent, HSSFAnchor anchor) {
super(parent, anchor); super(parent, anchor);
setShapeType(OBJECT_TYPE_COMMENT); _note = createNoteRecord();
//default color for comments //default color for comments
_fillColor = 0x08000050; setFillColor(0x08000050);
//by default comments are hidden //by default comments are hidden
_visible = false; setVisible(false);
setAuthor("");
_author = ""; CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) getObjRecord().getSubRecords().get(0);
cod.setObjectType(CommonObjectDataSubRecord.OBJECT_TYPE_COMMENT);
} }
protected HSSFComment(NoteRecord note, TextObjectRecord txo) { protected HSSFComment(NoteRecord note, TextObjectRecord txo) {
this((HSSFShape) null, (HSSFAnchor) null); this(null, new HSSFClientAnchor());
_txo = txo;
_note = note; _note = note;
} }
@Override
void afterInsert(HSSFPatriarch patriarch) {
super.afterInsert(patriarch);
patriarch._getBoundAggregate().addTailRecord(getNoteRecord());
}
@Override
protected EscherContainerRecord createSpContainer() {
EscherContainerRecord spContainer = super.createSpContainer();
EscherOptRecord opt = spContainer.getChildById(EscherOptRecord.RECORD_ID);
opt.removeEscherProperty(EscherProperties.TEXT__TEXTLEFT);
opt.removeEscherProperty(EscherProperties.TEXT__TEXTRIGHT);
opt.removeEscherProperty(EscherProperties.TEXT__TEXTTOP);
opt.removeEscherProperty(EscherProperties.TEXT__TEXTBOTTOM);
opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.GROUPSHAPE__PRINT, false, false, 655362));
return spContainer;
}
@Override
protected ObjRecord createObjRecord() {
ObjRecord obj = new ObjRecord();
CommonObjectDataSubRecord c = new CommonObjectDataSubRecord();
c.setObjectType(OBJECT_TYPE_COMMENT);
c.setLocked(true);
c.setPrintable(true);
c.setAutofill(false);
c.setAutoline(true);
NoteStructureSubRecord u = new NoteStructureSubRecord();
EndSubRecord e = new EndSubRecord();
obj.addSubRecord(c);
obj.addSubRecord(u);
obj.addSubRecord(e);
return obj;
}
private NoteRecord createNoteRecord(){
NoteRecord note = new NoteRecord();
note.setFlags(NoteRecord.NOTE_HIDDEN);
note.setAuthor("");
return note;
}
@Override
void setShapeId(int shapeId) {
super.setShapeId(shapeId);
CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) getObjRecord().getSubRecords().get(0);
cod.setObjectId((short) (shapeId % 1024));
_note.setShapeId(shapeId % 1024);
}
/** /**
* Returns whether this comment is visible. * Returns whether this comment is visible.
* *
* @param visible <code>true</code> if the comment is visible, <code>false</code> otherwise * @param visible <code>true</code> if the comment is visible, <code>false</code> otherwise
*/ */
public void setVisible(boolean visible){ public void setVisible(boolean visible) {
if(_note != null) { _note.setFlags(visible ? NoteRecord.NOTE_VISIBLE : NoteRecord.NOTE_HIDDEN);
_note.setFlags(visible ? NoteRecord.NOTE_VISIBLE : NoteRecord.NOTE_HIDDEN);
}
_visible = visible;
} }
/** /**
@ -89,7 +137,7 @@ public class HSSFComment extends HSSFTextbox implements Comment {
* @return <code>true</code> if the comment is visible, <code>false</code> otherwise * @return <code>true</code> if the comment is visible, <code>false</code> otherwise
*/ */
public boolean isVisible() { public boolean isVisible() {
return _visible; return _note.getFlags() == NoteRecord.NOTE_VISIBLE;
} }
/** /**
@ -98,7 +146,7 @@ public class HSSFComment extends HSSFTextbox implements Comment {
* @return the 0-based row of the cell that contains the comment * @return the 0-based row of the cell that contains the comment
*/ */
public int getRow() { public int getRow() {
return _row; return _note.getRow();
} }
/** /**
@ -107,10 +155,7 @@ public class HSSFComment extends HSSFTextbox implements Comment {
* @param row the 0-based row of the cell that contains the comment * @param row the 0-based row of the cell that contains the comment
*/ */
public void setRow(int row) { public void setRow(int row) {
if(_note != null) { _note.setRow(row);
_note.setRow(row);
}
_row = row;
} }
/** /**
@ -118,8 +163,8 @@ public class HSSFComment extends HSSFTextbox implements Comment {
* *
* @return the 0-based column of the cell that contains the comment * @return the 0-based column of the cell that contains the comment
*/ */
public int getColumn(){ public int getColumn() {
return _col; return _note.getColumn();
} }
/** /**
@ -128,17 +173,15 @@ public class HSSFComment extends HSSFTextbox implements Comment {
* @param col the 0-based column of the cell that contains the comment * @param col the 0-based column of the cell that contains the comment
*/ */
public void setColumn(int col) { public void setColumn(int col) {
if(_note != null) { _note.setColumn(col);
_note.setColumn(col);
}
_col = col;
} }
/** /**
* @deprecated (Nov 2009) use {@link HSSFComment#setColumn(int)} } * @deprecated (Nov 2009) use {@link HSSFComment#setColumn(int)} }
*/ */
@Deprecated @Deprecated
public void setColumn(short col) { public void setColumn(short col) {
setColumn((int)col); setColumn((int) col);
} }
/** /**
@ -147,7 +190,7 @@ public class HSSFComment extends HSSFTextbox implements Comment {
* @return the name of the original author of the comment * @return the name of the original author of the comment
*/ */
public String getAuthor() { public String getAuthor() {
return _author; return _note.getAuthor();
} }
/** /**
@ -155,37 +198,57 @@ public class HSSFComment extends HSSFTextbox implements Comment {
* *
* @param author the name of the original author of the comment * @param author the name of the original author of the comment
*/ */
public void setAuthor(String author){ public void setAuthor(String author) {
if(_note != null) _note.setAuthor(author); if (_note != null) _note.setAuthor(author);
this._author = author;
} }
/**
* Sets the rich text string used by this comment.
*
* @param string Sets the rich text string used by this object.
*/
public void setString(RichTextString string) {
HSSFRichTextString hstring = (HSSFRichTextString) string;
//if font is not set we must set the default one
if (hstring.numFormattingRuns() == 0) hstring.applyFont((short)0);
if (_txo != null) {
_txo.setStr(hstring);
}
super.setString(string);
}
/** /**
* Returns the underlying Note record * Returns the underlying Note record
*/ */
protected NoteRecord getNoteRecord() { protected NoteRecord getNoteRecord() {
return _note; return _note;
} }
/**
* Returns the underlying Text record @Override
*/ public void setShapeType(int shapeType) {
protected TextObjectRecord getTextObjectRecord() { throw new IllegalStateException("Shape type can not be changed in "+this.getClass().getSimpleName());
return _txo; }
}
public void afterRemove(HSSFPatriarch patriarch){
super.afterRemove(patriarch);
patriarch._getBoundAggregate().removeTailRecord(getNoteRecord());
}
@Override
protected HSSFShape cloneShape() {
TextObjectRecord txo = (TextObjectRecord) getTextObjectRecord().cloneViaReserialise();
EscherContainerRecord spContainer = new EscherContainerRecord();
byte [] inSp = getEscherContainer().serialize();
spContainer.fillFields(inSp, 0, new DefaultEscherRecordFactory());
ObjRecord obj = (ObjRecord) getObjRecord().cloneViaReserialise();
NoteRecord note = (NoteRecord) getNoteRecord().cloneViaReserialise();
return new HSSFComment(spContainer, obj, txo, note);
}
public void setBackgroundImage(int pictureIndex){
setPropertyValue(new EscherSimpleProperty( EscherProperties.FILL__PATTERNTEXTURE, false, true, pictureIndex));
setPropertyValue(new EscherSimpleProperty( EscherProperties.FILL__FILLTYPE, false, false, FILL_TYPE_PICTURE));
EscherBSERecord bse = getPatriarch().getSheet().getWorkbook().getWorkbook().getBSERecord(pictureIndex);
bse.setRef(bse.getRef() + 1);
}
public void resetBackgroundImage(){
EscherSimpleProperty property = getOptRecord().lookup(EscherProperties.FILL__PATTERNTEXTURE);
if (null != property){
EscherBSERecord bse = getPatriarch().getSheet().getWorkbook().getWorkbook().getBSERecord(property.getPropertyValue());
bse.setRef(bse.getRef() - 1);
getOptRecord().removeEscherProperty(EscherProperties.FILL__PATTERNTEXTURE);
}
setPropertyValue(new EscherSimpleProperty( EscherProperties.FILL__FILLTYPE, false, false, FILL_TYPE_SOLID));
}
public int getBackgroundImageId(){
EscherSimpleProperty property = getOptRecord().lookup(EscherProperties.FILL__PATTERNTEXTURE);
return property == null ? 0 : property.getPropertyValue();
}
} }

View File

@ -21,39 +21,28 @@ package org.apache.poi.hssf.usermodel;
import java.io.IOException; import java.io.IOException;
import java.util.Iterator; import java.util.Iterator;
import org.apache.poi.hssf.record.EmbeddedObjectRefSubRecord; import org.apache.poi.ddf.*;
import org.apache.poi.hssf.record.ObjRecord; import org.apache.poi.hssf.record.*;
import org.apache.poi.hssf.record.SubRecord;
import org.apache.poi.poifs.filesystem.DirectoryEntry; import org.apache.poi.poifs.filesystem.DirectoryEntry;
import org.apache.poi.poifs.filesystem.Entry; import org.apache.poi.poifs.filesystem.Entry;
import org.apache.poi.util.HexDump; import org.apache.poi.util.HexDump;
/** /**
* Represents binary object (i.e. OLE) data stored in the file. Eg. A GIF, JPEG etc... * Represents binary object (i.e. OLE) data stored in the file. Eg. A GIF, JPEG etc...
* <p/>
* Right now, 13, july, 2012 can not be created from scratch
* *
* @author Daniel Noll * @author Daniel Noll
*/ */
public final class HSSFObjectData { public final class HSSFObjectData extends HSSFPicture {
/**
* Underlying object record ultimately containing a reference to the object.
*/
private final ObjRecord _record;
/** /**
* Reference to the filesystem root, required for retrieving the object data. * Reference to the filesystem root, required for retrieving the object data.
*/ */
private final DirectoryEntry _root; private final DirectoryEntry _root;
/** public HSSFObjectData(EscherContainerRecord spContainer, ObjRecord objRecord, DirectoryEntry _root) {
* Constructs object data by wrapping a lower level object record. super(spContainer, objRecord);
* this._root = _root;
* @param record the low-level object record.
* @param root the root of the filesystem, required for retrieving the object data.
*/
public HSSFObjectData(ObjRecord record, DirectoryEntry root)
{
_record = record;
_root = root;
} }
/** /**
@ -65,7 +54,7 @@ public final class HSSFObjectData {
/** /**
* Gets the object data. Only call for ones that have * Gets the object data. Only call for ones that have
* data though. See {@link #hasDirectoryEntry()} * data though. See {@link #hasDirectoryEntry()}
* *
* @return the object data as an OLE2 directory. * @return the object data as an OLE2 directory.
* @throws IOException if there was an error reading the data. * @throws IOException if there was an error reading the data.
@ -85,8 +74,8 @@ public final class HSSFObjectData {
/** /**
* Returns the data portion, for an ObjectData * Returns the data portion, for an ObjectData
* that doesn't have an associated POIFS Directory * that doesn't have an associated POIFS Directory
* Entry * Entry
*/ */
public byte[] getObjectData() { public byte[] getObjectData() {
return findObjectRecord().getObjectData(); return findObjectRecord().getObjectData();
@ -94,7 +83,7 @@ public final class HSSFObjectData {
/** /**
* Does this ObjectData have an associated POIFS * Does this ObjectData have an associated POIFS
* Directory Entry? * Directory Entry?
* (Not all do, those that don't have a data portion) * (Not all do, those that don't have a data portion)
*/ */
public boolean hasDirectoryEntry() { public boolean hasDirectoryEntry() {
@ -107,18 +96,51 @@ public final class HSSFObjectData {
/** /**
* Finds the EmbeddedObjectRefSubRecord, or throws an * Finds the EmbeddedObjectRefSubRecord, or throws an
* Exception if there wasn't one * Exception if there wasn't one
*/ */
protected EmbeddedObjectRefSubRecord findObjectRecord() { protected EmbeddedObjectRefSubRecord findObjectRecord() {
Iterator<SubRecord> subRecordIter = _record.getSubRecords().iterator(); Iterator<SubRecord> subRecordIter = getObjRecord().getSubRecords().iterator();
while (subRecordIter.hasNext()) { while (subRecordIter.hasNext()) {
Object subRecord = subRecordIter.next(); Object subRecord = subRecordIter.next();
if (subRecord instanceof EmbeddedObjectRefSubRecord) { if (subRecord instanceof EmbeddedObjectRefSubRecord) {
return (EmbeddedObjectRefSubRecord)subRecord; return (EmbeddedObjectRefSubRecord) subRecord;
} }
} }
throw new IllegalStateException("Object data does not contain a reference to an embedded object OLE2 directory"); throw new IllegalStateException("Object data does not contain a reference to an embedded object OLE2 directory");
} }
@Override
protected EscherContainerRecord createSpContainer() {
throw new IllegalStateException("HSSFObjectData cannot be created from scratch");
}
@Override
protected ObjRecord createObjRecord() {
throw new IllegalStateException("HSSFObjectData cannot be created from scratch");
}
@Override
protected void afterRemove(HSSFPatriarch patriarch) {
throw new IllegalStateException("HSSFObjectData cannot be created from scratch");
}
@Override
void afterInsert(HSSFPatriarch patriarch) {
EscherAggregate agg = patriarch._getBoundAggregate();
agg.associateShapeToObjRecord(getEscherContainer().getChildById(EscherClientDataRecord.RECORD_ID), getObjRecord());
EscherBSERecord bse =
patriarch.getSheet().getWorkbook().getWorkbook().getBSERecord(getPictureIndex());
bse.setRef(bse.getRef() + 1);
}
@Override
protected HSSFShape cloneShape() {
EscherContainerRecord spContainer = new EscherContainerRecord();
byte[] inSp = getEscherContainer().serialize();
spContainer.fillFields(inSp, 0, new DefaultEscherRecordFactory());
ObjRecord obj = (ObjRecord) getObjRecord().cloneViaReserialise();
return new HSSFObjectData(spContainer, obj, _root);
}
} }

View File

@ -18,13 +18,12 @@
package org.apache.poi.hssf.usermodel; package org.apache.poi.hssf.usermodel;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import org.apache.poi.ddf.EscherComplexProperty; import org.apache.poi.ddf.*;
import org.apache.poi.ddf.EscherOptRecord; import org.apache.poi.hssf.model.DrawingManager2;
import org.apache.poi.ddf.EscherProperty;
import org.apache.poi.ddf.EscherBSERecord;
import org.apache.poi.hssf.record.EscherAggregate; import org.apache.poi.hssf.record.EscherAggregate;
import org.apache.poi.ss.usermodel.Chart; import org.apache.poi.ss.usermodel.Chart;
import org.apache.poi.util.StringUtil; import org.apache.poi.util.StringUtil;
@ -40,41 +39,89 @@ import org.apache.poi.ss.usermodel.ClientAnchor;
*/ */
public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { public final class HSSFPatriarch implements HSSFShapeContainer, Drawing {
private final List<HSSFShape> _shapes = new ArrayList<HSSFShape>(); private final List<HSSFShape> _shapes = new ArrayList<HSSFShape>();
private int _x1 = 0;
private int _y1 = 0 ; private final EscherSpgrRecord _spgrRecord;
private int _x2 = 1023; private final EscherContainerRecord _mainSpgrContainer;
private int _y2 = 255;
/** /**
* The EscherAggregate we have been bound to. * The EscherAggregate we have been bound to.
* (This will handle writing us out into records, * (This will handle writing us out into records,
* and building up our shapes from the records) * and building up our shapes from the records)
*/ */
private EscherAggregate _boundAggregate; private EscherAggregate _boundAggregate;
final HSSFSheet _sheet; // TODO make private private final HSSFSheet _sheet;
/** /**
* Creates the patriarch. * Creates the patriarch.
* *
* @param sheet the sheet this patriarch is stored in. * @param sheet the sheet this patriarch is stored in.
*/ */
HSSFPatriarch(HSSFSheet sheet, EscherAggregate boundAggregate){ HSSFPatriarch(HSSFSheet sheet, EscherAggregate boundAggregate) {
_sheet = sheet; _sheet = sheet;
_boundAggregate = boundAggregate; _boundAggregate = boundAggregate;
_mainSpgrContainer = _boundAggregate.getEscherContainer().getChildContainers().get(0);
EscherContainerRecord spContainer = (EscherContainerRecord) _boundAggregate.getEscherContainer()
.getChildContainers().get(0).getChild(0);
_spgrRecord = spContainer.getChildById(EscherSpgrRecord.RECORD_ID);
buildShapeTree();
}
/**
* used to clone patriarch
*
* create patriarch from existing one
* @param patriarch - copy all the shapes from this patriarch to new one
* @param sheet where must be located new patriarch
* @return new patriarch with copies of all shapes from the existing patriarch
*/
static HSSFPatriarch createPatriarch(HSSFPatriarch patriarch, HSSFSheet sheet){
HSSFPatriarch newPatriarch = new HSSFPatriarch(sheet, new EscherAggregate());
newPatriarch.afterCreate();
for (HSSFShape shape: patriarch.getChildren()){
HSSFShape newShape;
if (shape instanceof HSSFShapeGroup){
newShape = ((HSSFShapeGroup)shape).cloneShape(newPatriarch);
} else {
newShape = shape.cloneShape();
}
newPatriarch.onCreate(newShape);
newPatriarch.addShape(newShape);
}
return newPatriarch;
}
/**
* @param shape to be removed
* @return true of shape is removed
*/
public boolean removeShape(HSSFShape shape) {
boolean isRemoved = _mainSpgrContainer.removeChildRecord(shape.getEscherContainer());
if (isRemoved){
shape.afterRemove(this);
_shapes.remove(shape);
}
return isRemoved;
}
void afterCreate() {
DrawingManager2 drawingManager = _sheet.getWorkbook().getWorkbook().getDrawingManager();
short dgId = drawingManager.findNewDrawingGroupId();
_boundAggregate.setDgId(dgId);
_boundAggregate.setMainSpRecordId(newShapeId());
drawingManager.incrementDrawingsSaved();
} }
/** /**
* Creates a new group record stored under this patriarch. * Creates a new group record stored under this patriarch.
* *
* @param anchor the client anchor describes how this group is attached * @param anchor the client anchor describes how this group is attached
* to the sheet. * to the sheet.
* @return the newly created group. * @return the newly created group.
*/ */
public HSSFShapeGroup createGroup(HSSFClientAnchor anchor) public HSSFShapeGroup createGroup(HSSFClientAnchor anchor) {
{
HSSFShapeGroup group = new HSSFShapeGroup(null, anchor); HSSFShapeGroup group = new HSSFShapeGroup(null, anchor);
group.anchor = anchor;
addShape(group); addShape(group);
onCreate(group);
return group; return group;
} }
@ -82,84 +129,86 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing {
* Creates a simple shape. This includes such shapes as lines, rectangles, * Creates a simple shape. This includes such shapes as lines, rectangles,
* and ovals. * and ovals.
* *
* @param anchor the client anchor describes how this group is attached * @param anchor the client anchor describes how this group is attached
* to the sheet. * to the sheet.
* @return the newly created shape. * @return the newly created shape.
*/ */
public HSSFSimpleShape createSimpleShape(HSSFClientAnchor anchor) public HSSFSimpleShape createSimpleShape(HSSFClientAnchor anchor) {
{
HSSFSimpleShape shape = new HSSFSimpleShape(null, anchor); HSSFSimpleShape shape = new HSSFSimpleShape(null, anchor);
shape.anchor = anchor;
addShape(shape); addShape(shape);
//open existing file
onCreate(shape);
return shape; return shape;
} }
/** /**
* Creates a picture. * Creates a picture.
* *
* @param anchor the client anchor describes how this group is attached * @param anchor the client anchor describes how this group is attached
* to the sheet. * to the sheet.
* @return the newly created shape. * @return the newly created shape.
*/ */
public HSSFPicture createPicture(HSSFClientAnchor anchor, int pictureIndex) public HSSFPicture createPicture(HSSFClientAnchor anchor, int pictureIndex) {
{
HSSFPicture shape = new HSSFPicture(null, anchor); HSSFPicture shape = new HSSFPicture(null, anchor);
shape.setPictureIndex( pictureIndex ); shape.setPictureIndex(pictureIndex);
shape.anchor = anchor;
addShape(shape); addShape(shape);
//open existing file
EscherBSERecord bse = _sheet.getWorkbook().getWorkbook().getBSERecord(pictureIndex); onCreate(shape);
bse.setRef(bse.getRef() + 1);
return shape; return shape;
} }
public HSSFPicture createPicture(ClientAnchor anchor, int pictureIndex) /**
{ *
return createPicture((HSSFClientAnchor)anchor, pictureIndex); * @param anchor the client anchor describes how this picture is
* attached to the sheet.
* @param pictureIndex the index of the picture in the workbook collection
* of pictures.
*
* @return newly created shape
*/
public HSSFPicture createPicture(ClientAnchor anchor, int pictureIndex) {
return createPicture((HSSFClientAnchor) anchor, pictureIndex);
} }
/** /**
* Creates a polygon * Creates a polygon
* *
* @param anchor the client anchor describes how this group is attached * @param anchor the client anchor describes how this group is attached
* to the sheet. * to the sheet.
* @return the newly created shape. * @return the newly created shape.
*/ */
public HSSFPolygon createPolygon(HSSFClientAnchor anchor) public HSSFPolygon createPolygon(HSSFClientAnchor anchor) {
{
HSSFPolygon shape = new HSSFPolygon(null, anchor); HSSFPolygon shape = new HSSFPolygon(null, anchor);
shape.anchor = anchor;
addShape(shape); addShape(shape);
onCreate(shape);
return shape; return shape;
} }
/** /**
* Constructs a textbox under the patriarch. * Constructs a textbox under the patriarch.
* *
* @param anchor the client anchor describes how this group is attached * @param anchor the client anchor describes how this group is attached
* to the sheet. * to the sheet.
* @return the newly created textbox. * @return the newly created textbox.
*/ */
public HSSFTextbox createTextbox(HSSFClientAnchor anchor) public HSSFTextbox createTextbox(HSSFClientAnchor anchor) {
{
HSSFTextbox shape = new HSSFTextbox(null, anchor); HSSFTextbox shape = new HSSFTextbox(null, anchor);
shape.anchor = anchor;
addShape(shape); addShape(shape);
onCreate(shape);
return shape; return shape;
} }
/** /**
* Constructs a cell comment. * Constructs a cell comment.
* *
* @param anchor the client anchor describes how this comment is attached * @param anchor the client anchor describes how this comment is attached
* to the sheet. * to the sheet.
* @return the newly created comment. * @return the newly created comment.
*/ */
public HSSFComment createComment(HSSFAnchor anchor) public HSSFComment createComment(HSSFAnchor anchor) {
{
HSSFComment shape = new HSSFComment(null, anchor); HSSFComment shape = new HSSFComment(null, anchor);
shape.anchor = anchor;
addShape(shape); addShape(shape);
onCreate(shape);
return shape; return shape;
} }
@ -168,83 +217,116 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing {
* *
* @see org.apache.poi.hssf.usermodel.HSSFSheet#setAutoFilter(org.apache.poi.ss.util.CellRangeAddress) * @see org.apache.poi.hssf.usermodel.HSSFSheet#setAutoFilter(org.apache.poi.ss.util.CellRangeAddress)
*/ */
HSSFSimpleShape createComboBox(HSSFAnchor anchor) HSSFSimpleShape createComboBox(HSSFAnchor anchor) {
{ HSSFCombobox shape = new HSSFCombobox(null, anchor);
HSSFSimpleShape shape = new HSSFSimpleShape(null, anchor); addShape(shape);
shape.setShapeType(HSSFSimpleShape.OBJECT_TYPE_COMBO_BOX); onCreate(shape);
shape.anchor = anchor; return shape;
addShape(shape); }
return shape;
}
public HSSFComment createCellComment(ClientAnchor anchor) { public HSSFComment createCellComment(ClientAnchor anchor) {
return createComment((HSSFAnchor)anchor); return createComment((HSSFAnchor) anchor);
} }
/** /**
* Returns a list of all shapes contained by the patriarch. * Returns a unmodifiable list of all shapes contained by the patriarch.
*/ */
public List<HSSFShape> getChildren() public List<HSSFShape> getChildren() {
{ return Collections.unmodifiableList(_shapes);
return _shapes;
} }
/** /**
* add a shape to this drawing * add a shape to this drawing
*/ */
@Internal @Internal
public void addShape(HSSFShape shape){ public void addShape(HSSFShape shape) {
shape._patriarch = this; shape.setPatriarch(this);
_shapes.add(shape); _shapes.add(shape);
} }
private void onCreate(HSSFShape shape) {
EscherContainerRecord spgrContainer =
_boundAggregate.getEscherContainer().getChildContainers().get(0);
EscherContainerRecord spContainer = shape.getEscherContainer();
int shapeId = newShapeId();
shape.setShapeId(shapeId);
spgrContainer.addChildRecord(spContainer);
shape.afterInsert(this);
setFlipFlags(shape);
}
/** /**
* Total count of all children and their children's children. * Total count of all children and their children's children.
* @return count of shapes including shapes inside shape groups
*/ */
public int countOfAllChildren() { public int countOfAllChildren() {
int count = _shapes.size(); int count = _shapes.size();
for (Iterator<HSSFShape> iterator = _shapes.iterator(); iterator.hasNext();) { for (Iterator<HSSFShape> iterator = _shapes.iterator(); iterator.hasNext(); ) {
HSSFShape shape = iterator.next(); HSSFShape shape = iterator.next();
count += shape.countOfAllChildren(); count += shape.countOfAllChildren();
} }
return count; return count;
} }
/** /**
* Sets the coordinate space of this group. All children are constrained * Sets the coordinate space of this group. All children are constrained
* to these coordinates. * to these coordinates.
*/ */
public void setCoordinates(int x1, int y1, int x2, int y2){ public void setCoordinates(int x1, int y1, int x2, int y2) {
_x1 = x1; _spgrRecord.setRectY1(y1);
_y1 = y1; _spgrRecord.setRectY2(y2);
_x2 = x2; _spgrRecord.setRectX1(x1);
_y2 = y2; _spgrRecord.setRectX2(x2);
}
/**
* remove all shapes inside patriarch
*/
public void clear() {
ArrayList <HSSFShape> copy = new ArrayList<HSSFShape>(_shapes);
for (HSSFShape shape: copy){
removeShape(shape);
}
}
/**
* @return new unique shapeId
*/
int newShapeId() {
DrawingManager2 dm = _sheet.getWorkbook().getWorkbook().getDrawingManager();
EscherDgRecord dg =
_boundAggregate.getEscherContainer().getChildById(EscherDgRecord.RECORD_ID);
short drawingGroupId = dg.getDrawingGroupId();
return dm.allocateShapeId(drawingGroupId, dg);
} }
/** /**
* Does this HSSFPatriarch contain a chart? * Does this HSSFPatriarch contain a chart?
* (Technically a reference to a chart, since they * (Technically a reference to a chart, since they
* get stored in a different block of records) * get stored in a different block of records)
* FIXME - detect chart in all cases (only seems * FIXME - detect chart in all cases (only seems
* to work on some charts so far) * to work on some charts so far)
*/ */
public boolean containsChart() { public boolean containsChart() {
// TODO - support charts properly in usermodel // TODO - support charts properly in usermodel
// We're looking for a EscherOptRecord // We're looking for a EscherOptRecord
EscherOptRecord optRecord = (EscherOptRecord) EscherOptRecord optRecord = (EscherOptRecord)
_boundAggregate.findFirstWithId(EscherOptRecord.RECORD_ID); _boundAggregate.findFirstWithId(EscherOptRecord.RECORD_ID);
if(optRecord == null) { if (optRecord == null) {
// No opt record, can't have chart // No opt record, can't have chart
return false; return false;
} }
for(Iterator<EscherProperty> it = optRecord.getEscherProperties().iterator(); it.hasNext();) { for (Iterator<EscherProperty> it = optRecord.getEscherProperties().iterator(); it.hasNext(); ) {
EscherProperty prop = it.next(); EscherProperty prop = it.next();
if(prop.getPropertyNumber() == 896 && prop.isComplex()) { if (prop.getPropertyNumber() == 896 && prop.isComplex()) {
EscherComplexProperty cp = (EscherComplexProperty)prop; EscherComplexProperty cp = (EscherComplexProperty) prop;
String str = StringUtil.getFromUnicodeLE(cp.getComplexData()); String str = StringUtil.getFromUnicodeLE(cp.getComplexData());
if(str.equals("Chart 1\0")) { if (str.equals("Chart 1\0")) {
return true; return true;
} }
} }
@ -254,35 +336,31 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing {
} }
/** /**
* The top left x coordinate of this group. * @return x coordinate of the left up corner
*/ */
public int getX1() public int getX1() {
{ return _spgrRecord.getRectX1();
return _x1;
} }
/** /**
* The top left y coordinate of this group. * @return y coordinate of the left up corner
*/ */
public int getY1() public int getY1() {
{ return _spgrRecord.getRectY1();
return _y1;
} }
/** /**
* The bottom right x coordinate of this group. * @return x coordinate of the right down corner
*/ */
public int getX2() public int getX2() {
{ return _spgrRecord.getRectX2();
return _x2;
} }
/** /**
* The bottom right y coordinate of this group. * @return y coordinate of the right down corner
*/ */
public int getY2() public int getY2() {
{ return _spgrRecord.getRectY2();
return _y2;
} }
/** /**
@ -306,12 +384,51 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing {
* @param row2 the row (0 based) of the second cell. * @param row2 the row (0 based) of the second cell.
* @return the newly created client anchor * @return the newly created client anchor
*/ */
public HSSFClientAnchor createAnchor(int dx1, int dy1, int dx2, int dy2, int col1, int row1, int col2, int row2){ public HSSFClientAnchor createAnchor(int dx1, int dy1, int dx2, int dy2, int col1, int row1, int col2, int row2) {
return new HSSFClientAnchor(dx1, dy1, dx2, dy2, (short)col1, row1, (short)col2, row2); return new HSSFClientAnchor(dx1, dy1, dx2, dy2, (short) col1, row1, (short) col2, row2);
} }
public Chart createChart(ClientAnchor anchor) { public Chart createChart(ClientAnchor anchor) {
throw new RuntimeException("NotImplemented"); throw new RuntimeException("NotImplemented");
} }
/**
* create shape tree from existing escher records tree
*/
void buildShapeTree() {
EscherContainerRecord dgContainer = _boundAggregate.getEscherContainer();
if (dgContainer == null) {
return;
}
EscherContainerRecord spgrConrainer = dgContainer.getChildContainers().get(0);
List<EscherContainerRecord> spgrChildren = spgrConrainer.getChildContainers();
for (int i = 0; i < spgrChildren.size(); i++) {
EscherContainerRecord spContainer = spgrChildren.get(i);
if (i == 0) {
continue;
} else {
HSSFShapeFactory.createShapeTree(spContainer, _boundAggregate, this, _sheet.getWorkbook().getRootDirectory());
}
}
}
private void setFlipFlags(HSSFShape shape){
EscherSpRecord sp = shape.getEscherContainer().getChildById(EscherSpRecord.RECORD_ID);
if (shape.getAnchor().isHorizontallyFlipped()) {
sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_FLIPHORIZ);
}
if (shape.getAnchor().isVerticallyFlipped()) {
sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_FLIPVERT);
}
}
public Iterator<HSSFShape> iterator() {
return _shapes.iterator();
}
protected HSSFSheet getSheet() {
return _sheet;
}
} }

View File

@ -19,9 +19,12 @@ package org.apache.poi.hssf.usermodel;
import java.awt.Dimension; import java.awt.Dimension;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.UnsupportedEncodingException;
import org.apache.poi.ddf.EscherBSERecord; import org.apache.poi.ddf.*;
import org.apache.poi.ddf.EscherBlipRecord; import org.apache.poi.hssf.record.CommonObjectDataSubRecord;
import org.apache.poi.hssf.record.EscherAggregate;
import org.apache.poi.hssf.record.ObjRecord;
import org.apache.poi.ss.usermodel.Picture; import org.apache.poi.ss.usermodel.Picture;
import org.apache.poi.ss.util.ImageUtils; import org.apache.poi.ss.util.ImageUtils;
import org.apache.poi.hssf.model.InternalWorkbook; import org.apache.poi.hssf.model.InternalWorkbook;
@ -32,7 +35,7 @@ import org.apache.poi.hssf.model.InternalWorkbook;
* @author Glen Stampoultzis * @author Glen Stampoultzis
* @author Yegor Kozlov (yegor at apache.org) * @author Yegor Kozlov (yegor at apache.org)
*/ */
public final class HSSFPicture extends HSSFSimpleShape implements Picture { public class HSSFPicture extends HSSFSimpleShape implements Picture {
public static final int PICTURE_TYPE_EMF = HSSFWorkbook.PICTURE_TYPE_EMF; // Windows Enhanced Metafile public static final int PICTURE_TYPE_EMF = HSSFWorkbook.PICTURE_TYPE_EMF; // Windows Enhanced Metafile
public static final int PICTURE_TYPE_WMF = HSSFWorkbook.PICTURE_TYPE_WMF; // Windows Metafile public static final int PICTURE_TYPE_WMF = HSSFWorkbook.PICTURE_TYPE_WMF; // Windows Metafile
public static final int PICTURE_TYPE_PICT = HSSFWorkbook.PICTURE_TYPE_PICT; // Macintosh PICT public static final int PICTURE_TYPE_PICT = HSSFWorkbook.PICTURE_TYPE_PICT; // Macintosh PICT
@ -54,7 +57,9 @@ public final class HSSFPicture extends HSSFSimpleShape implements Picture {
*/ */
private static final int PX_ROW = 15; private static final int PX_ROW = 15;
private int _pictureIndex; public HSSFPicture(EscherContainerRecord spContainer, ObjRecord objRecord) {
super(spContainer, objRecord);
}
/** /**
* Constructs a picture object. * Constructs a picture object.
@ -62,17 +67,33 @@ public final class HSSFPicture extends HSSFSimpleShape implements Picture {
public HSSFPicture( HSSFShape parent, HSSFAnchor anchor ) public HSSFPicture( HSSFShape parent, HSSFAnchor anchor )
{ {
super( parent, anchor ); super( parent, anchor );
setShapeType(OBJECT_TYPE_PICTURE); super.setShapeType(OBJECT_TYPE_PICTURE);
CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) getObjRecord().getSubRecords().get(0);
cod.setObjectType(CommonObjectDataSubRecord.OBJECT_TYPE_PICTURE);
} }
public int getPictureIndex() public int getPictureIndex()
{ {
return _pictureIndex; EscherSimpleProperty property = getOptRecord().lookup(EscherProperties.BLIP__BLIPTODISPLAY);
if (null == property){
return -1;
}
return property.getPropertyValue();
} }
public void setPictureIndex( int pictureIndex ) public void setPictureIndex( int pictureIndex )
{ {
this._pictureIndex = pictureIndex; setPropertyValue(new EscherSimpleProperty( EscherProperties.BLIP__BLIPTODISPLAY, false, true, pictureIndex));
}
@Override
protected EscherContainerRecord createSpContainer() {
EscherContainerRecord spContainer = super.createSpContainer();
EscherOptRecord opt = spContainer.getChildById(EscherOptRecord.RECORD_ID);
opt.removeEscherProperty(EscherProperties.LINESTYLE__LINEDASHING);
opt.removeEscherProperty(EscherProperties.LINESTYLE__NOLINEDRAWDASH);
spContainer.removeChildRecord(spContainer.getChildById(EscherTextboxRecord.RECORD_ID));
return spContainer;
} }
/** /**
@ -145,8 +166,8 @@ public final class HSSFPicture extends HSSFSimpleShape implements Picture {
float w = 0; float w = 0;
//space in the leftmost cell //space in the leftmost cell
w += getColumnWidthInPixels(anchor.col1)*(1 - (float)anchor.dx1/1024); w += getColumnWidthInPixels(anchor.getCol1())*(1 - (float)anchor.getDx1()/1024);
short col2 = (short)(anchor.col1 + 1); short col2 = (short)(anchor.getCol1() + 1);
int dx2 = 0; int dx2 = 0;
while(w < scaledWidth){ while(w < scaledWidth){
@ -160,12 +181,12 @@ public final class HSSFPicture extends HSSFSimpleShape implements Picture {
double delta = w - scaledWidth; double delta = w - scaledWidth;
dx2 = (int)((cw-delta)/cw*1024); dx2 = (int)((cw-delta)/cw*1024);
} }
anchor.col2 = col2; anchor.setCol2(col2);
anchor.dx2 = dx2; anchor.setDx2(dx2);
float h = 0; float h = 0;
h += (1 - (float)anchor.dy1/256)* getRowHeightInPixels(anchor.row1); h += (1 - (float)anchor.getDy1()/256)* getRowHeightInPixels(anchor.getRow1());
int row2 = anchor.row1 + 1; int row2 = anchor.getRow1() + 1;
int dy2 = 0; int dy2 = 0;
while(h < scaledHeight){ while(h < scaledHeight){
@ -177,15 +198,15 @@ public final class HSSFPicture extends HSSFSimpleShape implements Picture {
double delta = h - scaledHeight; double delta = h - scaledHeight;
dy2 = (int)((ch-delta)/ch*256); dy2 = (int)((ch-delta)/ch*256);
} }
anchor.row2 = row2; anchor.setRow2(row2);
anchor.dy2 = dy2; anchor.setDy2(dy2);
return anchor; return anchor;
} }
private float getColumnWidthInPixels(int column){ private float getColumnWidthInPixels(int column){
int cw = _patriarch._sheet.getColumnWidth(column); int cw = getPatriarch().getSheet().getColumnWidth(column);
float px = getPixelWidth(column); float px = getPixelWidth(column);
return cw/px; return cw/px;
@ -193,18 +214,18 @@ public final class HSSFPicture extends HSSFSimpleShape implements Picture {
private float getRowHeightInPixels(int i){ private float getRowHeightInPixels(int i){
HSSFRow row = _patriarch._sheet.getRow(i); HSSFRow row = getPatriarch().getSheet().getRow(i);
float height; float height;
if(row != null) height = row.getHeight(); if(row != null) height = row.getHeight();
else height = _patriarch._sheet.getDefaultRowHeight(); else height = getPatriarch().getSheet().getDefaultRowHeight();
return height/PX_ROW; return height/PX_ROW;
} }
private float getPixelWidth(int column){ private float getPixelWidth(int column){
int def = _patriarch._sheet.getDefaultColumnWidth()*256; int def = getPatriarch().getSheet().getDefaultColumnWidth()*256;
int cw = _patriarch._sheet.getColumnWidth(column); int cw = getPatriarch().getSheet().getColumnWidth(column);
return cw == def ? PX_DEFAULT : PX_MODIFIED; return cw == def ? PX_DEFAULT : PX_MODIFIED;
} }
@ -215,7 +236,7 @@ public final class HSSFPicture extends HSSFSimpleShape implements Picture {
* @return image dimension * @return image dimension
*/ */
public Dimension getImageDimension(){ public Dimension getImageDimension(){
EscherBSERecord bse = _patriarch._sheet._book.getBSERecord(_pictureIndex); EscherBSERecord bse = getPatriarch().getSheet()._book.getBSERecord(getPictureIndex());
byte[] data = bse.getBlipRecord().getPicturedata(); byte[] data = bse.getBlipRecord().getPicturedata();
int type = bse.getBlipTypeWin32(); int type = bse.getBlipTypeWin32();
return ImageUtils.getImageDimension(new ByteArrayInputStream(data), type); return ImageUtils.getImageDimension(new ByteArrayInputStream(data), type);
@ -227,8 +248,56 @@ public final class HSSFPicture extends HSSFSimpleShape implements Picture {
* @return picture data for this shape * @return picture data for this shape
*/ */
public HSSFPictureData getPictureData(){ public HSSFPictureData getPictureData(){
InternalWorkbook iwb = _patriarch._sheet.getWorkbook().getWorkbook(); InternalWorkbook iwb = getPatriarch().getSheet().getWorkbook().getWorkbook();
EscherBlipRecord blipRecord = iwb.getBSERecord(_pictureIndex).getBlipRecord(); EscherBlipRecord blipRecord = iwb.getBSERecord(getPictureIndex()).getBlipRecord();
return new HSSFPictureData(blipRecord); return new HSSFPictureData(blipRecord);
} }
@Override
void afterInsert(HSSFPatriarch patriarch) {
EscherAggregate agg = patriarch._getBoundAggregate();
agg.associateShapeToObjRecord(getEscherContainer().getChildById(EscherClientDataRecord.RECORD_ID), getObjRecord());
EscherBSERecord bse =
patriarch.getSheet().getWorkbook().getWorkbook().getBSERecord(getPictureIndex());
bse.setRef(bse.getRef() + 1);
}
/**
* The color applied to the lines of this shape.
*/
public String getFileName() {
EscherComplexProperty propFile = (EscherComplexProperty) getOptRecord().lookup(
EscherProperties.BLIP__BLIPFILENAME);
try {
if (null == propFile){
return "";
}
return new String(propFile.getComplexData(), "UTF-16LE").trim();
} catch (UnsupportedEncodingException e) {
return "";
}
}
public void setFileName(String data){
try {
EscherComplexProperty prop = new EscherComplexProperty(EscherProperties.BLIP__BLIPFILENAME, true, data.getBytes("UTF-16LE"));
setPropertyValue(prop);
} catch (UnsupportedEncodingException e) {
System.out.println("Unsupported encoding: UTF-16LE");
}
}
@Override
public void setShapeType(int shapeType) {
throw new IllegalStateException("Shape type can not be changed in "+this.getClass().getSimpleName());
}
@Override
protected HSSFShape cloneShape() {
EscherContainerRecord spContainer = new EscherContainerRecord();
byte [] inSp = getEscherContainer().serialize();
spContainer.fillFields(inSp, 0, new DefaultEscherRecordFactory());
ObjRecord obj = (ObjRecord) getObjRecord().cloneViaReserialise();
return new HSSFPicture(spContainer, obj);
}
} }

View File

@ -17,45 +17,184 @@
package org.apache.poi.hssf.usermodel; package org.apache.poi.hssf.usermodel;
import org.apache.poi.ddf.*;
import org.apache.poi.hssf.record.*;
import org.apache.poi.util.LittleEndian;
/** /**
* @author Glen Stampoultzis (glens at superlinksoftware.com) * @author Glen Stampoultzis (glens at superlinksoftware.com)
*/ */
public class HSSFPolygon public class HSSFPolygon extends HSSFSimpleShape {
extends HSSFShape
{
int[] xPoints;
int[] yPoints;
int drawAreaWidth = 100;
int drawAreaHeight = 100;
HSSFPolygon( HSSFShape parent, HSSFAnchor anchor ) public final static short OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING = 0x1E;
{
super( parent, anchor ); public HSSFPolygon(EscherContainerRecord spContainer, ObjRecord objRecord, TextObjectRecord _textObjectRecord) {
super(spContainer, objRecord, _textObjectRecord);
} }
public int[] getXPoints() public HSSFPolygon(EscherContainerRecord spContainer, ObjRecord objRecord) {
{ super(spContainer, objRecord);
return xPoints;
} }
public int[] getYPoints() HSSFPolygon(HSSFShape parent, HSSFAnchor anchor) {
{ super(parent, anchor);
return yPoints;
} }
public void setPoints(int[] xPoints, int[] yPoints) @Override
{ protected TextObjectRecord createTextObjRecord() {
this.xPoints = cloneArray(xPoints); return null;
this.yPoints = cloneArray(yPoints);
} }
private int[] cloneArray( int[] a ) /**
{ * Generates the shape records for this shape.
int[] result = new int[a.length]; */
for ( int i = 0; i < a.length; i++ ) protected EscherContainerRecord createSpContainer() {
result[i] = a[i]; EscherContainerRecord spContainer = new EscherContainerRecord();
EscherSpRecord sp = new EscherSpRecord();
EscherOptRecord opt = new EscherOptRecord();
EscherClientDataRecord clientData = new EscherClientDataRecord();
return result; spContainer.setRecordId(EscherContainerRecord.SP_CONTAINER);
spContainer.setOptions((short) 0x000F);
sp.setRecordId(EscherSpRecord.RECORD_ID);
sp.setOptions((short) ((EscherAggregate.ST_NOT_PRIMATIVE << 4) | 0x2));
if (getParent() == null) {
sp.setFlags(EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HASSHAPETYPE);
} else {
sp.setFlags(EscherSpRecord.FLAG_CHILD | EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HASSHAPETYPE);
}
opt.setRecordId(EscherOptRecord.RECORD_ID);
opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.TRANSFORM__ROTATION, false, false, 0));
opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.GEOMETRY__RIGHT, false, false, 100));
opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.GEOMETRY__BOTTOM, false, false, 100));
opt.setEscherProperty(new EscherShapePathProperty(EscherProperties.GEOMETRY__SHAPEPATH, EscherShapePathProperty.COMPLEX));
opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.GEOMETRY__FILLOK, false, false, 0x00010001));
opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINESTARTARROWHEAD, false, false, 0x0));
opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEENDARROWHEAD, false, false, 0x0));
opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEENDCAPSTYLE, false, false, 0x0));
opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEDASHING, LINESTYLE_SOLID));
opt.setEscherProperty( new EscherBoolProperty( EscherProperties.LINESTYLE__NOLINEDRAWDASH, 0x00080008));
opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEWIDTH, LINEWIDTH_DEFAULT));
opt.setEscherProperty(new EscherRGBProperty(EscherProperties.FILL__FILLCOLOR, FILL__FILLCOLOR_DEFAULT));
opt.setEscherProperty(new EscherRGBProperty(EscherProperties.LINESTYLE__COLOR, LINESTYLE__COLOR_DEFAULT));
opt.setEscherProperty(new EscherBoolProperty(EscherProperties.FILL__NOFILLHITTEST, 1));
opt.setEscherProperty(new EscherBoolProperty( EscherProperties.GROUPSHAPE__PRINT, 0x080000));
EscherRecord anchor = getAnchor().getEscherAnchor();
clientData.setRecordId(EscherClientDataRecord.RECORD_ID);
clientData.setOptions((short) 0x0000);
spContainer.addChildRecord(sp);
spContainer.addChildRecord(opt);
spContainer.addChildRecord(anchor);
spContainer.addChildRecord(clientData);
return spContainer;
}
/**
* Creates the low level OBJ record for this shape.
*/
protected ObjRecord createObjRecord() {
ObjRecord obj = new ObjRecord();
CommonObjectDataSubRecord c = new CommonObjectDataSubRecord();
c.setObjectType(OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING);
c.setLocked(true);
c.setPrintable(true);
c.setAutofill(true);
c.setAutoline(true);
EndSubRecord e = new EndSubRecord();
obj.addSubRecord(c);
obj.addSubRecord(e);
return obj;
}
@Override
protected void afterRemove(HSSFPatriarch patriarch) {
patriarch._getBoundAggregate().removeShapeToObjRecord(getEscherContainer().getChildById(EscherClientDataRecord.RECORD_ID));
}
/**
* @return array of x coordinates
*/
public int[] getXPoints() {
EscherArrayProperty verticesProp = getOptRecord().lookup(EscherProperties.GEOMETRY__VERTICES);
if (null == verticesProp){
return new int[]{};
}
int []array = new int[verticesProp.getNumberOfElementsInArray()-1];
for (int i=0; i< verticesProp.getNumberOfElementsInArray()-1; i++){
byte[] property = verticesProp.getElement(i);
short x = LittleEndian.getShort(property, 0);
array[i] = x;
}
return array;
}
/**
* @return array of y coordinates
*/
public int[] getYPoints() {
EscherArrayProperty verticesProp = getOptRecord().lookup(EscherProperties.GEOMETRY__VERTICES);
if (null == verticesProp){
return new int[]{};
}
int []array = new int[verticesProp.getNumberOfElementsInArray()-1];
for (int i=0; i< verticesProp.getNumberOfElementsInArray()-1; i++){
byte[] property = verticesProp.getElement(i);
short x = LittleEndian.getShort(property, 2);
array[i] = x;
}
return array;
}
/**
* @param xPoints - array of x coordinates
* @param yPoints - array of y coordinates
*/
public void setPoints(int[] xPoints, int[] yPoints) {
if (xPoints.length != yPoints.length){
System.out.println("xPoint.length must be equal to yPoints.length");
return;
}
if (xPoints.length == 0){
System.out.println("HSSFPolygon must have at least one point");
}
EscherArrayProperty verticesProp = new EscherArrayProperty(EscherProperties.GEOMETRY__VERTICES, false, new byte[0] );
verticesProp.setNumberOfElementsInArray(xPoints.length+1);
verticesProp.setNumberOfElementsInMemory(xPoints.length+1);
verticesProp.setSizeOfElements(0xFFF0);
for (int i = 0; i < xPoints.length; i++)
{
byte[] data = new byte[4];
LittleEndian.putShort(data, 0, (short)xPoints[i]);
LittleEndian.putShort(data, 2, (short)yPoints[i]);
verticesProp.setElement(i, data);
}
int point = xPoints.length;
byte[] data = new byte[4];
LittleEndian.putShort(data, 0, (short)xPoints[0]);
LittleEndian.putShort(data, 2, (short)yPoints[0]);
verticesProp.setElement(point, data);
setPropertyValue(verticesProp);
EscherArrayProperty segmentsProp = new EscherArrayProperty(EscherProperties.GEOMETRY__SEGMENTINFO, false, null );
segmentsProp.setSizeOfElements(0x0002);
segmentsProp.setNumberOfElementsInArray(xPoints.length * 2 + 4);
segmentsProp.setNumberOfElementsInMemory(xPoints.length * 2 + 4);
segmentsProp.setElement(0, new byte[] { (byte)0x00, (byte)0x40 } );
segmentsProp.setElement(1, new byte[] { (byte)0x00, (byte)0xAC } );
for (int i = 0; i < xPoints.length; i++)
{
segmentsProp.setElement(2 + i * 2, new byte[] { (byte)0x01, (byte)0x00 } );
segmentsProp.setElement(3 + i * 2, new byte[] { (byte)0x00, (byte)0xAC } );
}
segmentsProp.setElement(segmentsProp.getNumberOfElementsInArray() - 2, new byte[] { (byte)0x01, (byte)0x60 } );
segmentsProp.setElement(segmentsProp.getNumberOfElementsInArray() - 1, new byte[] { (byte)0x00, (byte)0x80 } );
setPropertyValue(segmentsProp);
} }
/** /**
@ -63,21 +202,24 @@ public class HSSFPolygon
* @param width * @param width
* @param height * @param height
*/ */
public void setPolygonDrawArea( int width, int height ) public void setPolygonDrawArea(int width, int height) {
{ setPropertyValue(new EscherSimpleProperty(EscherProperties.GEOMETRY__RIGHT, width));
this.drawAreaWidth = width; setPropertyValue(new EscherSimpleProperty(EscherProperties.GEOMETRY__BOTTOM, height));
this.drawAreaHeight = height;
} }
public int getDrawAreaWidth() /**
{ * @return shape width
return drawAreaWidth; */
public int getDrawAreaWidth() {
EscherSimpleProperty property = getOptRecord().lookup(EscherProperties.GEOMETRY__RIGHT);
return property == null ? 100: property.getPropertyValue();
} }
public int getDrawAreaHeight() /**
{ * @return shape height
return drawAreaHeight; */
public int getDrawAreaHeight() {
EscherSimpleProperty property = getOptRecord().lookup(EscherProperties.GEOMETRY__BOTTOM);
return property == null ? 100: property.getPropertyValue();
} }
} }

View File

@ -17,6 +17,15 @@
package org.apache.poi.hssf.usermodel; package org.apache.poi.hssf.usermodel;
import org.apache.poi.ddf.*;
import org.apache.poi.hssf.record.CommonObjectDataSubRecord;
import org.apache.poi.hssf.record.ObjRecord;
import org.apache.poi.util.LittleEndian;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Iterator;
/** /**
* An abstract shape. * An abstract shape.
* *
@ -25,6 +34,9 @@ package org.apache.poi.hssf.usermodel;
public abstract class HSSFShape { public abstract class HSSFShape {
public static final int LINEWIDTH_ONE_PT = 12700; public static final int LINEWIDTH_ONE_PT = 12700;
public static final int LINEWIDTH_DEFAULT = 9525; public static final int LINEWIDTH_DEFAULT = 9525;
public static final int LINESTYLE__COLOR_DEFAULT = 0x08000040;
public static final int FILL__FILLCOLOR_DEFAULT = 0x08000009;
public static final boolean NO_FILL_DEFAULT = true;
public static final int LINESTYLE_SOLID = 0; // Solid (continuous) pen public static final int LINESTYLE_SOLID = 0; // Solid (continuous) pen
public static final int LINESTYLE_DASHSYS = 1; // PS_DASH system dash style public static final int LINESTYLE_DASHSYS = 1; // PS_DASH system dash style
@ -39,38 +51,98 @@ public abstract class HSSFShape {
public static final int LINESTYLE_LONGDASHDOTDOTGEL = 10; // long dash short dash short dash public static final int LINESTYLE_LONGDASHDOTDOTGEL = 10; // long dash short dash short dash
public static final int LINESTYLE_NONE = -1; public static final int LINESTYLE_NONE = -1;
public static final int LINESTYLE_DEFAULT = LINESTYLE_NONE;
// TODO - make all these fields private // TODO - make all these fields private
final HSSFShape parent; private HSSFShape parent;
HSSFAnchor anchor; HSSFAnchor anchor;
HSSFPatriarch _patriarch; private HSSFPatriarch _patriarch;
private int _lineStyleColor = 0x08000040;
int _fillColor = 0x08000009; private final EscherContainerRecord _escherContainer;
private int _lineWidth = LINEWIDTH_DEFAULT; // 12700 = 1pt private final ObjRecord _objRecord;
private int _lineStyle = LINESTYLE_SOLID; private final EscherOptRecord _optRecord;
private boolean _noFill = false;
public final static int NO_FILLHITTEST_TRUE = 0x00110000;
public final static int NO_FILLHITTEST_FALSE = 0x00010000;
/**
* creates shapes from existing file
* @param spContainer
* @param objRecord
*/
public HSSFShape(EscherContainerRecord spContainer, ObjRecord objRecord) {
this._escherContainer = spContainer;
this._objRecord = objRecord;
this._optRecord = spContainer.getChildById(EscherOptRecord.RECORD_ID);
this.anchor = HSSFAnchor.createAnchorFromEscher(spContainer);
}
/** /**
* Create a new shape with the specified parent and anchor. * Create a new shape with the specified parent and anchor.
*/ */
HSSFShape( HSSFShape parent, HSSFAnchor anchor ) public HSSFShape(HSSFShape parent, HSSFAnchor anchor) {
{
this.parent = parent; this.parent = parent;
this.anchor = anchor; this.anchor = anchor;
this._escherContainer = createSpContainer();
_optRecord = _escherContainer.getChildById(EscherOptRecord.RECORD_ID);
_objRecord = createObjRecord();
}
protected abstract EscherContainerRecord createSpContainer();
protected abstract ObjRecord createObjRecord();
/**
* remove escher container from the patriarch.escherAggregate
* remove obj, textObj and note records if it's necessary
* in case of ShapeGroup remove all contained shapes
* @param patriarch
*/
protected abstract void afterRemove(HSSFPatriarch patriarch);
/**
* @param shapeId - global shapeId which must be set to EscherSpRecord
*/
void setShapeId(int shapeId){
EscherSpRecord spRecord = _escherContainer.getChildById(EscherSpRecord.RECORD_ID);
spRecord.setShapeId(shapeId);
CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) _objRecord.getSubRecords().get(0);
cod.setObjectId((short) (shapeId%1024));
}
/**
* @return global shapeId(from EscherSpRecord)
*/
int getShapeId(){
return ((EscherSpRecord)_escherContainer.getChildById(EscherSpRecord.RECORD_ID)).getShapeId();
}
abstract void afterInsert(HSSFPatriarch patriarch);
protected EscherContainerRecord getEscherContainer() {
return _escherContainer;
}
protected ObjRecord getObjRecord() {
return _objRecord;
}
protected EscherOptRecord getOptRecord() {
return _optRecord;
} }
/** /**
* Gets the parent shape. * Gets the parent shape.
*/ */
public HSSFShape getParent() public HSSFShape getParent() {
{
return parent; return parent;
} }
/** /**
* @return the anchor that is used by this shape. * @return the anchor that is used by this shape.
*/ */
public HSSFAnchor getAnchor() public HSSFAnchor getAnchor() {
{
return anchor; return anchor;
} }
@ -78,26 +150,49 @@ public abstract class HSSFShape {
* Sets a particular anchor. A top-level shape must have an anchor of * Sets a particular anchor. A top-level shape must have an anchor of
* HSSFClientAnchor. A child anchor must have an anchor of HSSFChildAnchor * HSSFClientAnchor. A child anchor must have an anchor of HSSFChildAnchor
* *
* @param anchor the anchor to use. * @param anchor the anchor to use.
* @throws IllegalArgumentException when the wrong anchor is used for * @throws IllegalArgumentException when the wrong anchor is used for
* this particular shape. * this particular shape.
*
* @see HSSFChildAnchor * @see HSSFChildAnchor
* @see HSSFClientAnchor * @see HSSFClientAnchor
*/ */
public void setAnchor( HSSFAnchor anchor ) public void setAnchor(HSSFAnchor anchor) {
{ int i = 0;
if ( parent == null ) int recordId = -1;
{ if (parent == null) {
if ( anchor instanceof HSSFChildAnchor ) if (anchor instanceof HSSFChildAnchor)
throw new IllegalArgumentException( "Must use client anchors for shapes directly attached to sheet." ); throw new IllegalArgumentException("Must use client anchors for shapes directly attached to sheet.");
EscherClientAnchorRecord anch = _escherContainer.getChildById(EscherClientAnchorRecord.RECORD_ID);
if (null != anch) {
for (i=0; i< _escherContainer.getChildRecords().size(); i++){
if (_escherContainer.getChild(i).getRecordId() == EscherClientAnchorRecord.RECORD_ID){
if (i != _escherContainer.getChildRecords().size() -1){
recordId = _escherContainer.getChild(i+1).getRecordId();
}
}
}
_escherContainer.removeChildRecord(anch);
}
} else {
if (anchor instanceof HSSFClientAnchor)
throw new IllegalArgumentException("Must use child anchors for shapes attached to groups.");
EscherChildAnchorRecord anch = _escherContainer.getChildById(EscherChildAnchorRecord.RECORD_ID);
if (null != anch) {
for (i=0; i< _escherContainer.getChildRecords().size(); i++){
if (_escherContainer.getChild(i).getRecordId() == EscherChildAnchorRecord.RECORD_ID){
if (i != _escherContainer.getChildRecords().size() -1){
recordId = _escherContainer.getChild(i+1).getRecordId();
}
}
}
_escherContainer.removeChildRecord(anch);
}
} }
else if (-1 == recordId){
{ _escherContainer.addChildRecord(anchor.getEscherAnchor());
if ( anchor instanceof HSSFClientAnchor ) } else {
throw new IllegalArgumentException( "Must use child anchors for shapes attached to groups." ); _escherContainer.addChildBefore(anchor.getEscherAnchor(), recordId);
} }
this.anchor = anchor; this.anchor = anchor;
} }
@ -105,92 +200,181 @@ public abstract class HSSFShape {
* The color applied to the lines of this shape. * The color applied to the lines of this shape.
*/ */
public int getLineStyleColor() { public int getLineStyleColor() {
return _lineStyleColor; EscherRGBProperty rgbProperty = _optRecord.lookup(EscherProperties.LINESTYLE__COLOR);
return rgbProperty == null ? LINESTYLE__COLOR_DEFAULT : rgbProperty.getRgbColor();
} }
/** /**
* The color applied to the lines of this shape. * The color applied to the lines of this shape.
*/ */
public void setLineStyleColor(int lineStyleColor) { public void setLineStyleColor(int lineStyleColor) {
_lineStyleColor = lineStyleColor; setPropertyValue(new EscherRGBProperty(EscherProperties.LINESTYLE__COLOR, lineStyleColor));
} }
/** /**
* The color applied to the lines of this shape. * The color applied to the lines of this shape.
*/ */
public void setLineStyleColor(int red, int green, int blue) { public void setLineStyleColor(int red, int green, int blue) {
this._lineStyleColor = ((blue) << 16) | ((green) << 8) | red; int lineStyleColor = ((blue) << 16) | ((green) << 8) | red;
setPropertyValue(new EscherRGBProperty(EscherProperties.LINESTYLE__COLOR, lineStyleColor));
} }
/** /**
* The color used to fill this shape. * The color used to fill this shape.
*/ */
public int getFillColor() public int getFillColor() {
{ EscherRGBProperty rgbProperty = _optRecord.lookup(EscherProperties.FILL__FILLCOLOR);
return _fillColor; return rgbProperty == null ? FILL__FILLCOLOR_DEFAULT : rgbProperty.getRgbColor();
} }
/** /**
* The color used to fill this shape. * The color used to fill this shape.
*/ */
public void setFillColor(int fillColor) { public void setFillColor(int fillColor) {
_fillColor = fillColor; setPropertyValue(new EscherRGBProperty(EscherProperties.FILL__FILLCOLOR, fillColor));
} }
/** /**
* The color used to fill this shape. * The color used to fill this shape.
*/ */
public void setFillColor( int red, int green, int blue ) public void setFillColor(int red, int green, int blue) {
{ int fillColor = ((blue) << 16) | ((green) << 8) | red;
this._fillColor = ((blue) << 16) | ((green) << 8) | red; setPropertyValue(new EscherRGBProperty(EscherProperties.FILL__FILLCOLOR, fillColor));
} }
/** /**
* @return returns with width of the line in EMUs. 12700 = 1 pt. * @return returns with width of the line in EMUs. 12700 = 1 pt.
*/ */
public int getLineWidth() { public int getLineWidth() {
return _lineWidth; EscherSimpleProperty property = _optRecord.lookup(EscherProperties.LINESTYLE__LINEWIDTH);
return property == null ? LINEWIDTH_DEFAULT: property.getPropertyValue();
} }
/** /**
* Sets the width of the line. 12700 = 1 pt. * Sets the width of the line. 12700 = 1 pt.
* *
* @param lineWidth width in EMU's. 12700EMU's = 1 pt * @param lineWidth width in EMU's. 12700EMU's = 1 pt
*
* @see HSSFShape#LINEWIDTH_ONE_PT * @see HSSFShape#LINEWIDTH_ONE_PT
*/ */
public void setLineWidth(int lineWidth) { public void setLineWidth(int lineWidth) {
_lineWidth = lineWidth; setPropertyValue(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEWIDTH, lineWidth));
} }
/** /**
* @return One of the constants in LINESTYLE_* * @return One of the constants in LINESTYLE_*
*/ */
public int getLineStyle() { public int getLineStyle() {
return _lineStyle; EscherSimpleProperty property = _optRecord.lookup(EscherProperties.LINESTYLE__LINEDASHING);
if (null == property){
return LINESTYLE_DEFAULT;
}
return property.getPropertyValue();
} }
/** /**
* Sets the line style. * Sets the line style.
* *
* @param lineStyle One of the constants in LINESTYLE_* * @param lineStyle One of the constants in LINESTYLE_*
*/ */
public void setLineStyle(int lineStyle) { public void setLineStyle(int lineStyle) {
_lineStyle = lineStyle; setPropertyValue(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEDASHING, lineStyle));
if (getLineStyle() != HSSFShape.LINESTYLE_SOLID) {
setPropertyValue(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEENDCAPSTYLE, 0));
if (getLineStyle() == HSSFShape.LINESTYLE_NONE){
setPropertyValue(new EscherBoolProperty( EscherProperties.LINESTYLE__NOLINEDRAWDASH, 0x00080000));
} else {
setPropertyValue( new EscherBoolProperty( EscherProperties.LINESTYLE__NOLINEDRAWDASH, 0x00080008));
}
}
} }
/** /**
* @return <code>true</code> if this shape is not filled with a color. * @return <code>true</code> if this shape is not filled with a color.
*/ */
public boolean isNoFill() { public boolean isNoFill() {
return _noFill; EscherBoolProperty property = _optRecord.lookup(EscherProperties.FILL__NOFILLHITTEST);
return property == null ? NO_FILL_DEFAULT : property.getPropertyValue() == NO_FILLHITTEST_TRUE;
} }
/** /**
* Sets whether this shape is filled or transparent. * @param noFill sets whether this shape is filled or transparent.
*/ */
public void setNoFill(boolean noFill) { public void setNoFill(boolean noFill) {
_noFill = noFill; setPropertyValue(new EscherBoolProperty(EscherProperties.FILL__NOFILLHITTEST, noFill ? NO_FILLHITTEST_TRUE : NO_FILLHITTEST_FALSE));
}
protected void setPropertyValue(EscherProperty property){
_optRecord.setEscherProperty(property);
}
/**
* @param value specifies whether this shape is vertically flipped.
*/
public void setFlipVertical(boolean value){
EscherSpRecord sp = getEscherContainer().getChildById(EscherSpRecord.RECORD_ID);
if (value){
sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_FLIPVERT);
} else {
sp.setFlags(sp.getFlags() & (Integer.MAX_VALUE - EscherSpRecord.FLAG_FLIPVERT));
}
}
/**
* @param value specifies whether this shape is horizontally flipped.
*/
public void setFlipHorizontal(boolean value){
EscherSpRecord sp = getEscherContainer().getChildById(EscherSpRecord.RECORD_ID);
if (value){
sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_FLIPHORIZ);
} else {
sp.setFlags(sp.getFlags() & (Integer.MAX_VALUE - EscherSpRecord.FLAG_FLIPHORIZ));
}
}
/**
* @return whether this shape is vertically flipped.
*/
public boolean isFlipVertical(){
EscherSpRecord sp = getEscherContainer().getChildById(EscherSpRecord.RECORD_ID);
return (sp.getFlags() & EscherSpRecord.FLAG_FLIPVERT) != 0;
}
/**
* @return whether this shape is horizontally flipped.
*/
public boolean isFlipHorizontal(){
EscherSpRecord sp = getEscherContainer().getChildById(EscherSpRecord.RECORD_ID);
return (sp.getFlags() & EscherSpRecord.FLAG_FLIPHORIZ) != 0;
}
/**
* @return the rotation, in degrees, that is applied to a shape.
*/
public int getRotationDegree(){
ByteArrayOutputStream bos = new ByteArrayOutputStream();
EscherSimpleProperty property = getOptRecord().lookup(EscherProperties.TRANSFORM__ROTATION);
if (null == property){
return 0;
}
try {
LittleEndian.putInt(property.getPropertyValue(), bos);
return LittleEndian.getShort(bos.toByteArray(), 2);
} catch (IOException e) {
e.printStackTrace();
return 0;
}
}
/**
* specifies the rotation, in degrees, that is applied to a shape.
* Positive values specify rotation in the clockwise direction.
* Negative values specify rotation in the counterclockwise direction.
* Rotation occurs around the center of the shape.
* The default value for this property is 0x00000000
* @param value
*/
public void setRotationDegree(short value){
setPropertyValue(new EscherSimpleProperty(EscherProperties.TRANSFORM__ROTATION , (value << 16)));
} }
/** /**
@ -199,4 +383,18 @@ public abstract class HSSFShape {
public int countOfAllChildren() { public int countOfAllChildren() {
return 1; return 1;
} }
protected abstract HSSFShape cloneShape();
protected void setPatriarch(HSSFPatriarch _patriarch) {
this._patriarch = _patriarch;
}
public HSSFPatriarch getPatriarch() {
return _patriarch;
}
protected void setParent(HSSFShape parent) {
this.parent = parent;
}
} }

View File

@ -24,11 +24,50 @@ import java.util.List;
* *
* @author Glen Stampoultzis (glens at apache.org) * @author Glen Stampoultzis (glens at apache.org)
*/ */
public interface HSSFShapeContainer public interface HSSFShapeContainer extends Iterable<HSSFShape>
{ {
/** /**
* @return Any children contained by this shape. * @return Any children contained by this shape.
*/ */
List getChildren(); List<HSSFShape> getChildren();
/**
* add shape to the list of child records
* @param shape
*/
public void addShape(HSSFShape shape);
/**
* set coordinates of this group relative to the parent
*/
void setCoordinates( int x1, int y1, int x2, int y2 );
void clear();
/**
*@return The top left x coordinate of this group.
*/
public int getX1();
/**
*@return The top left y coordinate of this group.
*/
public int getY1();
/**
*@return The bottom right x coordinate of this group.
*/
public int getX2();
/**
* @return The bottom right y coordinate of this group.
*/
public int getY2();
/**
* remove first level shapes
* @param shape to be removed
* @return true if shape is removed else return false
*/
public boolean removeShape(HSSFShape shape);
} }

View File

@ -0,0 +1,131 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.poi.hssf.usermodel;
import org.apache.poi.ddf.*;
import org.apache.poi.hssf.record.*;
import org.apache.poi.poifs.filesystem.DirectoryNode;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* @author Evgeniy Berlog
* date: 05.06.12
*/
public class HSSFShapeFactory {
private final static short OBJECT_TYPE_LINE = 1;
private final static short OBJECT_TYPE_RECTANGLE = 2;
private final static short OBJECT_TYPE_OVAL = 3;
private final static short OBJECT_TYPE_ARC = 4;
private final static short OBJECT_TYPE_PICTURE = 8;
/**
* build shape tree from escher container
* @param container root escher container from which escher records must be taken
* @param agg - EscherAggregate
* @param out - shape container to which shapes must be added
* @param root - node to create HSSFObjectData shapes
*/
public static void createShapeTree(EscherContainerRecord container, EscherAggregate agg, HSSFShapeContainer out, DirectoryNode root) {
if (container.getRecordId() == EscherContainerRecord.SPGR_CONTAINER) {
ObjRecord obj = null;
EscherClientDataRecord clientData = ((EscherContainerRecord) container.getChild(0)).getChildById(EscherClientDataRecord.RECORD_ID);
if (null != clientData) {
obj = (ObjRecord) agg.getShapeToObjMapping().get(clientData);
}
HSSFShapeGroup group = new HSSFShapeGroup(container, obj);
List<EscherContainerRecord> children = container.getChildContainers();
// skip the first child record, it is group descriptor
for (int i = 0; i < children.size(); i++) {
EscherContainerRecord spContainer = children.get(i);
if (i != 0) {
createShapeTree(spContainer, agg, group, root);
}
}
out.addShape(group);
} else if (container.getRecordId() == EscherContainerRecord.SP_CONTAINER) {
Map<EscherRecord, Record> shapeToObj = agg.getShapeToObjMapping();
ObjRecord objRecord = null;
TextObjectRecord txtRecord = null;
for (EscherRecord record : container.getChildRecords()) {
switch (record.getRecordId()) {
case EscherClientDataRecord.RECORD_ID:
objRecord = (ObjRecord) shapeToObj.get(record);
break;
case EscherTextboxRecord.RECORD_ID:
txtRecord = (TextObjectRecord) shapeToObj.get(record);
break;
}
}
if (isEmbeddedObject(objRecord)) {
HSSFObjectData objectData = new HSSFObjectData(container, objRecord, root);
out.addShape(objectData);
return;
}
CommonObjectDataSubRecord cmo = (CommonObjectDataSubRecord) objRecord.getSubRecords().get(0);
HSSFShape shape;
switch (cmo.getObjectType()) {
case CommonObjectDataSubRecord.OBJECT_TYPE_PICTURE:
shape = new HSSFPicture(container, objRecord);
break;
case CommonObjectDataSubRecord.OBJECT_TYPE_RECTANGLE:
shape = new HSSFSimpleShape(container, objRecord, txtRecord);
break;
case CommonObjectDataSubRecord.OBJECT_TYPE_LINE:
shape = new HSSFSimpleShape(container, objRecord);
break;
case CommonObjectDataSubRecord.OBJECT_TYPE_COMBO_BOX:
shape = new HSSFCombobox(container, objRecord);
break;
case CommonObjectDataSubRecord.OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING:
EscherOptRecord optRecord = container.getChildById(EscherOptRecord.RECORD_ID);
EscherProperty property = optRecord.lookup(EscherProperties.GEOMETRY__VERTICES);
if (null != property) {
shape = new HSSFPolygon(container, objRecord, txtRecord);
} else {
shape = new HSSFSimpleShape(container, objRecord, txtRecord);
}
break;
case CommonObjectDataSubRecord.OBJECT_TYPE_TEXT:
shape = new HSSFTextbox(container, objRecord, txtRecord);
break;
case CommonObjectDataSubRecord.OBJECT_TYPE_COMMENT:
shape = new HSSFComment(container, objRecord, txtRecord, agg.getNoteRecordByObj(objRecord));
break;
default:
shape = new HSSFSimpleShape(container, objRecord, txtRecord);
}
out.addShape(shape);
}
}
private static boolean isEmbeddedObject(ObjRecord obj) {
Iterator<SubRecord> subRecordIter = obj.getSubRecords().iterator();
while (subRecordIter.hasNext()) {
SubRecord sub = subRecordIter.next();
if (sub instanceof EmbeddedObjectRefSubRecord) {
return true;
}
}
return false;
}
}

View File

@ -17,7 +17,11 @@
package org.apache.poi.hssf.usermodel; package org.apache.poi.hssf.usermodel;
import org.apache.poi.ddf.*;
import org.apache.poi.hssf.record.*;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Iterator; import java.util.Iterator;
@ -27,159 +31,357 @@ import java.util.Iterator;
* *
* @author Glen Stampoultzis (glens at apache.org) * @author Glen Stampoultzis (glens at apache.org)
*/ */
public class HSSFShapeGroup public class HSSFShapeGroup extends HSSFShape implements HSSFShapeContainer {
extends HSSFShape private final List<HSSFShape> shapes = new ArrayList<HSSFShape>();
implements HSSFShapeContainer private EscherSpgrRecord _spgrRecord;
{
List<HSSFShape> shapes = new ArrayList<HSSFShape>();
int x1 = 0;
int y1 = 0 ;
int x2 = 1023;
int y2 = 255;
public HSSFShapeGroup(EscherContainerRecord spgrContainer, ObjRecord objRecord) {
super(spgrContainer, objRecord);
public HSSFShapeGroup( HSSFShape parent, HSSFAnchor anchor ) // read internal and external coordinates from spgrContainer
{ EscherContainerRecord spContainer = spgrContainer.getChildContainers().get(0);
super( parent, anchor ); _spgrRecord = (EscherSpgrRecord) spContainer.getChild(0);
for (EscherRecord ch : spContainer.getChildRecords()) {
switch (ch.getRecordId()) {
case EscherSpgrRecord.RECORD_ID:
break;
case EscherClientAnchorRecord.RECORD_ID:
anchor = new HSSFClientAnchor((EscherClientAnchorRecord) ch);
break;
case EscherChildAnchorRecord.RECORD_ID:
anchor = new HSSFChildAnchor((EscherChildAnchorRecord) ch);
break;
}
}
}
public HSSFShapeGroup(HSSFShape parent, HSSFAnchor anchor) {
super(parent, anchor);
_spgrRecord = ((EscherContainerRecord)getEscherContainer().getChild(0)).getChildById(EscherSpgrRecord.RECORD_ID);
}
@Override
protected EscherContainerRecord createSpContainer() {
EscherContainerRecord spgrContainer = new EscherContainerRecord();
EscherContainerRecord spContainer = new EscherContainerRecord();
EscherSpgrRecord spgr = new EscherSpgrRecord();
EscherSpRecord sp = new EscherSpRecord();
EscherOptRecord opt = new EscherOptRecord();
EscherRecord anchor;
EscherClientDataRecord clientData = new EscherClientDataRecord();
spgrContainer.setRecordId(EscherContainerRecord.SPGR_CONTAINER);
spgrContainer.setOptions((short) 0x000F);
spContainer.setRecordId(EscherContainerRecord.SP_CONTAINER);
spContainer.setOptions((short) 0x000F);
spgr.setRecordId(EscherSpgrRecord.RECORD_ID);
spgr.setOptions((short) 0x0001);
spgr.setRectX1(0);
spgr.setRectY1(0);
spgr.setRectX2(1023);
spgr.setRectY2(255);
sp.setRecordId(EscherSpRecord.RECORD_ID);
sp.setOptions((short) 0x0002);
if (getAnchor() instanceof HSSFClientAnchor) {
sp.setFlags(EscherSpRecord.FLAG_GROUP | EscherSpRecord.FLAG_HAVEANCHOR);
} else {
sp.setFlags(EscherSpRecord.FLAG_GROUP | EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_CHILD);
}
opt.setRecordId(EscherOptRecord.RECORD_ID);
opt.setOptions((short) 0x0023);
opt.addEscherProperty(new EscherBoolProperty(EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 0x00040004));
opt.addEscherProperty(new EscherBoolProperty(EscherProperties.GROUPSHAPE__PRINT, 0x00080000));
anchor = getAnchor().getEscherAnchor();
clientData.setRecordId(EscherClientDataRecord.RECORD_ID);
clientData.setOptions((short) 0x0000);
spgrContainer.addChildRecord(spContainer);
spContainer.addChildRecord(spgr);
spContainer.addChildRecord(sp);
spContainer.addChildRecord(opt);
spContainer.addChildRecord(anchor);
spContainer.addChildRecord(clientData);
return spgrContainer;
}
@Override
protected ObjRecord createObjRecord() {
ObjRecord obj = new ObjRecord();
CommonObjectDataSubRecord cmo = new CommonObjectDataSubRecord();
cmo.setObjectType(CommonObjectDataSubRecord.OBJECT_TYPE_GROUP);
cmo.setLocked(true);
cmo.setPrintable(true);
cmo.setAutofill(true);
cmo.setAutoline(true);
GroupMarkerSubRecord gmo = new GroupMarkerSubRecord();
EndSubRecord end = new EndSubRecord();
obj.addSubRecord(cmo);
obj.addSubRecord(gmo);
obj.addSubRecord(end);
return obj;
}
@Override
protected void afterRemove(HSSFPatriarch patriarch) {
patriarch._getBoundAggregate().removeShapeToObjRecord(getEscherContainer().getChildContainers().get(0)
.getChildById(EscherClientDataRecord.RECORD_ID));
for ( int i=0; i<shapes.size(); i++ ) {
HSSFShape shape = shapes.get(i);
removeShape(shape);
shape.afterRemove(getPatriarch());
}
shapes.clear();
}
private void onCreate(HSSFShape shape){
if(getPatriarch() != null){
EscherContainerRecord spContainer = shape.getEscherContainer();
int shapeId = getPatriarch().newShapeId();
shape.setShapeId(shapeId);
getEscherContainer().addChildRecord(spContainer);
shape.afterInsert(getPatriarch());
EscherSpRecord sp;
if (shape instanceof HSSFShapeGroup){
sp = shape.getEscherContainer().getChildContainers().get(0).getChildById(EscherSpRecord.RECORD_ID);
} else {
sp = shape.getEscherContainer().getChildById(EscherSpRecord.RECORD_ID);
}
sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_CHILD);
}
} }
/** /**
* Create another group under this group. * Create another group under this group.
* @param anchor the position of the new group. *
* @return the group * @param anchor the position of the new group.
* @return the group
*/ */
public HSSFShapeGroup createGroup(HSSFChildAnchor anchor) public HSSFShapeGroup createGroup(HSSFChildAnchor anchor) {
{
HSSFShapeGroup group = new HSSFShapeGroup(this, anchor); HSSFShapeGroup group = new HSSFShapeGroup(this, anchor);
group.anchor = anchor; group.setParent(this);
group.setAnchor(anchor);
shapes.add(group); shapes.add(group);
onCreate(group);
return group; return group;
} }
public void addShape(HSSFShape shape){ public void addShape(HSSFShape shape) {
shape._patriarch = this._patriarch; shape.setPatriarch(this.getPatriarch());
shape.setParent(this);
shapes.add(shape); shapes.add(shape);
} }
/** /**
* Create a new simple shape under this group. * Create a new simple shape under this group.
* @param anchor the position of the shape. *
* @return the shape * @param anchor the position of the shape.
* @return the shape
*/ */
public HSSFSimpleShape createShape(HSSFChildAnchor anchor) public HSSFSimpleShape createShape(HSSFChildAnchor anchor) {
{
HSSFSimpleShape shape = new HSSFSimpleShape(this, anchor); HSSFSimpleShape shape = new HSSFSimpleShape(this, anchor);
shape.anchor = anchor; shape.setParent(this);
shape.setAnchor(anchor);
shapes.add(shape); shapes.add(shape);
onCreate(shape);
EscherSpRecord sp = shape.getEscherContainer().getChildById(EscherSpRecord.RECORD_ID);
if (shape.getAnchor().isHorizontallyFlipped()){
sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_FLIPHORIZ);
}
if (shape.getAnchor().isVerticallyFlipped()){
sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_FLIPVERT);
}
return shape; return shape;
} }
/** /**
* Create a new textbox under this group. * Create a new textbox under this group.
* @param anchor the position of the shape. *
* @return the textbox * @param anchor the position of the shape.
* @return the textbox
*/ */
public HSSFTextbox createTextbox(HSSFChildAnchor anchor) public HSSFTextbox createTextbox(HSSFChildAnchor anchor) {
{
HSSFTextbox shape = new HSSFTextbox(this, anchor); HSSFTextbox shape = new HSSFTextbox(this, anchor);
shape.anchor = anchor; shape.setParent(this);
shape.setAnchor(anchor);
shapes.add(shape); shapes.add(shape);
onCreate(shape);
return shape; return shape;
} }
/** /**
* Creates a polygon * Creates a polygon
* *
* @param anchor the client anchor describes how this group is attached * @param anchor the client anchor describes how this group is attached
* to the sheet. * to the sheet.
* @return the newly created shape. * @return the newly created shape.
*/ */
public HSSFPolygon createPolygon(HSSFChildAnchor anchor) public HSSFPolygon createPolygon(HSSFChildAnchor anchor) {
{
HSSFPolygon shape = new HSSFPolygon(this, anchor); HSSFPolygon shape = new HSSFPolygon(this, anchor);
shape.anchor = anchor; shape.setParent(this);
shape.setAnchor(anchor);
shapes.add(shape); shapes.add(shape);
onCreate(shape);
return shape; return shape;
} }
/** /**
* Creates a picture. * Creates a picture.
* *
* @param anchor the client anchor describes how this group is attached * @param anchor the client anchor describes how this group is attached
* to the sheet. * to the sheet.
* @return the newly created shape. * @return the newly created shape.
*/ */
public HSSFPicture createPicture(HSSFChildAnchor anchor, int pictureIndex) public HSSFPicture createPicture(HSSFChildAnchor anchor, int pictureIndex) {
{ HSSFPicture shape = new HSSFPicture(this, anchor);
HSSFPicture shape = new HSSFPicture(this, anchor); shape.setParent(this);
shape.anchor = anchor; shape.setAnchor(anchor);
shape.setPictureIndex( pictureIndex ); shape.setPictureIndex(pictureIndex);
shapes.add(shape); shapes.add(shape);
return shape; onCreate(shape);
EscherSpRecord sp = shape.getEscherContainer().getChildById(EscherSpRecord.RECORD_ID);
if (shape.getAnchor().isHorizontallyFlipped()){
sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_FLIPHORIZ);
}
if (shape.getAnchor().isVerticallyFlipped()){
sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_FLIPVERT);
}
return shape;
} }
/** /**
* Return all children contained by this shape. * Return all children contained by this shape.
*/ */
public List<HSSFShape> getChildren() public List<HSSFShape> getChildren() {
{ return Collections.unmodifiableList(shapes);
return shapes;
} }
/** /**
* Sets the coordinate space of this group. All children are constrained * Sets the coordinate space of this group. All children are constrained
* to these coordinates. * to these coordinates.
*/ */
public void setCoordinates( int x1, int y1, int x2, int y2 ) public void setCoordinates(int x1, int y1, int x2, int y2) {
{ _spgrRecord.setRectX1(x1);
this.x1 = x1; _spgrRecord.setRectX2(x2);
this.y1 = y1; _spgrRecord.setRectY1(y1);
this.x2 = x2; _spgrRecord.setRectY2(y2);
this.y2 = y2; }
public void clear() {
ArrayList <HSSFShape> copy = new ArrayList<HSSFShape>(shapes);
for (HSSFShape shape: copy){
removeShape(shape);
}
} }
/** /**
* The top left x coordinate of this group. * The top left x coordinate of this group.
*/ */
public int getX1() public int getX1() {
{ return _spgrRecord.getRectX1();
return x1;
} }
/** /**
* The top left y coordinate of this group. * The top left y coordinate of this group.
*/ */
public int getY1() public int getY1() {
{ return _spgrRecord.getRectY1();
return y1;
} }
/** /**
* The bottom right x coordinate of this group. * The bottom right x coordinate of this group.
*/ */
public int getX2() public int getX2() {
{ return _spgrRecord.getRectX2();
return x2;
} }
/** /**
* The bottom right y coordinate of this group. * The bottom right y coordinate of this group.
*/ */
public int getY2() public int getY2() {
{ return _spgrRecord.getRectY2();
return y2;
} }
/** /**
* Count of all children and their childrens children. * Count of all children and their childrens children.
*/ */
public int countOfAllChildren() public int countOfAllChildren() {
{
int count = shapes.size(); int count = shapes.size();
for ( Iterator iterator = shapes.iterator(); iterator.hasNext(); ) for (Iterator iterator = shapes.iterator(); iterator.hasNext(); ) {
{
HSSFShape shape = (HSSFShape) iterator.next(); HSSFShape shape = (HSSFShape) iterator.next();
count += shape.countOfAllChildren(); count += shape.countOfAllChildren();
} }
return count; return count;
} }
@Override
void afterInsert(HSSFPatriarch patriarch){
EscherAggregate agg = patriarch._getBoundAggregate();
EscherContainerRecord containerRecord = getEscherContainer().getChildById(EscherContainerRecord.SP_CONTAINER);
agg.associateShapeToObjRecord(containerRecord.getChildById(EscherClientDataRecord.RECORD_ID), getObjRecord());
}
@Override
void setShapeId(int shapeId){
EscherContainerRecord containerRecord = getEscherContainer().getChildById(EscherContainerRecord.SP_CONTAINER);
EscherSpRecord spRecord = containerRecord.getChildById(EscherSpRecord.RECORD_ID);
spRecord.setShapeId(shapeId);
CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) getObjRecord().getSubRecords().get(0);
cod.setObjectId((short) (shapeId % 1024));
}
@Override
int getShapeId(){
EscherContainerRecord containerRecord = getEscherContainer().getChildById(EscherContainerRecord.SP_CONTAINER);
return ((EscherSpRecord)containerRecord.getChildById(EscherSpRecord.RECORD_ID)).getShapeId();
}
@Override
protected HSSFShape cloneShape() {
throw new IllegalStateException("Use method cloneShape(HSSFPatriarch patriarch)");
}
protected HSSFShape cloneShape(HSSFPatriarch patriarch) {
EscherContainerRecord spgrContainer = new EscherContainerRecord();
spgrContainer.setRecordId(EscherContainerRecord.SPGR_CONTAINER);
spgrContainer.setOptions((short) 0x000F);
EscherContainerRecord spContainer = new EscherContainerRecord();
EscherContainerRecord cont = getEscherContainer().getChildById(EscherContainerRecord.SP_CONTAINER);
byte [] inSp = cont.serialize();
spContainer.fillFields(inSp, 0, new DefaultEscherRecordFactory());
spgrContainer.addChildRecord(spContainer);
ObjRecord obj = null;
if (null != getObjRecord()){
obj = (ObjRecord) getObjRecord().cloneViaReserialise();
}
HSSFShapeGroup group = new HSSFShapeGroup(spgrContainer, obj);
group.setPatriarch(patriarch);
for (HSSFShape shape: getChildren()){
HSSFShape newShape;
if (shape instanceof HSSFShapeGroup){
newShape = ((HSSFShapeGroup)shape).cloneShape(patriarch);
} else {
newShape = shape.cloneShape();
}
group.addShape(newShape);
group.onCreate(newShape);
}
return group;
}
public boolean removeShape(HSSFShape shape) {
boolean isRemoved = getEscherContainer().removeChildRecord(shape.getEscherContainer());
if (isRemoved){
shape.afterRemove(this.getPatriarch());
shapes.remove(shape);
}
return isRemoved;
}
public Iterator<HSSFShape> iterator() {
return shapes.iterator();
}
} }

View File

@ -0,0 +1,224 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.usermodel;
public interface HSSFShapeTypes {
public static final int NotPrimitive = 0;
public static final int Rectangle = 1;
public static final int RoundRectangle = 2;
public static final int Ellipse = 3;
public static final int Diamond = 4;
public static final int IsocelesTriangle = 5;
public static final int RightTriangle = 6;
public static final int Parallelogram = 7;
public static final int Trapezoid = 8;
public static final int Hexagon = 9;
public static final int Octagon = 10;
public static final int Plus = 11;
public static final int Star = 12;
public static final int Arrow = 13;
public static final int ThickArrow = 14;
public static final int HomePlate = 15;
public static final int Cube = 16;
public static final int Balloon = 17;
public static final int Seal = 18;
public static final int Arc = 19;
public static final int Line = 20;
public static final int Plaque = 21;
public static final int Can = 22;
public static final int Donut = 23;
public static final int TextSimple = 24;
public static final int TextOctagon = 25;
public static final int TextHexagon = 26;
public static final int TextCurve = 27;
public static final int TextWave = 28;
public static final int TextRing = 29;
public static final int TextOnCurve = 30;
public static final int TextOnRing = 31;
public static final int StraightConnector1 = 32;
public static final int BentConnector2 = 33;
public static final int BentConnector3 = 34;
public static final int BentConnector4 = 35;
public static final int BentConnector5 = 36;
public static final int CurvedConnector2 = 37;
public static final int CurvedConnector3 = 38;
public static final int CurvedConnector4 = 39;
public static final int CurvedConnector5 = 40;
public static final int Callout1 = 41;
public static final int Callout2 = 42;
public static final int Callout3 = 43;
public static final int AccentCallout1 = 44;
public static final int AccentCallout2 = 45;
public static final int AccentCallout3 = 46;
public static final int BorderCallout1 = 47;
public static final int BorderCallout2 = 48;
public static final int BorderCallout3 = 49;
public static final int AccentBorderCallout1 = 50;
public static final int AccentBorderCallout2 = 51;
public static final int AccentBorderCallout3 = 52;
public static final int Ribbon = 53;
public static final int Ribbon2 = 54;
public static final int Chevron = 55;
public static final int Pentagon = 56;
public static final int NoSmoking = 57;
public static final int Star8 = 58;
public static final int Star16 = 59;
public static final int Star32 = 60;
public static final int WedgeRectCallout = 61;
public static final int WedgeRRectCallout = 62;
public static final int WedgeEllipseCallout = 63;
public static final int Wave = 64;
public static final int FoldedCorner = 65;
public static final int LeftArrow = 66;
public static final int DownArrow = 67;
public static final int UpArrow = 68;
public static final int LeftRightArrow = 69;
public static final int UpDownArrow = 70;
public static final int IrregularSeal1 = 71;
public static final int IrregularSeal2 = 72;
public static final int LightningBolt = 73;
public static final int Heart = 74;
public static final int PictureFrame = 75;
public static final int QuadArrow = 76;
public static final int LeftArrowCallout = 77;
public static final int RightArrowCallout = 78;
public static final int UpArrowCallout = 79;
public static final int DownArrowCallout = 80;
public static final int LeftRightArrowCallout = 81;
public static final int UpDownArrowCallout = 82;
public static final int QuadArrowCallout = 83;
public static final int Bevel = 84;
public static final int LeftBracket = 85;
public static final int RightBracket = 86;
public static final int LeftBrace = 87;
public static final int RightBrace = 88;
public static final int LeftUpArrow = 89;
public static final int BentUpArrow = 90;
public static final int BentArrow = 91;
public static final int Star24 = 92;
public static final int StripedRightArrow = 93;
public static final int NotchedRightArrow = 94;
public static final int BlockArc = 95;
public static final int SmileyFace = 96;
public static final int VerticalScroll = 97;
public static final int HorizontalScroll = 98;
public static final int CircularArrow = 99;
public static final int NotchedCircularArrow = 100;
public static final int UturnArrow = 101;
public static final int CurvedRightArrow = 102;
public static final int CurvedLeftArrow = 103;
public static final int CurvedUpArrow = 104;
public static final int CurvedDownArrow = 105;
public static final int CloudCallout = 106;
public static final int EllipseRibbon = 107;
public static final int EllipseRibbon2 = 108;
public static final int FlowChartProcess = 109;
public static final int FlowChartDecision = 110;
public static final int FlowChartInputOutput = 111;
public static final int FlowChartPredefinedProcess = 112;
public static final int FlowChartInternalStorage = 113;
public static final int FlowChartDocument = 114;
public static final int FlowChartMultidocument = 115;
public static final int FlowChartTerminator = 116;
public static final int FlowChartPreparation = 117;
public static final int FlowChartManualInput = 118;
public static final int FlowChartManualOperation = 119;
public static final int FlowChartConnector = 120;
public static final int FlowChartPunchedCard = 121;
public static final int FlowChartPunchedTape = 122;
public static final int FlowChartSummingJunction = 123;
public static final int FlowChartOr = 124;
public static final int FlowChartCollate = 125;
public static final int FlowChartSort = 126;
public static final int FlowChartExtract = 127;
public static final int FlowChartMerge = 128;
public static final int FlowChartOfflineStorage = 129;
public static final int FlowChartOnlineStorage = 130;
public static final int FlowChartMagneticTape = 131;
public static final int FlowChartMagneticDisk = 132;
public static final int FlowChartMagneticDrum = 133;
public static final int FlowChartDisplay = 134;
public static final int FlowChartDelay = 135;
public static final int TextPlainText = 136;
public static final int TextStop = 137;
public static final int TextTriangle = 138;
public static final int TextTriangleInverted = 139;
public static final int TextChevron = 140;
public static final int TextChevronInverted = 141;
public static final int TextRingInside = 142;
public static final int TextRingOutside = 143;
public static final int TextArchUpCurve = 144;
public static final int TextArchDownCurve = 145;
public static final int TextCircleCurve = 146;
public static final int TextButtonCurve = 147;
public static final int TextArchUpPour = 148;
public static final int TextArchDownPour = 149;
public static final int TextCirclePour = 150;
public static final int TextButtonPour = 151;
public static final int TextCurveUp = 152;
public static final int TextCurveDown = 153;
public static final int TextCascadeUp = 154;
public static final int TextCascadeDown = 155;
public static final int TextWave1 = 156;
public static final int TextWave2 = 157;
public static final int TextWave3 = 158;
public static final int TextWave4 = 159;
public static final int TextInflate = 160;
public static final int TextDeflate = 161;
public static final int TextInflateBottom = 162;
public static final int TextDeflateBottom = 163;
public static final int TextInflateTop = 164;
public static final int TextDeflateTop = 165;
public static final int TextDeflateInflate = 166;
public static final int TextDeflateInflateDeflate = 167;
public static final int TextFadeRight = 168;
public static final int TextFadeLeft = 169;
public static final int TextFadeUp = 170;
public static final int TextFadeDown = 171;
public static final int TextSlantUp = 172;
public static final int TextSlantDown = 173;
public static final int TextCanUp = 174;
public static final int TextCanDown = 175;
public static final int FlowChartAlternateProcess = 176;
public static final int FlowChartOffpageConnector = 177;
public static final int Callout90 = 178;
public static final int AccentCallout90 = 179;
public static final int BorderCallout90 = 180;
public static final int AccentBorderCallout90 = 181;
public static final int LeftRightUpArrow = 182;
public static final int Sun = 183;
public static final int Moon = 184;
public static final int BracketPair = 185;
public static final int BracePair = 186;
public static final int Star4 = 187;
public static final int DoubleWave = 188;
public static final int ActionButtonBlank = 189;
public static final int ActionButtonHome = 190;
public static final int ActionButtonHelp = 191;
public static final int ActionButtonInformation = 192;
public static final int ActionButtonForwardNext = 193;
public static final int ActionButtonBackPrevious = 194;
public static final int ActionButtonEnd = 195;
public static final int ActionButtonBeginning = 196;
public static final int ActionButtonReturn = 197;
public static final int ActionButtonDocument = 198;
public static final int ActionButtonSound = 199;
public static final int ActionButtonMovie = 200;
public static final int HostControl = 201;
public static final int TextBox = 202;
}

File diff suppressed because it is too large Load Diff

View File

@ -17,25 +17,29 @@
package org.apache.poi.hssf.usermodel; package org.apache.poi.hssf.usermodel;
import org.apache.poi.ddf.*;
import org.apache.poi.hssf.record.*;
import org.apache.poi.ss.usermodel.RichTextString;
/** /**
* Represents a simple shape such as a line, rectangle or oval. * Represents a simple shape such as a line, rectangle or oval.
* *
* @author Glen Stampoultzis (glens at apache.org) * @author Glen Stampoultzis (glens at apache.org)
*/ */
public class HSSFSimpleShape public class HSSFSimpleShape extends HSSFShape
extends HSSFShape
{ {
// The commented out ones haven't been tested yet or aren't supported // The commented out ones haven't been tested yet or aren't supported
// by HSSFSimpleShape. // by HSSFSimpleShape.
public final static short OBJECT_TYPE_LINE = 1; public final static short OBJECT_TYPE_LINE = HSSFShapeTypes.Line;
public final static short OBJECT_TYPE_RECTANGLE = 2; public final static short OBJECT_TYPE_RECTANGLE = HSSFShapeTypes.Rectangle;
public final static short OBJECT_TYPE_OVAL = 3; public final static short OBJECT_TYPE_OVAL = HSSFShapeTypes.Ellipse;
// public final static short OBJECT_TYPE_ARC = 4; public final static short OBJECT_TYPE_ARC = HSSFShapeTypes.Arc;
// public final static short OBJECT_TYPE_CHART = 5; // public final static short OBJECT_TYPE_CHART = 5;
// public final static short OBJECT_TYPE_TEXT = 6; // public final static short OBJECT_TYPE_TEXT = 6;
// public final static short OBJECT_TYPE_BUTTON = 7; // public final static short OBJECT_TYPE_BUTTON = 7;
public final static short OBJECT_TYPE_PICTURE = 8; public final static short OBJECT_TYPE_PICTURE = HSSFShapeTypes.PictureFrame;
// public final static short OBJECT_TYPE_POLYGON = 9; // public final static short OBJECT_TYPE_POLYGON = 9;
// public final static short OBJECT_TYPE_CHECKBOX = 11; // public final static short OBJECT_TYPE_CHECKBOX = 11;
// public final static short OBJECT_TYPE_OPTION_BUTTON = 12; // public final static short OBJECT_TYPE_OPTION_BUTTON = 12;
@ -46,17 +50,156 @@ public class HSSFSimpleShape
// public final static short OBJECT_TYPE_SCROLL_BAR = 17; // public final static short OBJECT_TYPE_SCROLL_BAR = 17;
// public final static short OBJECT_TYPE_LIST_BOX = 18; // public final static short OBJECT_TYPE_LIST_BOX = 18;
// public final static short OBJECT_TYPE_GROUP_BOX = 19; // public final static short OBJECT_TYPE_GROUP_BOX = 19;
public final static short OBJECT_TYPE_COMBO_BOX = 20; public final static short OBJECT_TYPE_COMBO_BOX = HSSFShapeTypes.HostControl;
public final static short OBJECT_TYPE_COMMENT = 25; public final static short OBJECT_TYPE_COMMENT = HSSFShapeTypes.TextBox;
// public final static short OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING = 30; public final static short OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING = 30;
int shapeType = OBJECT_TYPE_LINE; public final static int WRAP_SQUARE = 0;
public final static int WRAP_BY_POINTS = 1;
public final static int WRAP_NONE = 2;
public HSSFSimpleShape( HSSFShape parent, HSSFAnchor anchor ) private TextObjectRecord _textObjectRecord;
public HSSFSimpleShape(EscherContainerRecord spContainer, ObjRecord objRecord, TextObjectRecord textObjectRecord) {
super(spContainer, objRecord);
this._textObjectRecord = textObjectRecord;
}
public HSSFSimpleShape(EscherContainerRecord spContainer, ObjRecord objRecord) {
super(spContainer, objRecord);
}
public HSSFSimpleShape( HSSFShape parent, HSSFAnchor anchor)
{ {
super( parent, anchor ); super( parent, anchor );
_textObjectRecord = createTextObjRecord();
} }
protected TextObjectRecord getTextObjectRecord() {
return _textObjectRecord;
}
protected TextObjectRecord createTextObjRecord(){
TextObjectRecord obj = new TextObjectRecord();
obj.setHorizontalTextAlignment(2);
obj.setVerticalTextAlignment(2);
obj.setTextLocked(true);
obj.setTextOrientation(TextObjectRecord.TEXT_ORIENTATION_NONE);
obj.setStr(new HSSFRichTextString(""));
return obj;
}
@Override
protected EscherContainerRecord createSpContainer() {
EscherContainerRecord spContainer = new EscherContainerRecord();
spContainer.setRecordId( EscherContainerRecord.SP_CONTAINER );
spContainer.setOptions( (short) 0x000F );
EscherSpRecord sp = new EscherSpRecord();
sp.setRecordId( EscherSpRecord.RECORD_ID );
sp.setFlags( EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HASSHAPETYPE );
sp.setVersion((short) 0x2);
EscherClientDataRecord clientData = new EscherClientDataRecord();
clientData.setRecordId( EscherClientDataRecord.RECORD_ID );
clientData.setOptions( (short) (0x0000) );
EscherOptRecord optRecord = new EscherOptRecord();
optRecord.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEDASHING, LINESTYLE_SOLID));
optRecord.setEscherProperty( new EscherBoolProperty( EscherProperties.LINESTYLE__NOLINEDRAWDASH, 0x00080008));
// optRecord.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEWIDTH, LINEWIDTH_DEFAULT));
optRecord.setEscherProperty(new EscherRGBProperty(EscherProperties.FILL__FILLCOLOR, FILL__FILLCOLOR_DEFAULT));
optRecord.setEscherProperty(new EscherRGBProperty(EscherProperties.LINESTYLE__COLOR, LINESTYLE__COLOR_DEFAULT));
optRecord.setEscherProperty(new EscherBoolProperty(EscherProperties.FILL__NOFILLHITTEST, NO_FILLHITTEST_FALSE));
optRecord.setEscherProperty( new EscherBoolProperty( EscherProperties.LINESTYLE__NOLINEDRAWDASH, 0x00080008));
optRecord.setEscherProperty( new EscherShapePathProperty( EscherProperties.GEOMETRY__SHAPEPATH, EscherShapePathProperty.COMPLEX ) );
optRecord.setEscherProperty(new EscherBoolProperty( EscherProperties.GROUPSHAPE__PRINT, 0x080000));
optRecord.setRecordId( EscherOptRecord.RECORD_ID );
EscherTextboxRecord escherTextbox = new EscherTextboxRecord();
escherTextbox.setRecordId(EscherTextboxRecord.RECORD_ID);
escherTextbox.setOptions((short) 0x0000);
spContainer.addChildRecord(sp);
spContainer.addChildRecord(optRecord);
spContainer.addChildRecord(getAnchor().getEscherAnchor());
spContainer.addChildRecord(clientData);
spContainer.addChildRecord(escherTextbox);
return spContainer;
}
@Override
protected ObjRecord createObjRecord() {
ObjRecord obj = new ObjRecord();
CommonObjectDataSubRecord c = new CommonObjectDataSubRecord();
c.setLocked(true);
c.setPrintable(true);
c.setAutofill(true);
c.setAutoline(true);
EndSubRecord e = new EndSubRecord();
obj.addSubRecord(c);
obj.addSubRecord(e);
return obj;
}
@Override
protected void afterRemove(HSSFPatriarch patriarch) {
patriarch._getBoundAggregate().removeShapeToObjRecord(getEscherContainer().getChildById(EscherClientDataRecord.RECORD_ID));
if (null != getEscherContainer().getChildById(EscherTextboxRecord.RECORD_ID)){
patriarch._getBoundAggregate().removeShapeToObjRecord(getEscherContainer().getChildById(EscherTextboxRecord.RECORD_ID));
}
}
/**
* @return the rich text string for this textbox.
*/
public HSSFRichTextString getString() {
return _textObjectRecord.getStr();
}
/**
* @param string Sets the rich text string used by this object.
*/
public void setString(RichTextString string) {
//TODO add other shape types which can not contain text
if (getShapeType() == 0 || getShapeType() == OBJECT_TYPE_LINE){
throw new IllegalStateException("Cannot set text for shape type: "+getShapeType());
}
HSSFRichTextString rtr = (HSSFRichTextString) string;
// If font is not set we must set the default one
if (rtr.numFormattingRuns() == 0) rtr.applyFont((short) 0);
_textObjectRecord.setStr(rtr);
if (string.getString() != null){
setPropertyValue(new EscherSimpleProperty(EscherProperties.TEXT__TEXTID, string.getString().hashCode()));
}
}
@Override
void afterInsert(HSSFPatriarch patriarch){
EscherAggregate agg = patriarch._getBoundAggregate();
agg.associateShapeToObjRecord(getEscherContainer().getChildById(EscherClientDataRecord.RECORD_ID), getObjRecord());
if (null != getTextObjectRecord()){
agg.associateShapeToObjRecord(getEscherContainer().getChildById(EscherTextboxRecord.RECORD_ID), getTextObjectRecord());
}
}
@Override
protected HSSFShape cloneShape() {
TextObjectRecord txo = null;
EscherContainerRecord spContainer = new EscherContainerRecord();
byte [] inSp = getEscherContainer().serialize();
spContainer.fillFields(inSp, 0, new DefaultEscherRecordFactory());
ObjRecord obj = (ObjRecord) getObjRecord().cloneViaReserialise();
if (getTextObjectRecord() != null && getString() != null && null != getString().getString()){
txo = (TextObjectRecord) getTextObjectRecord().cloneViaReserialise();
}
return new HSSFSimpleShape(spContainer, obj, txo);
}
/** /**
* Gets the shape type. * Gets the shape type.
* @return One of the OBJECT_TYPE_* constants. * @return One of the OBJECT_TYPE_* constants.
@ -67,19 +210,28 @@ public class HSSFSimpleShape
* @see #OBJECT_TYPE_PICTURE * @see #OBJECT_TYPE_PICTURE
* @see #OBJECT_TYPE_COMMENT * @see #OBJECT_TYPE_COMMENT
*/ */
public int getShapeType() { return shapeType; } public int getShapeType() {
EscherSpRecord spRecord = getEscherContainer().getChildById(EscherSpRecord.RECORD_ID);
return spRecord.getShapeType();
}
public int getWrapText(){
EscherSimpleProperty property = getOptRecord().lookup(EscherProperties.TEXT__WRAPTEXT);
return null == property ? WRAP_SQUARE : property.getPropertyValue();
}
public void setWrapText(int value){
setPropertyValue(new EscherSimpleProperty(EscherProperties.TEXT__WRAPTEXT, false, false, value));
}
/** /**
* Sets the shape types. * @see HSSFShapeTypes
* * @param value - shapeType
* @param shapeType One of the OBJECT_TYPE_* constants.
*
* @see #OBJECT_TYPE_LINE
* @see #OBJECT_TYPE_OVAL
* @see #OBJECT_TYPE_RECTANGLE
* @see #OBJECT_TYPE_PICTURE
* @see #OBJECT_TYPE_COMMENT
*/ */
public void setShapeType( int shapeType ){ this.shapeType = shapeType; } public void setShapeType(int value){
CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) getObjRecord().getSubRecords().get(0);
cod.setObjectType(OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING);
EscherSpRecord spRecord = getEscherContainer().getChildById(EscherSpRecord.RECORD_ID);
spRecord.setShapeType((short) value);
}
} }

View File

@ -17,6 +17,8 @@
package org.apache.poi.hssf.usermodel; package org.apache.poi.hssf.usermodel;
import org.apache.poi.ddf.*;
import org.apache.poi.hssf.record.*;
import org.apache.poi.ss.usermodel.RichTextString; import org.apache.poi.ss.usermodel.RichTextString;
/** /**
@ -24,163 +26,222 @@ import org.apache.poi.ss.usermodel.RichTextString;
* *
* @author Glen Stampoultzis (glens at apache.org) * @author Glen Stampoultzis (glens at apache.org)
*/ */
public class HSSFTextbox public class HSSFTextbox extends HSSFSimpleShape {
extends HSSFSimpleShape public final static short OBJECT_TYPE_TEXT = 6;
{
public final static short OBJECT_TYPE_TEXT = 6;
/** /**
* How to align text horizontally * How to align text horizontally
*/ */
public final static short HORIZONTAL_ALIGNMENT_LEFT = 1; public final static short HORIZONTAL_ALIGNMENT_LEFT = 1;
public final static short HORIZONTAL_ALIGNMENT_CENTERED = 2; public final static short HORIZONTAL_ALIGNMENT_CENTERED = 2;
public final static short HORIZONTAL_ALIGNMENT_RIGHT = 3; public final static short HORIZONTAL_ALIGNMENT_RIGHT = 3;
public final static short HORIZONTAL_ALIGNMENT_JUSTIFIED = 4; public final static short HORIZONTAL_ALIGNMENT_JUSTIFIED = 4;
public final static short HORIZONTAL_ALIGNMENT_DISTRIBUTED = 7; public final static short HORIZONTAL_ALIGNMENT_DISTRIBUTED = 7;
/** /**
* How to align text vertically * How to align text vertically
*/ */
public final static short VERTICAL_ALIGNMENT_TOP = 1; public final static short VERTICAL_ALIGNMENT_TOP = 1;
public final static short VERTICAL_ALIGNMENT_CENTER = 2; public final static short VERTICAL_ALIGNMENT_CENTER = 2;
public final static short VERTICAL_ALIGNMENT_BOTTOM = 3; public final static short VERTICAL_ALIGNMENT_BOTTOM = 3;
public final static short VERTICAL_ALIGNMENT_JUSTIFY = 4; public final static short VERTICAL_ALIGNMENT_JUSTIFY = 4;
public final static short VERTICAL_ALIGNMENT_DISTRIBUTED= 7; public final static short VERTICAL_ALIGNMENT_DISTRIBUTED = 7;
public HSSFTextbox(EscherContainerRecord spContainer, ObjRecord objRecord, TextObjectRecord textObjectRecord) {
int marginLeft, marginRight, marginTop, marginBottom; super(spContainer, objRecord, textObjectRecord);
short halign, valign; }
HSSFRichTextString string = new HSSFRichTextString(""); HSSFRichTextString string = new HSSFRichTextString("");
/** /**
* Construct a new textbox with the given parent and anchor. * Construct a new textbox with the given parent and anchor.
*
* @param parent * @param parent
* @param anchor One of HSSFClientAnchor or HSSFChildAnchor * @param anchor One of HSSFClientAnchor or HSSFChildAnchor
*/ */
public HSSFTextbox( HSSFShape parent, HSSFAnchor anchor ) public HSSFTextbox(HSSFShape parent, HSSFAnchor anchor) {
{ super(parent, anchor);
super( parent, anchor ); setHorizontalAlignment(HORIZONTAL_ALIGNMENT_LEFT);
setShapeType(OBJECT_TYPE_TEXT); setVerticalAlignment(VERTICAL_ALIGNMENT_TOP);
setString(new HSSFRichTextString(""));
}
halign = HORIZONTAL_ALIGNMENT_LEFT; @Override
valign = VERTICAL_ALIGNMENT_TOP; protected ObjRecord createObjRecord() {
ObjRecord obj = new ObjRecord();
CommonObjectDataSubRecord c = new CommonObjectDataSubRecord();
c.setObjectType(HSSFTextbox.OBJECT_TYPE_TEXT);
c.setLocked(true);
c.setPrintable(true);
c.setAutofill(true);
c.setAutoline(true);
EndSubRecord e = new EndSubRecord();
obj.addSubRecord(c);
obj.addSubRecord(e);
return obj;
}
@Override
protected EscherContainerRecord createSpContainer() {
EscherContainerRecord spContainer = new EscherContainerRecord();
EscherSpRecord sp = new EscherSpRecord();
EscherOptRecord opt = new EscherOptRecord();
EscherClientDataRecord clientData = new EscherClientDataRecord();
EscherTextboxRecord escherTextbox = new EscherTextboxRecord();
spContainer.setRecordId(EscherContainerRecord.SP_CONTAINER);
spContainer.setOptions((short) 0x000F);
sp.setRecordId(EscherSpRecord.RECORD_ID);
sp.setOptions((short) ((EscherAggregate.ST_TEXTBOX << 4) | 0x2));
sp.setFlags(EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HASSHAPETYPE);
opt.setRecordId(EscherOptRecord.RECORD_ID);
opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.TEXT__TEXTID, 0));
opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.TEXT__WRAPTEXT, 0));
opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.TEXT__ANCHORTEXT, 0));
opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.GROUPSHAPE__PRINT, 0x00080000));
opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.TEXT__TEXTLEFT, 0));
opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.TEXT__TEXTRIGHT, 0));
opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.TEXT__TEXTTOP, 0));
opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.TEXT__TEXTBOTTOM, 0));
opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEDASHING, LINESTYLE_SOLID));
opt.setEscherProperty(new EscherBoolProperty(EscherProperties.LINESTYLE__NOLINEDRAWDASH, 0x00080008));
opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEWIDTH, LINEWIDTH_DEFAULT));
opt.setEscherProperty(new EscherRGBProperty(EscherProperties.FILL__FILLCOLOR, FILL__FILLCOLOR_DEFAULT));
opt.setEscherProperty(new EscherRGBProperty(EscherProperties.LINESTYLE__COLOR, LINESTYLE__COLOR_DEFAULT));
opt.setEscherProperty(new EscherBoolProperty(EscherProperties.FILL__NOFILLHITTEST, NO_FILLHITTEST_FALSE));
opt.setEscherProperty(new EscherBoolProperty(EscherProperties.GROUPSHAPE__PRINT, 0x080000));
EscherRecord anchor = getAnchor().getEscherAnchor();
clientData.setRecordId(EscherClientDataRecord.RECORD_ID);
clientData.setOptions((short) 0x0000);
escherTextbox.setRecordId(EscherTextboxRecord.RECORD_ID);
escherTextbox.setOptions((short) 0x0000);
spContainer.addChildRecord(sp);
spContainer.addChildRecord(opt);
spContainer.addChildRecord(anchor);
spContainer.addChildRecord(clientData);
spContainer.addChildRecord(escherTextbox);
return spContainer;
}
@Override
void afterInsert(HSSFPatriarch patriarch) {
EscherAggregate agg = patriarch._getBoundAggregate();
agg.associateShapeToObjRecord(getEscherContainer().getChildById(EscherClientDataRecord.RECORD_ID), getObjRecord());
agg.associateShapeToObjRecord(getEscherContainer().getChildById(EscherTextboxRecord.RECORD_ID), getTextObjectRecord());
} }
/** /**
* @return the rich text string for this textbox. * @return Returns the left margin within the textbox.
*/ */
public HSSFRichTextString getString() public int getMarginLeft() {
{ EscherSimpleProperty property = getOptRecord().lookup(EscherProperties.TEXT__TEXTLEFT);
return string; return property == null ? 0 : property.getPropertyValue();
}
/**
* @param string Sets the rich text string used by this object.
*/
public void setString( RichTextString string )
{
HSSFRichTextString rtr = (HSSFRichTextString)string;
// If font is not set we must set the default one
if (rtr.numFormattingRuns() == 0) rtr.applyFont((short)0);
this.string = rtr;
}
/**
* @return Returns the left margin within the textbox.
*/
public int getMarginLeft()
{
return marginLeft;
} }
/** /**
* Sets the left margin within the textbox. * Sets the left margin within the textbox.
*/ */
public void setMarginLeft( int marginLeft ) public void setMarginLeft(int marginLeft) {
{ setPropertyValue(new EscherSimpleProperty(EscherProperties.TEXT__TEXTLEFT, marginLeft));
this.marginLeft = marginLeft;
} }
/** /**
* @return returns the right margin within the textbox. * @return returns the right margin within the textbox.
*/ */
public int getMarginRight() public int getMarginRight() {
{ EscherSimpleProperty property = getOptRecord().lookup(EscherProperties.TEXT__TEXTRIGHT);
return marginRight; return property == null ? 0 : property.getPropertyValue();
} }
/** /**
* Sets the right margin within the textbox. * Sets the right margin within the textbox.
*/ */
public void setMarginRight( int marginRight ) public void setMarginRight(int marginRight) {
{ setPropertyValue(new EscherSimpleProperty(EscherProperties.TEXT__TEXTRIGHT, marginRight));
this.marginRight = marginRight;
} }
/** /**
* @return returns the top margin within the textbox. * @return returns the top margin within the textbox.
*/ */
public int getMarginTop() public int getMarginTop() {
{ EscherSimpleProperty property = getOptRecord().lookup(EscherProperties.TEXT__TEXTTOP);
return marginTop; return property == null ? 0 : property.getPropertyValue();
} }
/** /**
* Sets the top margin within the textbox. * Sets the top margin within the textbox.
*/ */
public void setMarginTop( int marginTop ) public void setMarginTop(int marginTop) {
{ setPropertyValue(new EscherSimpleProperty(EscherProperties.TEXT__TEXTTOP, marginTop));
this.marginTop = marginTop;
} }
/** /**
* Gets the bottom margin within the textbox. * Gets the bottom margin within the textbox.
*/ */
public int getMarginBottom() public int getMarginBottom() {
{ EscherSimpleProperty property = getOptRecord().lookup(EscherProperties.TEXT__TEXTBOTTOM);
return marginBottom; return property == null ? 0 : property.getPropertyValue();
} }
/** /**
* Sets the bottom margin within the textbox. * Sets the bottom margin within the textbox.
*/ */
public void setMarginBottom( int marginBottom ) public void setMarginBottom(int marginBottom) {
{ setPropertyValue(new EscherSimpleProperty(EscherProperties.TEXT__TEXTBOTTOM, marginBottom));
this.marginBottom = marginBottom;
} }
/** /**
* Gets the horizontal alignment. * Gets the horizontal alignment.
*/ */
public short getHorizontalAlignment() public short getHorizontalAlignment() {
{ return (short) getTextObjectRecord().getHorizontalTextAlignment();
return halign;
} }
/** /**
* Sets the horizontal alignment. * Sets the horizontal alignment.
*/ */
public void setHorizontalAlignment( short align ) public void setHorizontalAlignment(short align) {
{ getTextObjectRecord().setHorizontalTextAlignment(align);
this.halign = align;
} }
/** /**
* Gets the vertical alignment. * Gets the vertical alignment.
*/ */
public short getVerticalAlignment() public short getVerticalAlignment() {
{ return (short) getTextObjectRecord().getVerticalTextAlignment();
return valign;
} }
/** /**
* Sets the vertical alignment. * Sets the vertical alignment.
*/ */
public void setVerticalAlignment( short align ) public void setVerticalAlignment(short align) {
{ getTextObjectRecord().setVerticalTextAlignment(align);
this.valign = align; }
@Override
public void setShapeType(int shapeType) {
throw new IllegalStateException("Shape type can not be changed in " + this.getClass().getSimpleName());
}
@Override
protected HSSFShape cloneShape() {
TextObjectRecord txo = (TextObjectRecord) getTextObjectRecord().cloneViaReserialise();
EscherContainerRecord spContainer = new EscherContainerRecord();
byte[] inSp = getEscherContainer().serialize();
spContainer.fillFields(inSp, 0, new DefaultEscherRecordFactory());
ObjRecord obj = (ObjRecord) getObjRecord().cloneViaReserialise();
return new HSSFTextbox(spContainer, obj, txo);
}
@Override
protected void afterRemove(HSSFPatriarch patriarch) {
patriarch._getBoundAggregate().removeShapeToObjRecord(getEscherContainer().getChildById(EscherClientDataRecord.RECORD_ID));
patriarch._getBoundAggregate().removeShapeToObjRecord(getEscherContainer().getChildById(EscherTextboxRecord.RECORD_ID));
} }
} }

View File

@ -696,7 +696,7 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss
names.add(newName); names.add(newName);
} }
// TODO - maybe same logic required for other/all built-in name records // TODO - maybe same logic required for other/all built-in name records
workbook.cloneDrawings(clonedSheet.getSheet()); // workbook.cloneDrawings(clonedSheet.getSheet());
return clonedSheet; return clonedSheet;
} }
@ -1606,7 +1606,7 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss
r.setUid( uid ); r.setUid( uid );
r.setTag( (short) 0xFF ); r.setTag( (short) 0xFF );
r.setSize( pictureData.length + 25 ); r.setSize( pictureData.length + 25 );
r.setRef( 1 ); r.setRef( 0 );
r.setOffset( 0 ); r.setOffset( 0 );
r.setBlipRecord( blipRecord ); r.setBlipRecord( blipRecord );
@ -1698,7 +1698,7 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss
List<HSSFObjectData> objects = new ArrayList<HSSFObjectData>(); List<HSSFObjectData> objects = new ArrayList<HSSFObjectData>();
for (int i = 0; i < getNumberOfSheets(); i++) for (int i = 0; i < getNumberOfSheets(); i++)
{ {
getAllEmbeddedObjects(getSheetAt(i).getSheet().getRecords(), objects); getAllEmbeddedObjects(getSheetAt(i), objects);
} }
return objects; return objects;
} }
@ -1706,27 +1706,20 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss
/** /**
* Gets all embedded OLE2 objects from the Workbook. * Gets all embedded OLE2 objects from the Workbook.
* *
* @param records the list of records to search. * @param sheet embedded object attached to
* @param objects the list of embedded objects to populate. * @param objects the list of embedded objects to populate.
*/ */
private void getAllEmbeddedObjects(List<RecordBase> records, List<HSSFObjectData> objects) private void getAllEmbeddedObjects(HSSFSheet sheet, List<HSSFObjectData> objects)
{ {
for (RecordBase obj : records) { HSSFPatriarch patriarch = sheet.getDrawingPatriarch();
if (obj instanceof ObjRecord) if (null == patriarch){
{ return;
// TODO: More convenient way of determining if there is stored binary. }
// TODO: Link to the data stored in the other stream. for (HSSFShape shape: patriarch.getChildren()){
Iterator<SubRecord> subRecordIter = ((ObjRecord) obj).getSubRecords().iterator(); if (shape instanceof HSSFObjectData){
while (subRecordIter.hasNext()) objects.add((HSSFObjectData) shape);
{ }
SubRecord sub = subRecordIter.next(); }
if (sub instanceof EmbeddedObjectRefSubRecord)
{
objects.add(new HSSFObjectData((ObjRecord) obj, directory));
}
}
}
}
} }
public HSSFCreationHelper getCreationHelper() { public HSSFCreationHelper getCreationHelper() {
@ -1800,4 +1793,8 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss
public boolean changeExternalReference(String oldUrl, String newUrl) { public boolean changeExternalReference(String oldUrl, String newUrl) {
return workbook.changeExternalReference(oldUrl, newUrl); return workbook.changeExternalReference(oldUrl, newUrl);
} }
public DirectoryNode getRootDirectory(){
return directory;
}
} }

View File

@ -0,0 +1,40 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.model;
import org.apache.poi.hssf.usermodel.HSSFComment;
import org.apache.poi.hssf.usermodel.HSSFPolygon;
import org.apache.poi.hssf.usermodel.HSSFTextbox;
/**
* @author Evgeniy Berlog
* @date 25.06.12
*/
public class HSSFTestModelHelper {
public static TextboxShape createTextboxShape(int shapeId, HSSFTextbox textbox){
return new TextboxShape(textbox, shapeId);
}
public static CommentShape createCommentShape(int shapeId, HSSFComment comment){
return new CommentShape(comment, shapeId);
}
public static PolygonShape createPolygonShape(int shapeId, HSSFPolygon polygon){
return new PolygonShape(polygon, shapeId);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,665 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.model;
import junit.framework.TestCase;
import org.apache.poi.ddf.*;
import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.hssf.record.CommonObjectDataSubRecord;
import org.apache.poi.hssf.record.EscherAggregate;
import org.apache.poi.hssf.record.ObjRecord;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.util.HexDump;
import java.io.IOException;
import java.util.Arrays;
import static junit.framework.Assert.assertEquals;
/**
* @author Evgeniy Berlog
* date: 12.06.12
*/
public class TestDrawingShapes extends TestCase {
/**
* HSSFShape tree bust be built correctly
* Check file with such records structure:
* -patriarch
* --shape
* --group
* ---group
* ----shape
* ----shape
* ---shape
* ---group
* ----shape
* ----shape
*/
public void testDrawingGroups() {
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("drawings.xls");
HSSFSheet sheet = wb.getSheet("groups");
HSSFPatriarch patriarch = sheet.getDrawingPatriarch();
assertEquals(patriarch.getChildren().size(), 2);
HSSFShapeGroup group = (HSSFShapeGroup) patriarch.getChildren().get(1);
assertEquals(3, group.getChildren().size());
HSSFShapeGroup group1 = (HSSFShapeGroup) group.getChildren().get(0);
assertEquals(2, group1.getChildren().size());
group1 = (HSSFShapeGroup) group.getChildren().get(2);
assertEquals(2, group1.getChildren().size());
}
public void testHSSFShapeCompatibility() {
HSSFSimpleShape shape = new HSSFSimpleShape(null, new HSSFClientAnchor());
shape.setShapeType(HSSFSimpleShape.OBJECT_TYPE_LINE);
assertEquals(0x08000040, shape.getLineStyleColor());
assertEquals(0x08000009, shape.getFillColor());
assertEquals(HSSFShape.LINEWIDTH_DEFAULT, shape.getLineWidth());
assertEquals(HSSFShape.LINESTYLE_SOLID, shape.getLineStyle());
assertFalse(shape.isNoFill());
AbstractShape sp = AbstractShape.createShape(shape, 1);
EscherContainerRecord spContainer = sp.getSpContainer();
EscherOptRecord opt =
spContainer.getChildById(EscherOptRecord.RECORD_ID);
assertEquals(7, opt.getEscherProperties().size());
assertEquals(true,
((EscherBoolProperty) opt.lookup(EscherProperties.TEXT__SIZE_TEXT_TO_FIT_SHAPE)).isTrue());
assertEquals(0x00000004,
((EscherSimpleProperty) opt.lookup(EscherProperties.GEOMETRY__SHAPEPATH)).getPropertyValue());
assertEquals(0x08000009,
((EscherSimpleProperty) opt.lookup(EscherProperties.FILL__FILLCOLOR)).getPropertyValue());
assertEquals(true,
((EscherBoolProperty) opt.lookup(EscherProperties.FILL__NOFILLHITTEST)).isTrue());
assertEquals(0x08000040,
((EscherSimpleProperty) opt.lookup(EscherProperties.LINESTYLE__COLOR)).getPropertyValue());
assertEquals(true,
((EscherBoolProperty) opt.lookup(EscherProperties.LINESTYLE__NOLINEDRAWDASH)).isTrue());
assertEquals(true,
((EscherBoolProperty) opt.lookup(EscherProperties.GROUPSHAPE__PRINT)).isTrue());
}
public void testDefaultPictureSettings() {
HSSFPicture picture = new HSSFPicture(null, new HSSFClientAnchor());
assertEquals(picture.getLineWidth(), HSSFShape.LINEWIDTH_DEFAULT);
assertEquals(picture.getFillColor(), HSSFShape.FILL__FILLCOLOR_DEFAULT);
assertEquals(picture.getLineStyle(), HSSFShape.LINESTYLE_NONE);
assertEquals(picture.getLineStyleColor(), HSSFShape.LINESTYLE__COLOR_DEFAULT);
assertEquals(picture.isNoFill(), false);
assertEquals(picture.getPictureIndex(), -1);//not set yet
}
/**
* No NullPointerException should appear
*/
public void testDefaultSettingsWithEmptyContainer() {
EscherContainerRecord container = new EscherContainerRecord();
EscherOptRecord opt = new EscherOptRecord();
opt.setRecordId(EscherOptRecord.RECORD_ID);
container.addChildRecord(opt);
ObjRecord obj = new ObjRecord();
CommonObjectDataSubRecord cod = new CommonObjectDataSubRecord();
cod.setObjectType(HSSFSimpleShape.OBJECT_TYPE_PICTURE);
obj.addSubRecord(cod);
HSSFPicture picture = new HSSFPicture(container, obj);
assertEquals(picture.getLineWidth(), HSSFShape.LINEWIDTH_DEFAULT);
assertEquals(picture.getFillColor(), HSSFShape.FILL__FILLCOLOR_DEFAULT);
assertEquals(picture.getLineStyle(), HSSFShape.LINESTYLE_DEFAULT);
assertEquals(picture.getLineStyleColor(), HSSFShape.LINESTYLE__COLOR_DEFAULT);
assertEquals(picture.isNoFill(), HSSFShape.NO_FILL_DEFAULT);
assertEquals(picture.getPictureIndex(), -1);//not set yet
}
/**
* create a rectangle, save the workbook, read back and verify that all shape properties are there
*/
public void testReadWriteRectangle() throws IOException {
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet();
HSSFPatriarch drawing = sheet.createDrawingPatriarch();
HSSFClientAnchor anchor = new HSSFClientAnchor(10, 10, 50, 50, (short) 2, 2, (short) 4, 4);
anchor.setAnchorType(2);
assertEquals(anchor.getAnchorType(), 2);
HSSFSimpleShape rectangle = drawing.createSimpleShape(anchor);
rectangle.setShapeType(HSSFSimpleShape.OBJECT_TYPE_RECTANGLE);
rectangle.setLineWidth(10000);
rectangle.setFillColor(777);
assertEquals(rectangle.getFillColor(), 777);
assertEquals(10000, rectangle.getLineWidth());
rectangle.setLineStyle(10);
assertEquals(10, rectangle.getLineStyle());
assertEquals(rectangle.getWrapText(), HSSFSimpleShape.WRAP_SQUARE);
rectangle.setLineStyleColor(1111);
rectangle.setNoFill(true);
rectangle.setWrapText(HSSFSimpleShape.WRAP_NONE);
rectangle.setString(new HSSFRichTextString("teeeest"));
assertEquals(rectangle.getLineStyleColor(), 1111);
assertEquals(((EscherSimpleProperty)((EscherOptRecord)HSSFTestHelper.getEscherContainer(rectangle).getChildById(EscherOptRecord.RECORD_ID))
.lookup(EscherProperties.TEXT__TEXTID)).getPropertyValue(), "teeeest".hashCode());
assertEquals(rectangle.isNoFill(), true);
assertEquals(rectangle.getWrapText(), HSSFSimpleShape.WRAP_NONE);
assertEquals(rectangle.getString().getString(), "teeeest");
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sheet = wb.getSheetAt(0);
drawing = sheet.getDrawingPatriarch();
assertEquals(1, drawing.getChildren().size());
HSSFSimpleShape rectangle2 =
(HSSFSimpleShape) drawing.getChildren().get(0);
assertEquals(HSSFSimpleShape.OBJECT_TYPE_RECTANGLE,
rectangle2.getShapeType());
assertEquals(10000, rectangle2.getLineWidth());
assertEquals(10, rectangle2.getLineStyle());
assertEquals(anchor, rectangle2.getAnchor());
assertEquals(rectangle2.getLineStyleColor(), 1111);
assertEquals(rectangle2.getFillColor(), 777);
assertEquals(rectangle2.isNoFill(), true);
assertEquals(rectangle2.getString().getString(), "teeeest");
assertEquals(rectangle.getWrapText(), HSSFSimpleShape.WRAP_NONE);
rectangle2.setFillColor(3333);
rectangle2.setLineStyle(9);
rectangle2.setLineStyleColor(4444);
rectangle2.setNoFill(false);
rectangle2.setLineWidth(77);
rectangle2.getAnchor().setDx1(2);
rectangle2.getAnchor().setDx2(3);
rectangle2.getAnchor().setDy1(4);
rectangle2.getAnchor().setDy2(5);
rectangle.setWrapText(HSSFSimpleShape.WRAP_BY_POINTS);
rectangle2.setString(new HSSFRichTextString("test22"));
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sheet = wb.getSheetAt(0);
drawing = sheet.getDrawingPatriarch();
assertEquals(1, drawing.getChildren().size());
rectangle2 = (HSSFSimpleShape) drawing.getChildren().get(0);
assertEquals(HSSFSimpleShape.OBJECT_TYPE_RECTANGLE, rectangle2.getShapeType());
assertEquals(rectangle.getWrapText(), HSSFSimpleShape.WRAP_BY_POINTS);
assertEquals(77, rectangle2.getLineWidth());
assertEquals(9, rectangle2.getLineStyle());
assertEquals(rectangle2.getLineStyleColor(), 4444);
assertEquals(rectangle2.getFillColor(), 3333);
assertEquals(rectangle2.getAnchor().getDx1(), 2);
assertEquals(rectangle2.getAnchor().getDx2(), 3);
assertEquals(rectangle2.getAnchor().getDy1(), 4);
assertEquals(rectangle2.getAnchor().getDy2(), 5);
assertEquals(rectangle2.isNoFill(), false);
assertEquals(rectangle2.getString().getString(), "test22");
HSSFSimpleShape rect3 = drawing.createSimpleShape(new HSSFClientAnchor());
rect3.setShapeType(HSSFSimpleShape.OBJECT_TYPE_RECTANGLE);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
drawing = wb.getSheetAt(0).getDrawingPatriarch();
assertEquals(drawing.getChildren().size(), 2);
}
public void testReadExistingImage() {
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("drawings.xls");
HSSFSheet sheet = wb.getSheet("pictures");
HSSFPatriarch drawing = sheet.getDrawingPatriarch();
assertEquals(1, drawing.getChildren().size());
HSSFPicture picture = (HSSFPicture) drawing.getChildren().get(0);
assertEquals(picture.getPictureIndex(), 2);
assertEquals(picture.getLineStyleColor(), HSSFShape.LINESTYLE__COLOR_DEFAULT);
assertEquals(picture.getFillColor(), 0x5DC943);
assertEquals(picture.getLineWidth(), HSSFShape.LINEWIDTH_DEFAULT);
assertEquals(picture.getLineStyle(), HSSFShape.LINESTYLE_DEFAULT);
assertEquals(picture.isNoFill(), false);
picture.setPictureIndex(2);
assertEquals(picture.getPictureIndex(), 2);
}
/* assert shape properties when reading shapes from a existing workbook */
public void testReadExistingRectangle() {
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("drawings.xls");
HSSFSheet sheet = wb.getSheet("rectangles");
HSSFPatriarch drawing = sheet.getDrawingPatriarch();
assertEquals(1, drawing.getChildren().size());
HSSFSimpleShape shape = (HSSFSimpleShape) drawing.getChildren().get(0);
assertEquals(shape.isNoFill(), false);
assertEquals(shape.getLineStyle(), HSSFShape.LINESTYLE_DASHDOTGEL);
assertEquals(shape.getLineStyleColor(), 0x616161);
assertEquals(HexDump.toHex(shape.getFillColor()), shape.getFillColor(), 0x2CE03D);
assertEquals(shape.getLineWidth(), HSSFShape.LINEWIDTH_ONE_PT * 2);
assertEquals(shape.getString().getString(), "POItest");
assertEquals(shape.getRotationDegree(), 27);
}
public void testShapeIds() {
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet1 = wb.createSheet();
HSSFPatriarch patriarch1 = sheet1.createDrawingPatriarch();
for (int i = 0; i < 2; i++) {
patriarch1.createSimpleShape(new HSSFClientAnchor());
}
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sheet1 = wb.getSheetAt(0);
patriarch1 = sheet1.getDrawingPatriarch();
EscherAggregate agg1 = HSSFTestHelper.getEscherAggregate(patriarch1);
// last shape ID cached in EscherDgRecord
EscherDgRecord dg1 =
agg1.getEscherContainer().getChildById(EscherDgRecord.RECORD_ID);
assertEquals(1026, dg1.getLastMSOSPID());
// iterate over shapes and check shapeId
EscherContainerRecord spgrContainer =
agg1.getEscherContainer().getChildContainers().get(0);
// root spContainer + 2 spContainers for shapes
assertEquals(3, spgrContainer.getChildRecords().size());
EscherSpRecord sp0 =
((EscherContainerRecord) spgrContainer.getChild(0)).getChildById(EscherSpRecord.RECORD_ID);
assertEquals(1024, sp0.getShapeId());
EscherSpRecord sp1 =
((EscherContainerRecord) spgrContainer.getChild(1)).getChildById(EscherSpRecord.RECORD_ID);
assertEquals(1025, sp1.getShapeId());
EscherSpRecord sp2 =
((EscherContainerRecord) spgrContainer.getChild(2)).getChildById(EscherSpRecord.RECORD_ID);
assertEquals(1026, sp2.getShapeId());
}
/**
* Test get new id for shapes from existing file
* File already have for 1 shape on each sheet, because document must contain EscherDgRecord for each sheet
*/
public void testAllocateNewIds() {
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("empty.xls");
HSSFSheet sheet = wb.getSheetAt(0);
HSSFPatriarch patriarch = sheet.getDrawingPatriarch();
/**
* 2048 - main SpContainer id
* 2049 - existing shape id
*/
assertEquals(HSSFTestHelper.allocateNewShapeId(patriarch), 2050);
assertEquals(HSSFTestHelper.allocateNewShapeId(patriarch), 2051);
assertEquals(HSSFTestHelper.allocateNewShapeId(patriarch), 2052);
sheet = wb.getSheetAt(1);
patriarch = sheet.getDrawingPatriarch();
/**
* 3072 - main SpContainer id
* 3073 - existing shape id
*/
assertEquals(HSSFTestHelper.allocateNewShapeId(patriarch), 3074);
assertEquals(HSSFTestHelper.allocateNewShapeId(patriarch), 3075);
assertEquals(HSSFTestHelper.allocateNewShapeId(patriarch), 3076);
sheet = wb.getSheetAt(2);
patriarch = sheet.getDrawingPatriarch();
assertEquals(HSSFTestHelper.allocateNewShapeId(patriarch), 1026);
assertEquals(HSSFTestHelper.allocateNewShapeId(patriarch), 1027);
assertEquals(HSSFTestHelper.allocateNewShapeId(patriarch), 1028);
}
public void testOpt() throws Exception {
HSSFWorkbook wb = new HSSFWorkbook();
// create a sheet with a text box
HSSFSheet sheet = wb.createSheet();
HSSFPatriarch patriarch = sheet.createDrawingPatriarch();
HSSFTextbox textbox = patriarch.createTextbox(new HSSFClientAnchor());
EscherOptRecord opt1 = HSSFTestHelper.getOptRecord(textbox);
EscherOptRecord opt2 = HSSFTestHelper.getEscherContainer(textbox).getChildById(EscherOptRecord.RECORD_ID);
assertSame(opt1, opt2);
}
public void testCorrectOrderInOptRecord(){
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet();
HSSFPatriarch patriarch = sheet.createDrawingPatriarch();
HSSFTextbox textbox = patriarch.createTextbox(new HSSFClientAnchor());
EscherOptRecord opt = HSSFTestHelper.getOptRecord(textbox);
String opt1Str = opt.toXml();
textbox.setFillColor(textbox.getFillColor());
EscherContainerRecord container = HSSFTestHelper.getEscherContainer(textbox);
EscherOptRecord optRecord = container.getChildById(EscherOptRecord.RECORD_ID);
assertEquals(opt1Str, optRecord.toXml());
textbox.setLineStyle(textbox.getLineStyle());
assertEquals(opt1Str, optRecord.toXml());
textbox.setLineWidth(textbox.getLineWidth());
assertEquals(opt1Str, optRecord.toXml());
textbox.setLineStyleColor(textbox.getLineStyleColor());
assertEquals(opt1Str, optRecord.toXml());
}
public void testDgRecordNumShapes(){
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet();
HSSFPatriarch patriarch = sheet.createDrawingPatriarch();
EscherAggregate aggregate = HSSFTestHelper.getEscherAggregate(patriarch);
EscherDgRecord dgRecord = (EscherDgRecord) aggregate.getEscherRecord(0).getChild(0);
assertEquals(dgRecord.getNumShapes(), 1);
}
public void testTextForSimpleShape(){
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet();
HSSFPatriarch patriarch = sheet.createDrawingPatriarch();
HSSFSimpleShape shape = patriarch.createSimpleShape(new HSSFClientAnchor());
shape.setShapeType(HSSFSimpleShape.OBJECT_TYPE_RECTANGLE);
EscherAggregate agg = HSSFTestHelper.getEscherAggregate(patriarch);
assertEquals(agg.getShapeToObjMapping().size(), 2);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sheet = wb.getSheetAt(0);
patriarch = sheet.getDrawingPatriarch();
shape = (HSSFSimpleShape) patriarch.getChildren().get(0);
agg = HSSFTestHelper.getEscherAggregate(patriarch);
assertEquals(agg.getShapeToObjMapping().size(), 2);
shape.setString(new HSSFRichTextString("string1"));
assertEquals(shape.getString().getString(), "string1");
assertNotNull(HSSFTestHelper.getEscherContainer(shape).getChildById(EscherTextboxRecord.RECORD_ID));
assertEquals(agg.getShapeToObjMapping().size(), 2);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sheet = wb.getSheetAt(0);
patriarch = sheet.getDrawingPatriarch();
shape = (HSSFSimpleShape) patriarch.getChildren().get(0);
assertNotNull(HSSFTestHelper.getTextObjRecord(shape));
assertEquals(shape.getString().getString(), "string1");
assertNotNull(HSSFTestHelper.getEscherContainer(shape).getChildById(EscherTextboxRecord.RECORD_ID));
assertEquals(agg.getShapeToObjMapping().size(), 2);
}
public void testRemoveShapes(){
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet();
HSSFPatriarch patriarch = sheet.createDrawingPatriarch();
HSSFSimpleShape rectangle = patriarch.createSimpleShape(new HSSFClientAnchor());
rectangle.setShapeType(HSSFSimpleShape.OBJECT_TYPE_RECTANGLE);
int idx = wb.addPicture(new byte[]{1,2,3}, Workbook.PICTURE_TYPE_JPEG);
patriarch.createPicture(new HSSFClientAnchor(), idx);
patriarch.createCellComment(new HSSFClientAnchor());
HSSFPolygon polygon = patriarch.createPolygon(new HSSFClientAnchor());
polygon.setPoints(new int[]{1,2}, new int[]{2,3});
patriarch.createTextbox(new HSSFClientAnchor());
HSSFShapeGroup group = patriarch.createGroup(new HSSFClientAnchor());
group.createTextbox(new HSSFChildAnchor());
group.createPicture(new HSSFChildAnchor(), idx);
assertEquals(patriarch.getChildren().size(), 6);
assertEquals(group.getChildren().size(), 2);
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getShapeToObjMapping().size(), 12);
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getTailRecords().size(), 1);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sheet = wb.getSheetAt(0);
patriarch = sheet.getDrawingPatriarch();
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getShapeToObjMapping().size(), 12);
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getTailRecords().size(), 1);
assertEquals(patriarch.getChildren().size(), 6);
group = (HSSFShapeGroup) patriarch.getChildren().get(5);
group.removeShape(group.getChildren().get(0));
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getShapeToObjMapping().size(), 10);
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getTailRecords().size(), 1);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sheet = wb.getSheetAt(0);
patriarch = sheet.getDrawingPatriarch();
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getShapeToObjMapping().size(), 10);
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getTailRecords().size(), 1);
group = (HSSFShapeGroup) patriarch.getChildren().get(5);
patriarch.removeShape(group);
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getShapeToObjMapping().size(), 8);
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getTailRecords().size(), 1);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sheet = wb.getSheetAt(0);
patriarch = sheet.getDrawingPatriarch();
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getShapeToObjMapping().size(), 8);
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getTailRecords().size(), 1);
assertEquals(patriarch.getChildren().size(), 5);
HSSFShape shape = patriarch.getChildren().get(0);
patriarch.removeShape(shape);
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getShapeToObjMapping().size(), 6);
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getTailRecords().size(), 1);
assertEquals(patriarch.getChildren().size(), 4);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sheet = wb.getSheetAt(0);
patriarch = sheet.getDrawingPatriarch();
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getShapeToObjMapping().size(), 6);
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getTailRecords().size(), 1);
assertEquals(patriarch.getChildren().size(), 4);
HSSFPicture picture = (HSSFPicture) patriarch.getChildren().get(0);
patriarch.removeShape(picture);
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getShapeToObjMapping().size(), 5);
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getTailRecords().size(), 1);
assertEquals(patriarch.getChildren().size(), 3);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sheet = wb.getSheetAt(0);
patriarch = sheet.getDrawingPatriarch();
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getShapeToObjMapping().size(), 5);
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getTailRecords().size(), 1);
assertEquals(patriarch.getChildren().size(), 3);
HSSFComment comment = (HSSFComment) patriarch.getChildren().get(0);
patriarch.removeShape(comment);
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getShapeToObjMapping().size(), 3);
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getTailRecords().size(), 0);
assertEquals(patriarch.getChildren().size(), 2);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sheet = wb.getSheetAt(0);
patriarch = sheet.getDrawingPatriarch();
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getShapeToObjMapping().size(), 3);
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getTailRecords().size(), 0);
assertEquals(patriarch.getChildren().size(), 2);
polygon = (HSSFPolygon) patriarch.getChildren().get(0);
patriarch.removeShape(polygon);
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getShapeToObjMapping().size(), 2);
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getTailRecords().size(), 0);
assertEquals(patriarch.getChildren().size(), 1);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sheet = wb.getSheetAt(0);
patriarch = sheet.getDrawingPatriarch();
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getShapeToObjMapping().size(), 2);
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getTailRecords().size(), 0);
assertEquals(patriarch.getChildren().size(), 1);
HSSFTextbox textbox = (HSSFTextbox) patriarch.getChildren().get(0);
patriarch.removeShape(textbox);
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getShapeToObjMapping().size(), 0);
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getTailRecords().size(), 0);
assertEquals(patriarch.getChildren().size(), 0);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sheet = wb.getSheetAt(0);
patriarch = sheet.getDrawingPatriarch();
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getShapeToObjMapping().size(), 0);
assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getTailRecords().size(), 0);
assertEquals(patriarch.getChildren().size(), 0);
}
public void testShapeFlip(){
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet();
HSSFPatriarch patriarch = sheet.createDrawingPatriarch();
HSSFSimpleShape rectangle = patriarch.createSimpleShape(new HSSFClientAnchor());
rectangle.setShapeType(HSSFSimpleShape.OBJECT_TYPE_RECTANGLE);
assertEquals(rectangle.isFlipVertical(), false);
assertEquals(rectangle.isFlipHorizontal(), false);
rectangle.setFlipVertical(true);
assertEquals(rectangle.isFlipVertical(), true);
rectangle.setFlipHorizontal(true);
assertEquals(rectangle.isFlipHorizontal(), true);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sheet = wb.getSheetAt(0);
patriarch = sheet.getDrawingPatriarch();
rectangle = (HSSFSimpleShape) patriarch.getChildren().get(0);
assertEquals(rectangle.isFlipHorizontal(), true);
rectangle.setFlipHorizontal(false);
assertEquals(rectangle.isFlipHorizontal(), false);
assertEquals(rectangle.isFlipVertical(), true);
rectangle.setFlipVertical(false);
assertEquals(rectangle.isFlipVertical(), false);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sheet = wb.getSheetAt(0);
patriarch = sheet.getDrawingPatriarch();
rectangle = (HSSFSimpleShape) patriarch.getChildren().get(0);
assertEquals(rectangle.isFlipVertical(), false);
assertEquals(rectangle.isFlipHorizontal(), false);
}
public void testRotation() {
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet();
HSSFPatriarch patriarch = sheet.createDrawingPatriarch();
HSSFSimpleShape rectangle = patriarch.createSimpleShape(new HSSFClientAnchor(0,0,100,100, (short) 0,0,(short)5,5));
rectangle.setShapeType(HSSFSimpleShape.OBJECT_TYPE_RECTANGLE);
assertEquals(rectangle.getRotationDegree(), 0);
rectangle.setRotationDegree((short) 45);
assertEquals(rectangle.getRotationDegree(), 45);
rectangle.setFlipHorizontal(true);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sheet = wb.getSheetAt(0);
patriarch = sheet.getDrawingPatriarch();
rectangle = (HSSFSimpleShape) patriarch.getChildren().get(0);
assertEquals(rectangle.getRotationDegree(), 45);
rectangle.setRotationDegree((short) 30);
assertEquals(rectangle.getRotationDegree(), 30);
patriarch.setCoordinates(0, 0, 10, 10);
rectangle.setString(new HSSFRichTextString("1234"));
}
public void testShapeContainerImplementsIterable(){
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet();
HSSFPatriarch patriarch = sheet.createDrawingPatriarch();
patriarch.createSimpleShape(new HSSFClientAnchor());
patriarch.createSimpleShape(new HSSFClientAnchor());
int i=2;
for (HSSFShape shape: patriarch){
i--;
}
assertEquals(i, 0);
}
public void testClearShapesForPatriarch(){
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet();
HSSFPatriarch patriarch = sheet.createDrawingPatriarch();
patriarch.createSimpleShape(new HSSFClientAnchor());
patriarch.createSimpleShape(new HSSFClientAnchor());
patriarch.createCellComment(new HSSFClientAnchor());
EscherAggregate agg = HSSFTestHelper.getEscherAggregate(patriarch);
assertEquals(agg.getShapeToObjMapping().size(), 6);
assertEquals(agg.getTailRecords().size(), 1);
assertEquals(patriarch.getChildren().size(), 3);
patriarch.clear();
assertEquals(agg.getShapeToObjMapping().size(), 0);
assertEquals(agg.getTailRecords().size(), 0);
assertEquals(patriarch.getChildren().size(), 0);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sheet = wb.getSheetAt(0);
patriarch = sheet.getDrawingPatriarch();
assertEquals(agg.getShapeToObjMapping().size(), 0);
assertEquals(agg.getTailRecords().size(), 0);
assertEquals(patriarch.getChildren().size(), 0);
}
}

View File

@ -0,0 +1,99 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.model;
import junit.framework.TestCase;
import org.apache.poi.ddf.DefaultEscherRecordFactory;
import org.apache.poi.ddf.EscherContainerRecord;
import org.apache.poi.ddf.EscherTextboxRecord;
import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.hssf.record.EscherAggregate;
import org.apache.poi.hssf.record.Record;
import org.apache.poi.hssf.record.RecordBase;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFTestHelper;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
/**
* @author Evgeniy Berlog
* @date 18.06.12
*/
public class TestEscherRecordFactory extends TestCase{
private static byte[] toByteArray(List<RecordBase> records) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
for (RecordBase rb : records) {
Record r = (Record) rb;
try {
out.write(r.serialize());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return out.toByteArray();
}
public void testDetectContainer() {
Random rnd = new Random();
assertEquals(true, DefaultEscherRecordFactory.isContainer((short) 0x0, EscherContainerRecord.DG_CONTAINER));
assertEquals(true, DefaultEscherRecordFactory.isContainer((short) 0x0, EscherContainerRecord.SOLVER_CONTAINER));
assertEquals(true, DefaultEscherRecordFactory.isContainer((short) 0x0, EscherContainerRecord.SP_CONTAINER));
assertEquals(true, DefaultEscherRecordFactory.isContainer((short) 0x0, EscherContainerRecord.DGG_CONTAINER));
assertEquals(true, DefaultEscherRecordFactory.isContainer((short) 0x0, EscherContainerRecord.BSTORE_CONTAINER));
assertEquals(true, DefaultEscherRecordFactory.isContainer((short) 0x0, EscherContainerRecord.SPGR_CONTAINER));
for (Short i=EscherContainerRecord.DGG_CONTAINER; i<= EscherContainerRecord.SOLVER_CONTAINER; i++){
assertEquals(true, DefaultEscherRecordFactory.isContainer(Integer.valueOf(rnd.nextInt(Short.MAX_VALUE)).shortValue(), i));
}
assertEquals(false, DefaultEscherRecordFactory.isContainer((short) 0x0, Integer.valueOf(EscherContainerRecord.DGG_CONTAINER-1).shortValue()));
assertEquals(false, DefaultEscherRecordFactory.isContainer((short) 0x0, Integer.valueOf(EscherContainerRecord.SOLVER_CONTAINER+1).shortValue()));
assertEquals(true, DefaultEscherRecordFactory.isContainer((short) 0x000F, Integer.valueOf(EscherContainerRecord.DGG_CONTAINER-1).shortValue()));
assertEquals(true, DefaultEscherRecordFactory.isContainer((short) 0xFFFF, Integer.valueOf(EscherContainerRecord.DGG_CONTAINER-1).shortValue()));
assertEquals(false, DefaultEscherRecordFactory.isContainer((short) 0x000C, Integer.valueOf(EscherContainerRecord.DGG_CONTAINER-1).shortValue()));
assertEquals(false, DefaultEscherRecordFactory.isContainer((short) 0xCCCC, Integer.valueOf(EscherContainerRecord.DGG_CONTAINER-1).shortValue()));
assertEquals(false, DefaultEscherRecordFactory.isContainer((short) 0x000F, EscherTextboxRecord.RECORD_ID));
assertEquals(false, DefaultEscherRecordFactory.isContainer((short) 0xCCCC, EscherTextboxRecord.RECORD_ID));
}
public void testDgContainerMustBeRootOfHSSFSheetEscherRecords() throws IOException {
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("47251.xls");
HSSFSheet sh = wb.getSheetAt(0);
InternalSheet ish = HSSFTestHelper.getSheetForTest(sh);
List<RecordBase> records = ish.getRecords();
// records to be aggregated
List<RecordBase> dgRecords = records.subList(19, 23);
byte[] dgBytes = toByteArray(dgRecords);
sh.getDrawingPatriarch();
EscherAggregate agg = (EscherAggregate) ish.findFirstRecordBySid(EscherAggregate.sid);
assertEquals(true, agg.getEscherRecords().get(0) instanceof EscherContainerRecord);
assertEquals(EscherContainerRecord.DG_CONTAINER, agg.getEscherRecords().get(0).getRecordId());
assertEquals((short) 0x0, agg.getEscherRecords().get(0).getOptions());
agg = (EscherAggregate) ish.findFirstRecordBySid(EscherAggregate.sid);
byte[] dgBytesAfterSave = agg.serialize();
assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length);
assertTrue("drawing data before and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave));
}
}

View File

@ -0,0 +1,428 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.model;
import junit.framework.TestCase;
import org.apache.poi.ddf.*;
import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.util.HexDump;
/**
* @author Evgeniy Berlog
* @date 12.06.12
*/
public class TestHSSFAnchor extends TestCase {
public void testDefaultValues(){
HSSFClientAnchor clientAnchor = new HSSFClientAnchor();
assertEquals(clientAnchor.getAnchorType(), 0);
assertEquals(clientAnchor.getCol1(), 0);
assertEquals(clientAnchor.getCol2(), 0);
assertEquals(clientAnchor.getDx1(), 0);
assertEquals(clientAnchor.getDx2(), 0);
assertEquals(clientAnchor.getDy1(), 0);
assertEquals(clientAnchor.getDy2(), 0);
assertEquals(clientAnchor.getRow1(), 0);
assertEquals(clientAnchor.getRow2(), 0);
clientAnchor = new HSSFClientAnchor(new EscherClientAnchorRecord());
assertEquals(clientAnchor.getAnchorType(), 0);
assertEquals(clientAnchor.getCol1(), 0);
assertEquals(clientAnchor.getCol2(), 0);
assertEquals(clientAnchor.getDx1(), 0);
assertEquals(clientAnchor.getDx2(), 0);
assertEquals(clientAnchor.getDy1(), 0);
assertEquals(clientAnchor.getDy2(), 0);
assertEquals(clientAnchor.getRow1(), 0);
assertEquals(clientAnchor.getRow2(), 0);
HSSFChildAnchor childAnchor = new HSSFChildAnchor();
assertEquals(childAnchor.getDx1(), 0);
assertEquals(childAnchor.getDx2(), 0);
assertEquals(childAnchor.getDy1(), 0);
assertEquals(childAnchor.getDy2(), 0);
childAnchor = new HSSFChildAnchor(new EscherChildAnchorRecord());
assertEquals(childAnchor.getDx1(), 0);
assertEquals(childAnchor.getDx2(), 0);
assertEquals(childAnchor.getDy1(), 0);
assertEquals(childAnchor.getDy2(), 0);
}
public void testCorrectOrderInSpContainer(){
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("drawings.xls");
HSSFSheet sheet = wb.getSheet("pictures");
HSSFPatriarch drawing = sheet.getDrawingPatriarch();
HSSFSimpleShape rectangle = (HSSFSimpleShape) drawing.getChildren().get(0);
assertEquals(HSSFTestHelper.getEscherContainer(rectangle).getChild(0).getRecordId(), EscherSpRecord.RECORD_ID);
assertEquals(HSSFTestHelper.getEscherContainer(rectangle).getChild(1).getRecordId(), EscherOptRecord.RECORD_ID);
assertEquals(HSSFTestHelper.getEscherContainer(rectangle).getChild(2).getRecordId(), EscherClientAnchorRecord.RECORD_ID);
assertEquals(HSSFTestHelper.getEscherContainer(rectangle).getChild(3).getRecordId(), EscherClientDataRecord.RECORD_ID);
rectangle.setAnchor(new HSSFClientAnchor());
assertEquals(HSSFTestHelper.getEscherContainer(rectangle).getChild(0).getRecordId(), EscherSpRecord.RECORD_ID);
assertEquals(HSSFTestHelper.getEscherContainer(rectangle).getChild(1).getRecordId(), EscherOptRecord.RECORD_ID);
assertEquals(HSSFTestHelper.getEscherContainer(rectangle).getChild(2).getRecordId(), EscherClientAnchorRecord.RECORD_ID);
assertEquals(HSSFTestHelper.getEscherContainer(rectangle).getChild(3).getRecordId(), EscherClientDataRecord.RECORD_ID);
}
public void testCreateClientAnchorFromContainer(){
EscherContainerRecord container = new EscherContainerRecord();
EscherClientAnchorRecord escher = new EscherClientAnchorRecord();
escher.setFlag((short) 3);
escher.setCol1((short)11);
escher.setCol2((short)12);
escher.setRow1((short)13);
escher.setRow2((short) 14);
escher.setDx1((short) 15);
escher.setDx2((short) 16);
escher.setDy1((short) 17);
escher.setDy2((short) 18);
container.addChildRecord(escher);
HSSFClientAnchor anchor = (HSSFClientAnchor) HSSFAnchor.createAnchorFromEscher(container);
assertEquals(anchor.getCol1(), 11);
assertEquals(escher.getCol1(), 11);
assertEquals(anchor.getCol2(), 12);
assertEquals(escher.getCol2(), 12);
assertEquals(anchor.getRow1(), 13);
assertEquals(escher.getRow1(), 13);
assertEquals(anchor.getRow2(), 14);
assertEquals(escher.getRow2(), 14);
assertEquals(anchor.getDx1(), 15);
assertEquals(escher.getDx1(), 15);
assertEquals(anchor.getDx2(), 16);
assertEquals(escher.getDx2(), 16);
assertEquals(anchor.getDy1(), 17);
assertEquals(escher.getDy1(), 17);
assertEquals(anchor.getDy2(), 18);
assertEquals(escher.getDy2(), 18);
}
public void testCreateChildAnchorFromContainer(){
EscherContainerRecord container = new EscherContainerRecord();
EscherChildAnchorRecord escher = new EscherChildAnchorRecord();
escher.setDx1((short) 15);
escher.setDx2((short) 16);
escher.setDy1((short) 17);
escher.setDy2((short) 18);
container.addChildRecord(escher);
HSSFChildAnchor anchor = (HSSFChildAnchor) HSSFAnchor.createAnchorFromEscher(container);
assertEquals(anchor.getDx1(), 15);
assertEquals(escher.getDx1(), 15);
assertEquals(anchor.getDx2(), 16);
assertEquals(escher.getDx2(), 16);
assertEquals(anchor.getDy1(), 17);
assertEquals(escher.getDy1(), 17);
assertEquals(anchor.getDy2(), 18);
assertEquals(escher.getDy2(), 18);
}
public void testShapeEscherMustHaveAnchorRecord(){
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet();
HSSFPatriarch drawing = sheet.createDrawingPatriarch();
HSSFClientAnchor anchor = new HSSFClientAnchor(10, 10, 200, 200, (short)2, 2, (short)15, 15);
anchor.setAnchorType(2);
HSSFSimpleShape rectangle = drawing.createSimpleShape(anchor);
rectangle.setShapeType(HSSFSimpleShape.OBJECT_TYPE_RECTANGLE);
rectangle.setAnchor(anchor);
assertNotNull(HSSFTestHelper.getEscherAnchor(anchor));
assertNotNull(HSSFTestHelper.getEscherContainer(rectangle));
assertTrue(HSSFTestHelper.getEscherAnchor(anchor).equals(HSSFTestHelper.getEscherContainer(rectangle).getChildById(EscherClientAnchorRecord.RECORD_ID)));
}
public void testClientAnchorFromEscher(){
EscherClientAnchorRecord escher = new EscherClientAnchorRecord();
escher.setCol1((short)11);
escher.setCol2((short)12);
escher.setRow1((short)13);
escher.setRow2((short) 14);
escher.setDx1((short) 15);
escher.setDx2((short) 16);
escher.setDy1((short) 17);
escher.setDy2((short) 18);
HSSFClientAnchor anchor = new HSSFClientAnchor(escher);
assertEquals(anchor.getCol1(), 11);
assertEquals(escher.getCol1(), 11);
assertEquals(anchor.getCol2(), 12);
assertEquals(escher.getCol2(), 12);
assertEquals(anchor.getRow1(), 13);
assertEquals(escher.getRow1(), 13);
assertEquals(anchor.getRow2(), 14);
assertEquals(escher.getRow2(), 14);
assertEquals(anchor.getDx1(), 15);
assertEquals(escher.getDx1(), 15);
assertEquals(anchor.getDx2(), 16);
assertEquals(escher.getDx2(), 16);
assertEquals(anchor.getDy1(), 17);
assertEquals(escher.getDy1(), 17);
assertEquals(anchor.getDy2(), 18);
assertEquals(escher.getDy2(), 18);
}
public void testClientAnchorFromScratch(){
HSSFClientAnchor anchor = new HSSFClientAnchor();
EscherClientAnchorRecord escher = (EscherClientAnchorRecord) HSSFTestHelper.getEscherAnchor(anchor);
anchor.setAnchor((short)11, 12, 13, 14, (short)15, 16, 17, 18);
assertEquals(anchor.getCol1(), 11);
assertEquals(escher.getCol1(), 11);
assertEquals(anchor.getCol2(), 15);
assertEquals(escher.getCol2(), 15);
assertEquals(anchor.getRow1(), 12);
assertEquals(escher.getRow1(), 12);
assertEquals(anchor.getRow2(), 16);
assertEquals(escher.getRow2(), 16);
assertEquals(anchor.getDx1(), 13);
assertEquals(escher.getDx1(), 13);
assertEquals(anchor.getDx2(), 17);
assertEquals(escher.getDx2(), 17);
assertEquals(anchor.getDy1(), 14);
assertEquals(escher.getDy1(), 14);
assertEquals(anchor.getDy2(), 18);
assertEquals(escher.getDy2(), 18);
anchor.setCol1(111);
assertEquals(anchor.getCol1(), 111);
assertEquals(escher.getCol1(), 111);
anchor.setCol2(112);
assertEquals(anchor.getCol2(), 112);
assertEquals(escher.getCol2(), 112);
anchor.setRow1(113);
assertEquals(anchor.getRow1(), 113);
assertEquals(escher.getRow1(), 113);
anchor.setRow2(114);
assertEquals(anchor.getRow2(), 114);
assertEquals(escher.getRow2(), 114);
anchor.setDx1(115);
assertEquals(anchor.getDx1(), 115);
assertEquals(escher.getDx1(), 115);
anchor.setDx2(116);
assertEquals(anchor.getDx2(), 116);
assertEquals(escher.getDx2(), 116);
anchor.setDy1(117);
assertEquals(anchor.getDy1(), 117);
assertEquals(escher.getDy1(), 117);
anchor.setDy2(118);
assertEquals(anchor.getDy2(), 118);
assertEquals(escher.getDy2(), 118);
}
public void testChildAnchorFromEscher(){
EscherChildAnchorRecord escher = new EscherChildAnchorRecord();
escher.setDx1((short) 15);
escher.setDx2((short) 16);
escher.setDy1((short) 17);
escher.setDy2((short) 18);
HSSFChildAnchor anchor = new HSSFChildAnchor(escher);
assertEquals(anchor.getDx1(), 15);
assertEquals(escher.getDx1(), 15);
assertEquals(anchor.getDx2(), 16);
assertEquals(escher.getDx2(), 16);
assertEquals(anchor.getDy1(), 17);
assertEquals(escher.getDy1(), 17);
assertEquals(anchor.getDy2(), 18);
assertEquals(escher.getDy2(), 18);
}
public void testChildAnchorFromScratch(){
HSSFChildAnchor anchor = new HSSFChildAnchor();
EscherChildAnchorRecord escher = (EscherChildAnchorRecord) HSSFTestHelper.getEscherAnchor(anchor);
anchor.setAnchor(11, 12, 13, 14);
assertEquals(anchor.getDx1(), 11);
assertEquals(escher.getDx1(), 11);
assertEquals(anchor.getDx2(), 13);
assertEquals(escher.getDx2(), 13);
assertEquals(anchor.getDy1(), 12);
assertEquals(escher.getDy1(), 12);
assertEquals(anchor.getDy2(), 14);
assertEquals(escher.getDy2(), 14);
anchor.setDx1(115);
assertEquals(anchor.getDx1(), 115);
assertEquals(escher.getDx1(), 115);
anchor.setDx2(116);
assertEquals(anchor.getDx2(), 116);
assertEquals(escher.getDx2(), 116);
anchor.setDy1(117);
assertEquals(anchor.getDy1(), 117);
assertEquals(escher.getDy1(), 117);
anchor.setDy2(118);
assertEquals(anchor.getDy2(), 118);
assertEquals(escher.getDy2(), 118);
}
public void testEqualsToSelf(){
HSSFClientAnchor clientAnchor = new HSSFClientAnchor(0, 1, 2, 3, (short)4, 5, (short)6, 7);
assertEquals(clientAnchor, clientAnchor);
HSSFChildAnchor childAnchor = new HSSFChildAnchor(0, 1, 2, 3);
assertEquals(childAnchor, childAnchor);
}
public void testPassIncompatibleTypeIsFalse(){
HSSFClientAnchor clientAnchor = new HSSFClientAnchor(0, 1, 2, 3, (short)4, 5, (short)6, 7);
assertNotSame(clientAnchor, "wrongType");
HSSFChildAnchor childAnchor = new HSSFChildAnchor(0, 1, 2, 3);
assertNotSame(childAnchor, "wrongType");
}
public void testNullReferenceIsFalse() {
HSSFClientAnchor clientAnchor = new HSSFClientAnchor(0, 1, 2, 3, (short)4, 5, (short)6, 7);
assertFalse("Passing null to equals should return false", clientAnchor.equals(null));
HSSFChildAnchor childAnchor = new HSSFChildAnchor(0, 1, 2, 3);
assertFalse("Passing null to equals should return false", childAnchor.equals(null));
}
public void testEqualsIsReflexiveIsSymmetric() {
HSSFClientAnchor clientAnchor1 = new HSSFClientAnchor(0, 1, 2, 3, (short)4, 5, (short)6, 7);
HSSFClientAnchor clientAnchor2 = new HSSFClientAnchor(0, 1, 2, 3, (short)4, 5, (short)6, 7);
assertTrue(clientAnchor1.equals(clientAnchor2));
assertTrue(clientAnchor1.equals(clientAnchor2));
HSSFChildAnchor childAnchor1 = new HSSFChildAnchor(0, 1, 2, 3);
HSSFChildAnchor childAnchor2 = new HSSFChildAnchor(0, 1, 2, 3);
assertTrue(childAnchor1.equals(childAnchor2));
assertTrue(childAnchor2.equals(childAnchor1));
}
public void testEqualsValues(){
HSSFClientAnchor clientAnchor1 = new HSSFClientAnchor(0, 1, 2, 3, (short)4, 5, (short)6, 7);
HSSFClientAnchor clientAnchor2 = new HSSFClientAnchor(0, 1, 2, 3, (short)4, 5, (short)6, 7);
assertEquals(clientAnchor1, clientAnchor2);
clientAnchor2.setDx1(10);
assertNotSame(clientAnchor1, clientAnchor2);
clientAnchor2.setDx1(0);
assertEquals(clientAnchor1, clientAnchor2);
clientAnchor2.setDy1(10);
assertNotSame(clientAnchor1, clientAnchor2);
clientAnchor2.setDy1(1);
assertEquals(clientAnchor1, clientAnchor2);
clientAnchor2.setDx2(10);
assertNotSame(clientAnchor1, clientAnchor2);
clientAnchor2.setDx2(2);
assertEquals(clientAnchor1, clientAnchor2);
clientAnchor2.setDy2(10);
assertNotSame(clientAnchor1, clientAnchor2);
clientAnchor2.setDy2(3);
assertEquals(clientAnchor1, clientAnchor2);
clientAnchor2.setCol1(10);
assertNotSame(clientAnchor1, clientAnchor2);
clientAnchor2.setCol1(4);
assertEquals(clientAnchor1, clientAnchor2);
clientAnchor2.setRow1(10);
assertNotSame(clientAnchor1, clientAnchor2);
clientAnchor2.setRow1(5);
assertEquals(clientAnchor1, clientAnchor2);
clientAnchor2.setCol2(10);
assertNotSame(clientAnchor1, clientAnchor2);
clientAnchor2.setCol2(6);
assertEquals(clientAnchor1, clientAnchor2);
clientAnchor2.setRow2(10);
assertNotSame(clientAnchor1, clientAnchor2);
clientAnchor2.setRow2(7);
assertEquals(clientAnchor1, clientAnchor2);
clientAnchor2.setAnchorType(3);
assertNotSame(clientAnchor1, clientAnchor2);
clientAnchor2.setAnchorType(0);
assertEquals(clientAnchor1, clientAnchor2);
HSSFChildAnchor childAnchor1 = new HSSFChildAnchor(0, 1, 2, 3);
HSSFChildAnchor childAnchor2 = new HSSFChildAnchor(0, 1, 2, 3);
childAnchor1.setDx1(10);
assertNotSame(childAnchor1, childAnchor2);
childAnchor1.setDx1(0);
assertEquals(childAnchor1, childAnchor2);
childAnchor2.setDy1(10);
assertNotSame(childAnchor1, childAnchor2);
childAnchor2.setDy1(1);
assertEquals(childAnchor1, childAnchor2);
childAnchor2.setDx2(10);
assertNotSame(childAnchor1, childAnchor2);
childAnchor2.setDx2(2);
assertEquals(childAnchor1, childAnchor2);
childAnchor2.setDy2(10);
assertNotSame(childAnchor1, childAnchor2);
childAnchor2.setDy2(3);
assertEquals(childAnchor1, childAnchor2);
}
public void testFlipped(){
HSSFChildAnchor child = new HSSFChildAnchor(2,2,1,1);
assertEquals(child.isHorizontallyFlipped(), true);
assertEquals(child.isVerticallyFlipped(), true);
assertEquals(child.getDx1(), 1);
assertEquals(child.getDx2(), 2);
assertEquals(child.getDy1(), 1);
assertEquals(child.getDy2(), 2);
child = new HSSFChildAnchor(3,3,4,4);
assertEquals(child.isHorizontallyFlipped(), false);
assertEquals(child.isVerticallyFlipped(), false);
assertEquals(child.getDx1(), 3);
assertEquals(child.getDx2(), 4);
assertEquals(child.getDy1(), 3);
assertEquals(child.getDy2(), 4);
HSSFClientAnchor client = new HSSFClientAnchor(1,1,1,1, (short)4,4,(short)3,3);
assertEquals(client.isVerticallyFlipped(), true);
assertEquals(client.isHorizontallyFlipped(), true);
assertEquals(client.getCol1(), 3);
assertEquals(client.getCol2(), 4);
assertEquals(client.getRow1(), 3);
assertEquals(client.getRow2(), 4);
client = new HSSFClientAnchor(1,1,1,1, (short)5,5,(short)6,6);
assertEquals(client.isVerticallyFlipped(), false);
assertEquals(client.isHorizontallyFlipped(), false);
assertEquals(client.getCol1(), 5);
assertEquals(client.getCol2(), 6);
assertEquals(client.getRow1(), 5);
assertEquals(client.getRow2(), 6);
}
}

View File

@ -49,17 +49,12 @@ public final class TestDrawingRecord extends TestCase {
out.write(cn.serialize()); out.write(cn.serialize());
List<Record> rec = RecordFactory.createRecords(new ByteArrayInputStream(out.toByteArray())); List<Record> rec = RecordFactory.createRecords(new ByteArrayInputStream(out.toByteArray()));
assertEquals(1, rec.size()); assertEquals(2, rec.size());
assertTrue(rec.get(0) instanceof DrawingRecord); assertTrue(rec.get(0) instanceof DrawingRecord);
assertTrue(rec.get(1) instanceof ContinueRecord);
//DrawingRecord.getData() should return concatenated data1 and data2 assertTrue(Arrays.equals(data1, ((DrawingRecord)rec.get(0)).getData()));
byte[] tmp = new byte[data1.length + data2.length]; assertTrue(Arrays.equals(data2, ((ContinueRecord)rec.get(1)).getData()));
System.arraycopy(data1, 0, tmp, 0, data1.length);
System.arraycopy(data2, 0, tmp, data1.length, data2.length);
DrawingRecord dg2 = (DrawingRecord)rec.get(0);
assertEquals(data1.length + data2.length, dg2.getData().length);
assertTrue(Arrays.equals(tmp, dg2.getData()));
} }

View File

@ -16,8 +16,18 @@
==================================================================== */ ==================================================================== */
package org.apache.poi.hssf.usermodel; package org.apache.poi.hssf.usermodel;
import org.apache.poi.ddf.*;
import org.apache.poi.hssf.model.DrawingManager2;
import org.apache.poi.hssf.model.InternalSheet; import org.apache.poi.hssf.model.InternalSheet;
import org.apache.poi.hssf.model.InternalWorkbook; import org.apache.poi.hssf.model.InternalWorkbook;
import org.apache.poi.hssf.record.EscherAggregate;
import org.apache.poi.hssf.record.ObjRecord;
import org.apache.poi.hssf.record.TextObjectRecord;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Map;
/** /**
* Helper class for HSSF tests that aren't within the * Helper class for HSSF tests that aren't within the
@ -25,6 +35,33 @@ import org.apache.poi.hssf.model.InternalWorkbook;
* UserModel things. * UserModel things.
*/ */
public class HSSFTestHelper { public class HSSFTestHelper {
public static class MockDrawingManager extends DrawingManager2 {
public MockDrawingManager (){
super(null);
}
@Override
public int allocateShapeId(short drawingGroupId) {
return 1025; //Mock value
}
@Override
public int allocateShapeId(short drawingGroupId, EscherDgRecord dg) {
return 1025;
}
public EscherDgRecord createDgRecord()
{
EscherDgRecord dg = new EscherDgRecord();
dg.setRecordId( EscherDgRecord.RECORD_ID );
dg.setOptions( (short) (16) );
dg.setNumShapes( 1 );
dg.setLastMSOSPID( 1024 );
return dg;
}
}
/** /**
* Lets non UserModel tests at the low level Workbook * Lets non UserModel tests at the low level Workbook
*/ */
@ -34,4 +71,55 @@ public class HSSFTestHelper {
public static InternalSheet getSheetForTest(HSSFSheet sheet) { public static InternalSheet getSheetForTest(HSSFSheet sheet) {
return sheet.getSheet(); return sheet.getSheet();
} }
public static HSSFPatriarch createTestPatriarch(HSSFSheet sheet, EscherAggregate agg){
return new HSSFPatriarch(sheet, agg);
}
public static EscherAggregate getEscherAggregate(HSSFPatriarch patriarch){
return patriarch._getBoundAggregate();
}
public static int allocateNewShapeId(HSSFPatriarch patriarch){
return patriarch.newShapeId();
}
public static EscherOptRecord getOptRecord(HSSFShape shape){
return shape.getOptRecord();
}
public static void convertHSSFGroup(HSSFShapeGroup shape, EscherContainerRecord escherParent, Map shapeToObj){
Class clazz = EscherAggregate.class;
try {
Method method = clazz.getDeclaredMethod("convertGroup", HSSFShapeGroup.class, EscherContainerRecord.class, Map.class);
method.setAccessible(true);
method.invoke(new EscherAggregate(new MockDrawingManager()), shape, escherParent, shapeToObj);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
public static void setShapeId(HSSFShape shape, int id){
shape.setShapeId(id);
}
public static EscherContainerRecord getEscherContainer(HSSFShape shape){
return shape.getEscherContainer();
}
public static TextObjectRecord getTextObjRecord(HSSFSimpleShape shape){
return shape.getTextObjectRecord();
}
public static ObjRecord getObjRecord(HSSFShape shape){
return shape.getObjRecord();
}
public static EscherRecord getEscherAnchor(HSSFAnchor anchor){
return anchor.getEscherAnchor();
}
} }

View File

@ -24,9 +24,12 @@ import org.apache.poi.hssf.HSSFITestDataProvider;
import org.apache.poi.hssf.HSSFTestDataSamples; import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.hssf.OldExcelFormatException; import org.apache.poi.hssf.OldExcelFormatException;
import org.apache.poi.hssf.extractor.ExcelExtractor; import org.apache.poi.hssf.extractor.ExcelExtractor;
import org.apache.poi.hssf.model.InternalSheet;
import org.apache.poi.hssf.model.InternalWorkbook; import org.apache.poi.hssf.model.InternalWorkbook;
import org.apache.poi.hssf.record.*; import org.apache.poi.hssf.record.*;
import org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate; import org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate;
import org.apache.poi.hssf.record.aggregates.PageSettingsBlock;
import org.apache.poi.hssf.record.aggregates.RecordAggregate;
import org.apache.poi.hssf.record.common.UnicodeString; import org.apache.poi.hssf.record.common.UnicodeString;
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.poifs.filesystem.POIFSFileSystem;
@ -2238,4 +2241,31 @@ if(1==2) {
// make sure we are still readable // make sure we are still readable
writeOutAndReadBack(workbook); writeOutAndReadBack(workbook);
} }
public void test51675(){
final List<Short> list = new ArrayList<Short>();
HSSFWorkbook workbook = openSample("51675.xls");
HSSFSheet sh = workbook.getSheetAt(0);
InternalSheet ish = HSSFTestHelper.getSheetForTest(sh);
PageSettingsBlock psb = (PageSettingsBlock) ish.getRecords().get(13);
psb.visitContainedRecords(new RecordAggregate.RecordVisitor() {
public void visitRecord(Record r) {
list.add(r.getSid());
}
});
assertTrue(list.get(list.size()-1).intValue() == UnknownRecord.BITMAP_00E9);
assertTrue(list.get(list.size()-2).intValue() == UnknownRecord.HEADER_FOOTER_089C);
}
public void test52272(){
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sh = wb.createSheet();
HSSFPatriarch p = sh.createDrawingPatriarch();
HSSFSimpleShape s = p.createSimpleShape(new HSSFClientAnchor());
s.setShapeType(HSSFSimpleShape.OBJECT_TYPE_LINE);
HSSFSheet sh2 = wb.cloneSheet(0);
assertNotNull(sh2.getDrawingPatriarch());
}
} }

View File

@ -19,8 +19,14 @@ package org.apache.poi.hssf.usermodel;
import junit.framework.TestCase; import junit.framework.TestCase;
import org.apache.poi.ddf.EscherDgRecord;
import org.apache.poi.ddf.EscherSpRecord;
import org.apache.poi.hssf.record.EscherAggregate;
import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.ss.util.CellRangeAddress;
import java.io.IOException;
import java.util.Arrays;
/** /**
* Test the ability to clone a sheet. * Test the ability to clone a sheet.
* If adding new records that belong to a sheet (as opposed to a book) * If adding new records that belong to a sheet (as opposed to a book)
@ -55,4 +61,74 @@ public final class TestCloneSheet extends TestCase {
assertTrue("Row 3 still should be broken", clone.isRowBroken(3)); assertTrue("Row 3 still should be broken", clone.isRowBroken(3));
} }
public void testCloneSheetWithoutDrawings(){
HSSFWorkbook b = new HSSFWorkbook();
HSSFSheet s = b.createSheet("Test");
HSSFSheet s2 = s.cloneSheet(b);
assertNull(s.getDrawingPatriarch());
assertNull(s2.getDrawingPatriarch());
assertEquals(HSSFTestHelper.getSheetForTest(s).getRecords().size(), HSSFTestHelper.getSheetForTest(s2).getRecords().size());
}
public void testCloneSheetWithEmptyDrawingAggregate(){
HSSFWorkbook b = new HSSFWorkbook();
HSSFSheet s = b.createSheet("Test");
HSSFPatriarch patriarch = s.createDrawingPatriarch();
EscherAggregate agg1 = patriarch._getBoundAggregate();
HSSFSheet s2 = s.cloneSheet(b);
patriarch = s2.getDrawingPatriarch();
EscherAggregate agg2 = patriarch._getBoundAggregate();
EscherSpRecord sp1 = (EscherSpRecord) agg1.getEscherContainer().getChild(1).getChild(0).getChild(1);
EscherSpRecord sp2 = (EscherSpRecord) agg2.getEscherContainer().getChild(1).getChild(0).getChild(1);
assertEquals(sp1.getShapeId(), 1024);
assertEquals(sp2.getShapeId(), 2048);
EscherDgRecord dg = (EscherDgRecord) agg2.getEscherContainer().getChild(0);
assertEquals(dg.getLastMSOSPID(), 2048);
assertEquals(dg.getInstance(), 0x2);
//everything except id and DgRecord.lastMSOSPID and DgRecord.Instance must be the same
sp2.setShapeId(1024);
dg.setLastMSOSPID(1024);
dg.setInstance((short) 0x1);
assertEquals(agg1.serialize().length, agg2.serialize().length);
assertEquals(agg1.toXml(""), agg2.toXml(""));
assertTrue(Arrays.equals(agg1.serialize(), agg2.serialize()));
}
public void testCloneComment() throws IOException {
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sh = wb.createSheet();
HSSFPatriarch p = sh.createDrawingPatriarch();
HSSFComment c = p.createComment(new HSSFClientAnchor(0,0,100,100, (short) 0,0,(short)5,5));
c.setColumn(1);
c.setRow(2);
c.setString(new HSSFRichTextString("qwertyuio"));
HSSFSheet sh2 = wb.cloneSheet(0);
HSSFPatriarch p2 = sh2.getDrawingPatriarch();
HSSFComment c2 = (HSSFComment) p2.getChildren().get(0);
assertTrue(Arrays.equals(c2.getTextObjectRecord().serialize(), c.getTextObjectRecord().serialize()));
assertTrue(Arrays.equals(c2.getObjRecord().serialize(), c.getObjRecord().serialize()));
assertTrue(Arrays.equals(c2.getNoteRecord().serialize(), c.getNoteRecord().serialize()));
//everything except spRecord.shapeId must be the same
assertFalse(Arrays.equals(c2.getEscherContainer().serialize(), c.getEscherContainer().serialize()));
EscherSpRecord sp = (EscherSpRecord) c2.getEscherContainer().getChild(0);
sp.setShapeId(1025);
assertTrue(Arrays.equals(c2.getEscherContainer().serialize(), c.getEscherContainer().serialize()));
}
} }

View File

@ -0,0 +1,268 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.usermodel;
import junit.framework.TestCase;
import org.apache.poi.ddf.EscherSpRecord;
import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.hssf.model.CommentShape;
import org.apache.poi.hssf.model.HSSFTestModelHelper;
import org.apache.poi.hssf.record.*;
import java.io.*;
import java.util.Arrays;
/**
* @author Evgeniy Berlog
* @date 26.06.12
*/
public class TestComment extends TestCase {
public void testResultEqualsToAbstractShape() {
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sh = wb.createSheet();
HSSFPatriarch patriarch = sh.createDrawingPatriarch();
HSSFComment comment = patriarch.createCellComment(new HSSFClientAnchor());
HSSFRow row = sh.createRow(0);
HSSFCell cell = row.createCell(0);
cell.setCellComment(comment);
CommentShape commentShape = HSSFTestModelHelper.createCommentShape(1025, comment);
assertEquals(comment.getEscherContainer().getChildRecords().size(), 5);
assertEquals(commentShape.getSpContainer().getChildRecords().size(), 5);
//sp record
byte[] expected = commentShape.getSpContainer().getChild(0).serialize();
byte[] actual = comment.getEscherContainer().getChild(0).serialize();
assertEquals(expected.length, actual.length);
assertTrue(Arrays.equals(expected, actual));
expected = commentShape.getSpContainer().getChild(2).serialize();
actual = comment.getEscherContainer().getChild(2).serialize();
assertEquals(expected.length, actual.length);
assertTrue(Arrays.equals(expected, actual));
expected = commentShape.getSpContainer().getChild(3).serialize();
actual = comment.getEscherContainer().getChild(3).serialize();
assertEquals(expected.length, actual.length);
assertTrue(Arrays.equals(expected, actual));
expected = commentShape.getSpContainer().getChild(4).serialize();
actual = comment.getEscherContainer().getChild(4).serialize();
assertEquals(expected.length, actual.length);
assertTrue(Arrays.equals(expected, actual));
ObjRecord obj = comment.getObjRecord();
ObjRecord objShape = commentShape.getObjRecord();
/**shapeId = 1025 % 1024**/
((CommonObjectDataSubRecord)objShape.getSubRecords().get(0)).setObjectId(1);
expected = obj.serialize();
actual = objShape.serialize();
TextObjectRecord tor = comment.getTextObjectRecord();
TextObjectRecord torShape = commentShape.getTextObjectRecord();
expected = tor.serialize();
actual = torShape.serialize();
assertEquals(expected.length, actual.length);
assertTrue(Arrays.equals(expected, actual));
NoteRecord note = comment.getNoteRecord();
NoteRecord noteShape = commentShape.getNoteRecord();
noteShape.setShapeId(1);
expected = note.serialize();
actual = noteShape.serialize();
assertEquals(expected.length, actual.length);
assertTrue(Arrays.equals(expected, actual));
}
public void testAddToExistingFile() {
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sh = wb.createSheet();
HSSFPatriarch patriarch = sh.createDrawingPatriarch();
int idx = wb.addPicture(new byte[]{1,2,3}, HSSFWorkbook.PICTURE_TYPE_PNG);
HSSFComment comment = patriarch.createCellComment(new HSSFClientAnchor());
comment.setString(new HSSFRichTextString("comment1"));
comment = patriarch.createCellComment(new HSSFClientAnchor(0,0,100,100,(short)0,0,(short)10,10));
comment.setString(new HSSFRichTextString("comment2"));
comment.setBackgroundImage(idx);
assertEquals(comment.getBackgroundImageId(), idx);
assertEquals(patriarch.getChildren().size(), 2);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sh = wb.getSheetAt(0);
patriarch = sh.getDrawingPatriarch();
comment = (HSSFComment) patriarch.getChildren().get(1);
assertEquals(comment.getBackgroundImageId(), idx);
comment.resetBackgroundImage();
assertEquals(comment.getBackgroundImageId(), 0);
assertEquals(patriarch.getChildren().size(), 2);
comment = patriarch.createCellComment(new HSSFClientAnchor());
comment.setString(new HSSFRichTextString("comment3"));
assertEquals(patriarch.getChildren().size(), 3);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sh = wb.getSheetAt(0);
patriarch = sh.getDrawingPatriarch();
comment = (HSSFComment) patriarch.getChildren().get(1);
assertEquals(comment.getBackgroundImageId(), 0);
assertEquals(patriarch.getChildren().size(), 3);
assertEquals(((HSSFComment) patriarch.getChildren().get(0)).getString().getString(), "comment1");
assertEquals(((HSSFComment) patriarch.getChildren().get(1)).getString().getString(), "comment2");
assertEquals(((HSSFComment) patriarch.getChildren().get(2)).getString().getString(), "comment3");
}
public void testSetGetProperties() throws IOException {
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sh = wb.createSheet();
HSSFPatriarch patriarch = sh.createDrawingPatriarch();
HSSFComment comment = patriarch.createCellComment(new HSSFClientAnchor());
comment.setString(new HSSFRichTextString("comment1"));
assertEquals(comment.getString().getString(), "comment1");
comment.setAuthor("poi");
assertEquals(comment.getAuthor(), "poi");
comment.setColumn(3);
assertEquals(comment.getColumn(), 3);
comment.setRow(4);
assertEquals(comment.getRow(), 4);
comment.setVisible(false);
assertEquals(comment.isVisible(), false);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sh = wb.getSheetAt(0);
patriarch = sh.getDrawingPatriarch();
comment = (HSSFComment) patriarch.getChildren().get(0);
assertEquals(comment.getString().getString(), "comment1");
assertEquals("poi", comment.getAuthor());
assertEquals(comment.getColumn(), 3);
assertEquals(comment.getRow(), 4);
assertEquals(comment.isVisible(), false);
comment.setString(new HSSFRichTextString("comment12"));
comment.setAuthor("poi2");
comment.setColumn(32);
comment.setRow(42);
comment.setVisible(true);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sh = wb.getSheetAt(0);
patriarch = sh.getDrawingPatriarch();
comment = (HSSFComment) patriarch.getChildren().get(0);
assertEquals(comment.getString().getString(), "comment12");
assertEquals("poi2", comment.getAuthor());
assertEquals(comment.getColumn(), 32);
assertEquals(comment.getRow(), 42);
assertEquals(comment.isVisible(), true);
}
public void testExistingFileWithComment(){
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("drawings.xls");
HSSFSheet sheet = wb.getSheet("comments");
HSSFPatriarch drawing = sheet.getDrawingPatriarch();
assertEquals(1, drawing.getChildren().size());
HSSFComment comment = (HSSFComment) drawing.getChildren().get(0);
assertEquals(comment.getAuthor(), "evgeniy");
assertEquals(comment.getString().getString(), "evgeniy:\npoi test");
assertEquals(comment.getColumn(), 1);
assertEquals(comment.getRow(), 2);
}
public void testFindComments(){
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sh = wb.createSheet();
HSSFPatriarch patriarch = sh.createDrawingPatriarch();
HSSFComment comment = patriarch.createCellComment(new HSSFClientAnchor());
HSSFRow row = sh.createRow(5);
HSSFCell cell = row.createCell(4);
cell.setCellComment(comment);
HSSFTestModelHelper.createCommentShape(0, comment);
assertNotNull(sh.findCellComment(5, 4));
assertNull(sh.findCellComment(5, 5));
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sh = wb.getSheetAt(0);
assertNotNull(sh.findCellComment(5, 4));
assertNull(sh.findCellComment(5, 5));
}
public void testInitState(){
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sh = wb.createSheet();
HSSFPatriarch patriarch = sh.createDrawingPatriarch();
EscherAggregate agg = HSSFTestHelper.getEscherAggregate(patriarch);
assertEquals(agg.getTailRecords().size(), 0);
HSSFComment comment = patriarch.createCellComment(new HSSFClientAnchor());
assertEquals(agg.getTailRecords().size(), 1);
HSSFSimpleShape shape = patriarch.createSimpleShape(new HSSFClientAnchor());
assertEquals(comment.getOptRecord().getEscherProperties().size(), 10);
}
public void testShapeId(){
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sh = wb.createSheet();
HSSFPatriarch patriarch = sh.createDrawingPatriarch();
HSSFComment comment = patriarch.createCellComment(new HSSFClientAnchor());
comment.setShapeId(2024);
/**
* SpRecord.id == shapeId
* ObjRecord.id == shapeId % 1024
* NoteRecord.id == ObjectRecord.id == shapeId % 1024
*/
assertEquals(comment.getShapeId(), 2024);
CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) comment.getObjRecord().getSubRecords().get(0);
assertEquals(cod.getObjectId(), 1000);
EscherSpRecord spRecord = (EscherSpRecord) comment.getEscherContainer().getChild(0);
assertEquals(spRecord.getShapeId(), 2024);
assertEquals(comment.getShapeId(), 2024);
assertEquals(comment.getNoteRecord().getShapeId(), 1000);
}
}

View File

@ -0,0 +1,41 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.usermodel;
import junit.framework.TestCase;
import org.apache.poi.hssf.HSSFTestDataSamples;
import java.io.IOException;
import java.util.List;
/**
* @author Evgeniy Berlog
* @date 13.07.12
*/
public class TestEmbeddedObjects extends TestCase{
public void testReadExistingObject() throws IOException {
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("drawings.xls");
List<HSSFObjectData> list = wb.getAllEmbeddedObjects();
assertEquals(list.size(), 1);
HSSFObjectData obj = list.get(0);
assertNotNull(obj.getObjectData());
assertNotNull(obj.getDirectory());
assertNotNull(obj.getOLE2ClassName());
}
}

View File

@ -32,7 +32,7 @@ public final class TestHSSFComment extends BaseTestCellComment {
} }
public void testDefaultShapeType() { public void testDefaultShapeType() {
HSSFComment comment = new HSSFComment((HSSFShape)null, (HSSFAnchor)null); HSSFComment comment = new HSSFComment((HSSFShape)null, new HSSFClientAnchor());
assertEquals(HSSFSimpleShape.OBJECT_TYPE_COMMENT, comment.getShapeType()); assertEquals(HSSFSimpleShape.OBJECT_TYPE_COMMENT, comment.getShapeType());
} }

View File

@ -17,8 +17,10 @@
package org.apache.poi.hssf.usermodel; package org.apache.poi.hssf.usermodel;
import org.apache.poi.ddf.EscherBSERecord;
import org.apache.poi.hssf.HSSFTestDataSamples; import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.hssf.HSSFITestDataProvider; import org.apache.poi.hssf.HSSFITestDataProvider;
import org.apache.poi.hssf.model.InternalSheet;
import org.apache.poi.ss.usermodel.BaseTestPicture; import org.apache.poi.ss.usermodel.BaseTestPicture;
import org.apache.poi.ss.usermodel.PictureData; import org.apache.poi.ss.usermodel.PictureData;
import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.usermodel.Workbook;
@ -149,4 +151,63 @@ public final class TestHSSFPicture extends BaseTestPicture {
assertTrue(Arrays.equals(data4, ((HSSFPicture)dr.getChildren().get(3)).getPictureData().getData())); assertTrue(Arrays.equals(data4, ((HSSFPicture)dr.getChildren().get(3)).getPictureData().getData()));
} }
public void testBSEPictureRef(){
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sh = wb.createSheet("Pictures");
HSSFPatriarch dr = sh.createDrawingPatriarch();
HSSFClientAnchor anchor = new HSSFClientAnchor();
InternalSheet ish = HSSFTestHelper.getSheetForTest(sh);
//register a picture
byte[] data1 = new byte[]{1, 2, 3};
int idx1 = wb.addPicture(data1, Workbook.PICTURE_TYPE_JPEG);
assertEquals(1, idx1);
HSSFPicture p1 = dr.createPicture(anchor, idx1);
EscherBSERecord bse = wb.getWorkbook().getBSERecord(idx1);
assertEquals(bse.getRef(), 1);
dr.createPicture(new HSSFClientAnchor(), idx1);
assertEquals(bse.getRef(), 2);
HSSFShapeGroup gr = dr.createGroup(new HSSFClientAnchor());
gr.createPicture(new HSSFChildAnchor(), idx1);
assertEquals(bse.getRef(), 3);
}
public void testReadExistingImage(){
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("drawings.xls");
HSSFSheet sheet = wb.getSheet("picture");
HSSFPatriarch drawing = sheet.getDrawingPatriarch();
assertEquals(1, drawing.getChildren().size());
HSSFPicture picture = (HSSFPicture) drawing.getChildren().get(0);
assertEquals(picture.getFileName(), "test");
}
public void testSetGetProperties(){
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sh = wb.createSheet("Pictures");
HSSFPatriarch dr = sh.createDrawingPatriarch();
HSSFClientAnchor anchor = new HSSFClientAnchor();
//register a picture
byte[] data1 = new byte[]{1, 2, 3};
int idx1 = wb.addPicture(data1, Workbook.PICTURE_TYPE_JPEG);
HSSFPicture p1 = dr.createPicture(anchor, idx1);
assertEquals(p1.getFileName(), "");
p1.setFileName("aaa");
assertEquals(p1.getFileName(), "aaa");
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sh = wb.getSheet("Pictures");
dr = sh.getDrawingPatriarch();
p1 = (HSSFPicture) dr.getChildren().get(0);
assertEquals(p1.getFileName(), "aaa");
}
} }

View File

@ -824,8 +824,8 @@ public final class TestHSSFSheet extends BaseTestSheet {
HSSFSheet sheet2 = wb2.getSheetAt(1); HSSFSheet sheet2 = wb2.getSheetAt(1);
//check that id of the drawing group was updated //check that id of the drawing group was updated
EscherDgRecord dg1 = (EscherDgRecord)sheet1.getDrawingEscherAggregate().findFirstWithId(EscherDgRecord.RECORD_ID); EscherDgRecord dg1 = (EscherDgRecord)sheet1.getDrawingPatriarch()._getBoundAggregate().findFirstWithId(EscherDgRecord.RECORD_ID);
EscherDgRecord dg2 = (EscherDgRecord)sheet2.getDrawingEscherAggregate().findFirstWithId(EscherDgRecord.RECORD_ID); EscherDgRecord dg2 = (EscherDgRecord)sheet2.getDrawingPatriarch()._getBoundAggregate().findFirstWithId(EscherDgRecord.RECORD_ID);
int dg_id_1 = dg1.getOptions() >> 4; int dg_id_1 = dg1.getOptions() >> 4;
int dg_id_2 = dg2.getOptions() >> 4; int dg_id_2 = dg2.getOptions() >> 4;
assertEquals(dg_id_1 + 1, dg_id_2); assertEquals(dg_id_1 + 1, dg_id_2);

View File

@ -0,0 +1,57 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.usermodel;
import junit.framework.TestCase;
import org.apache.poi.ddf.EscherDgRecord;
import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.hssf.record.EscherAggregate;
/**
* @author Evgeniy Berlog
* @date 01.08.12
*/
public class TestPatriarch extends TestCase {
public void testGetPatriarch(){
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sh = wb.createSheet();
assertNull(sh.getDrawingPatriarch());
HSSFPatriarch patriarch = sh.createDrawingPatriarch();
assertNotNull(patriarch);
patriarch.createSimpleShape(new HSSFClientAnchor());
patriarch.createSimpleShape(new HSSFClientAnchor());
assertSame(patriarch, sh.getDrawingPatriarch());
EscherAggregate agg = patriarch._getBoundAggregate();
EscherDgRecord dg = agg.getEscherContainer().getChildById(EscherDgRecord.RECORD_ID);
int lastId = dg.getLastMSOSPID();
assertSame(patriarch, sh.createDrawingPatriarch());
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sh = wb.getSheetAt(0);
patriarch = sh.createDrawingPatriarch();
dg = patriarch._getBoundAggregate().getEscherContainer().getChildById(EscherDgRecord.RECORD_ID);
assertEquals(lastId, dg.getLastMSOSPID());
}
}

View File

@ -0,0 +1,248 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.usermodel;
import junit.framework.TestCase;
import org.apache.poi.ddf.EscherArrayProperty;
import org.apache.poi.ddf.EscherOptRecord;
import org.apache.poi.ddf.EscherProperties;
import org.apache.poi.ddf.EscherSpRecord;
import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.hssf.model.HSSFTestModelHelper;
import org.apache.poi.hssf.model.PolygonShape;
import org.apache.poi.hssf.record.ObjRecord;
import java.io.IOException;
import java.util.Arrays;
/**
* @author Evgeniy Berlog
* @date 28.06.12
*/
public class TestPolygon extends TestCase{
public void testResultEqualsToAbstractShape() throws IOException {
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sh = wb.createSheet();
HSSFPatriarch patriarch = sh.createDrawingPatriarch();
HSSFPolygon polygon = patriarch.createPolygon(new HSSFClientAnchor());
polygon.setPolygonDrawArea( 100, 100 );
polygon.setPoints( new int[]{0, 90, 50}, new int[]{5, 5, 44} );
PolygonShape polygonShape = HSSFTestModelHelper.createPolygonShape(1024, polygon);
polygon.setShapeId(1024);
assertEquals(polygon.getEscherContainer().getChildRecords().size(), 4);
assertEquals(polygonShape.getSpContainer().getChildRecords().size(), 4);
//sp record
byte[] expected = polygonShape.getSpContainer().getChild(0).serialize();
byte[] actual = polygon.getEscherContainer().getChild(0).serialize();
assertEquals(expected.length, actual.length);
assertTrue(Arrays.equals(expected, actual));
expected = polygonShape.getSpContainer().getChild(2).serialize();
actual = polygon.getEscherContainer().getChild(2).serialize();
assertEquals(expected.length, actual.length);
assertTrue(Arrays.equals(expected, actual));
expected = polygonShape.getSpContainer().getChild(3).serialize();
actual = polygon.getEscherContainer().getChild(3).serialize();
assertEquals(expected.length, actual.length);
assertTrue(Arrays.equals(expected, actual));
ObjRecord obj = polygon.getObjRecord();
ObjRecord objShape = polygonShape.getObjRecord();
expected = obj.serialize();
actual = objShape.serialize();
assertEquals(expected.length, actual.length);
assertTrue(Arrays.equals(expected, actual));
}
public void testPolygonPoints(){
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sh = wb.createSheet();
HSSFPatriarch patriarch = sh.createDrawingPatriarch();
HSSFPolygon polygon = patriarch.createPolygon(new HSSFClientAnchor());
polygon.setPolygonDrawArea( 100, 100 );
polygon.setPoints( new int[]{0, 90, 50, 90}, new int[]{5, 5, 44, 88} );
PolygonShape polygonShape = HSSFTestModelHelper.createPolygonShape(0, polygon);
EscherArrayProperty verticesProp1 = polygon.getOptRecord().lookup(EscherProperties.GEOMETRY__VERTICES);
EscherArrayProperty verticesProp2 = ((EscherOptRecord)polygonShape.getSpContainer().getChildById(EscherOptRecord.RECORD_ID))
.lookup(EscherProperties.GEOMETRY__VERTICES);
assertEquals(verticesProp1.getNumberOfElementsInArray(), verticesProp2.getNumberOfElementsInArray());
assertEquals(verticesProp1.toXml(""), verticesProp2.toXml(""));
polygon.setPoints(new int[]{1,2,3}, new int[] {4,5,6});
assertTrue(Arrays.equals(polygon.getXPoints(), new int[]{1, 2, 3}));
assertTrue(Arrays.equals(polygon.getYPoints(), new int[]{4, 5, 6}));
polygonShape = HSSFTestModelHelper.createPolygonShape(0, polygon);
verticesProp1 = polygon.getOptRecord().lookup(EscherProperties.GEOMETRY__VERTICES);
verticesProp2 = ((EscherOptRecord)polygonShape.getSpContainer().getChildById(EscherOptRecord.RECORD_ID))
.lookup(EscherProperties.GEOMETRY__VERTICES);
assertEquals(verticesProp1.getNumberOfElementsInArray(), verticesProp2.getNumberOfElementsInArray());
assertEquals(verticesProp1.toXml(""), verticesProp2.toXml(""));
}
public void testSetGetProperties(){
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sh = wb.createSheet();
HSSFPatriarch patriarch = sh.createDrawingPatriarch();
HSSFPolygon polygon = patriarch.createPolygon(new HSSFClientAnchor());
polygon.setPolygonDrawArea( 102, 101 );
polygon.setPoints( new int[]{1,2,3}, new int[]{4,5,6} );
assertTrue(Arrays.equals(polygon.getXPoints(), new int[]{1,2,3}));
assertTrue(Arrays.equals(polygon.getYPoints(), new int[]{4, 5, 6}));
assertEquals(polygon.getDrawAreaHeight(), 101);
assertEquals(polygon.getDrawAreaWidth(), 102);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sh = wb.getSheetAt(0);
patriarch = sh.getDrawingPatriarch();
polygon = (HSSFPolygon) patriarch.getChildren().get(0);
assertTrue(Arrays.equals(polygon.getXPoints(), new int[]{1, 2, 3}));
assertTrue(Arrays.equals(polygon.getYPoints(), new int[]{4, 5, 6}));
assertEquals(polygon.getDrawAreaHeight(), 101);
assertEquals(polygon.getDrawAreaWidth(), 102);
polygon.setPolygonDrawArea( 1021, 1011 );
polygon.setPoints( new int[]{11,21,31}, new int[]{41,51,61} );
assertTrue(Arrays.equals(polygon.getXPoints(), new int[]{11, 21, 31}));
assertTrue(Arrays.equals(polygon.getYPoints(), new int[]{41, 51, 61}));
assertEquals(polygon.getDrawAreaHeight(), 1011);
assertEquals(polygon.getDrawAreaWidth(), 1021);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sh = wb.getSheetAt(0);
patriarch = sh.getDrawingPatriarch();
polygon = (HSSFPolygon) patriarch.getChildren().get(0);
assertTrue(Arrays.equals(polygon.getXPoints(), new int[]{11, 21, 31}));
assertTrue(Arrays.equals(polygon.getYPoints(), new int[]{41, 51, 61}));
assertEquals(polygon.getDrawAreaHeight(), 1011);
assertEquals(polygon.getDrawAreaWidth(), 1021);
}
public void testAddToExistingFile(){
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sh = wb.createSheet();
HSSFPatriarch patriarch = sh.createDrawingPatriarch();
HSSFPolygon polygon = patriarch.createPolygon(new HSSFClientAnchor());
polygon.setPolygonDrawArea( 102, 101 );
polygon.setPoints( new int[]{1,2,3}, new int[]{4,5,6} );
HSSFPolygon polygon1 = patriarch.createPolygon(new HSSFClientAnchor());
polygon1.setPolygonDrawArea( 103, 104 );
polygon1.setPoints( new int[]{11,12,13}, new int[]{14,15,16} );
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sh = wb.getSheetAt(0);
patriarch = sh.getDrawingPatriarch();
assertEquals(patriarch.getChildren().size(), 2);
HSSFPolygon polygon2 = patriarch.createPolygon(new HSSFClientAnchor());
polygon2.setPolygonDrawArea( 203, 204 );
polygon2.setPoints( new int[]{21,22,23}, new int[]{24,25,26} );
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sh = wb.getSheetAt(0);
patriarch = sh.getDrawingPatriarch();
assertEquals(patriarch.getChildren().size(), 3);
polygon = (HSSFPolygon) patriarch.getChildren().get(0);
polygon1 = (HSSFPolygon) patriarch.getChildren().get(1);
polygon2 = (HSSFPolygon) patriarch.getChildren().get(2);
assertTrue(Arrays.equals(polygon.getXPoints(), new int[]{1, 2, 3}));
assertTrue(Arrays.equals(polygon.getYPoints(), new int[]{4,5,6}));
assertEquals(polygon.getDrawAreaHeight(), 101);
assertEquals(polygon.getDrawAreaWidth(), 102);
assertTrue(Arrays.equals(polygon1.getXPoints(), new int[]{11,12,13}));
assertTrue(Arrays.equals(polygon1.getYPoints(), new int[]{14,15,16}));
assertEquals(polygon1.getDrawAreaHeight(), 104);
assertEquals(polygon1.getDrawAreaWidth(), 103);
assertTrue(Arrays.equals(polygon2.getXPoints(), new int[]{21,22,23}));
assertTrue(Arrays.equals(polygon2.getYPoints(), new int[]{24,25,26}));
assertEquals(polygon2.getDrawAreaHeight(), 204);
assertEquals(polygon2.getDrawAreaWidth(), 203);
}
public void testExistingFile() throws IOException {
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("drawings.xls");
HSSFSheet sheet = wb.getSheet("polygon");
HSSFPatriarch drawing = sheet.getDrawingPatriarch();
assertEquals(1, drawing.getChildren().size());
HSSFPolygon polygon = (HSSFPolygon) drawing.getChildren().get(0);
assertEquals(polygon.getDrawAreaHeight(), 2466975);
assertEquals(polygon.getDrawAreaWidth(), 3686175);
assertTrue(Arrays.equals(polygon.getXPoints(), new int[]{0, 0, 31479, 16159, 19676, 20502}));
assertTrue(Arrays.equals(polygon.getYPoints(), new int[]{0, 0, 36, 56, 34, 18}));
}
public void testPolygonType(){
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sh = wb.createSheet();
HSSFPatriarch patriarch = sh.createDrawingPatriarch();
HSSFPolygon polygon = patriarch.createPolygon(new HSSFClientAnchor());
polygon.setPolygonDrawArea( 102, 101 );
polygon.setPoints( new int[]{1,2,3}, new int[]{4,5,6} );
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sh = wb.getSheetAt(0);
patriarch = sh.getDrawingPatriarch();
HSSFPolygon polygon1 = patriarch.createPolygon(new HSSFClientAnchor());
polygon1.setPolygonDrawArea( 102, 101 );
polygon1.setPoints( new int[]{1,2,3}, new int[]{4,5,6} );
EscherSpRecord spRecord = polygon1.getEscherContainer().getChildById(EscherSpRecord.RECORD_ID);
spRecord.setShapeType((short)77/**RANDOM**/);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sh = wb.getSheetAt(0);
patriarch = sh.getDrawingPatriarch();
assertEquals(patriarch.getChildren().size(), 2);
assertTrue(patriarch.getChildren().get(0) instanceof HSSFPolygon);
assertTrue(patriarch.getChildren().get(1) instanceof HSSFPolygon);
}
}

View File

@ -0,0 +1,279 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.usermodel;
import junit.framework.TestCase;
import org.apache.poi.ddf.EscherContainerRecord;
import org.apache.poi.ddf.EscherSpgrRecord;
import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.hssf.record.EscherAggregate;
import org.apache.poi.hssf.record.ObjRecord;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
/**
* @author Evgeniy Berlog
* @date 29.06.12
*/
public class TestShapeGroup extends TestCase{
public void testSetGetCoordinates(){
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sh = wb.createSheet();
HSSFPatriarch patriarch = sh.createDrawingPatriarch();
HSSFShapeGroup group = patriarch.createGroup(new HSSFClientAnchor());
assertEquals(group.getX1(), 0);
assertEquals(group.getY1(), 0);
assertEquals(group.getX2(), 1023);
assertEquals(group.getY2(), 255);
group.setCoordinates(1,2,3,4);
assertEquals(group.getX1(), 1);
assertEquals(group.getY1(), 2);
assertEquals(group.getX2(), 3);
assertEquals(group.getY2(), 4);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sh = wb.getSheetAt(0);
patriarch = sh.getDrawingPatriarch();
group = (HSSFShapeGroup) patriarch.getChildren().get(0);
assertEquals(group.getX1(), 1);
assertEquals(group.getY1(), 2);
assertEquals(group.getX2(), 3);
assertEquals(group.getY2(), 4);
}
public void testAddToExistingFile(){
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sh = wb.createSheet();
HSSFPatriarch patriarch = sh.createDrawingPatriarch();
HSSFShapeGroup group1 = patriarch.createGroup(new HSSFClientAnchor());
HSSFShapeGroup group2 = patriarch.createGroup(new HSSFClientAnchor());
group1.setCoordinates(1,2,3,4);
group2.setCoordinates(5,6,7,8);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sh = wb.getSheetAt(0);
patriarch = sh.getDrawingPatriarch();
assertEquals(patriarch.getChildren().size(), 2);
HSSFShapeGroup group3 = patriarch.createGroup(new HSSFClientAnchor());
group3.setCoordinates(9,10,11,12);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sh = wb.getSheetAt(0);
patriarch = sh.getDrawingPatriarch();
assertEquals(patriarch.getChildren().size(), 3);
}
public void testModify() throws Exception {
HSSFWorkbook wb = new HSSFWorkbook();
// create a sheet with a text box
HSSFSheet sheet = wb.createSheet();
HSSFPatriarch patriarch = sheet.createDrawingPatriarch();
HSSFShapeGroup group1 = patriarch.createGroup(new
HSSFClientAnchor(0,0,0,0,
(short)0, 0, (short)15, 25));
group1.setCoordinates(0, 0, 792, 612);
HSSFTextbox textbox1 = group1.createTextbox(new
HSSFChildAnchor(100, 100, 300, 300));
HSSFRichTextString rt1 = new HSSFRichTextString("Hello, World!");
textbox1.setString(rt1);
// write, read back and check that our text box is there
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sheet = wb.getSheetAt(0);
patriarch = sheet.getDrawingPatriarch();
assertEquals(1, patriarch.getChildren().size());
group1 = (HSSFShapeGroup)patriarch.getChildren().get(0);
assertEquals(1, group1.getChildren().size());
textbox1 = (HSSFTextbox)group1.getChildren().get(0);
assertEquals("Hello, World!", textbox1.getString().getString());
// modify anchor
assertEquals(new HSSFChildAnchor(100, 100, 300, 300),
textbox1.getAnchor());
HSSFChildAnchor newAnchor = new HSSFChildAnchor(200,200, 400, 400);
textbox1.setAnchor(newAnchor);
// modify text
textbox1.setString(new HSSFRichTextString("Hello, World! (modified)"));
// add a new text box
HSSFTextbox textbox2 = group1.createTextbox(new
HSSFChildAnchor(400, 400, 600, 600));
HSSFRichTextString rt2 = new HSSFRichTextString("Hello, World-2");
textbox2.setString(rt2);
assertEquals(2, group1.getChildren().size());
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sheet = wb.getSheetAt(0);
patriarch = sheet.getDrawingPatriarch();
assertEquals(1, patriarch.getChildren().size());
group1 = (HSSFShapeGroup)patriarch.getChildren().get(0);
assertEquals(2, group1.getChildren().size());
textbox1 = (HSSFTextbox)group1.getChildren().get(0);
assertEquals("Hello, World! (modified)",
textbox1.getString().getString());
assertEquals(new HSSFChildAnchor(200,200, 400, 400),
textbox1.getAnchor());
textbox2 = (HSSFTextbox)group1.getChildren().get(1);
assertEquals("Hello, World-2", textbox2.getString().getString());
assertEquals(new HSSFChildAnchor(400, 400, 600, 600),
textbox2.getAnchor());
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sheet = wb.getSheetAt(0);
patriarch = sheet.getDrawingPatriarch();
group1 = (HSSFShapeGroup)patriarch.getChildren().get(0);
textbox1 = (HSSFTextbox)group1.getChildren().get(0);
textbox2 = (HSSFTextbox)group1.getChildren().get(1);
HSSFTextbox textbox3 = group1.createTextbox(new
HSSFChildAnchor(400,200, 600, 400));
HSSFRichTextString rt3 = new HSSFRichTextString("Hello, World-3");
textbox3.setString(rt3);
}
public void testAddShapesToGroup(){
HSSFWorkbook wb = new HSSFWorkbook();
// create a sheet with a text box
HSSFSheet sheet = wb.createSheet();
HSSFPatriarch patriarch = sheet.createDrawingPatriarch();
HSSFShapeGroup group = patriarch.createGroup(new HSSFClientAnchor());
int index = wb.addPicture(new byte[]{1,2,3}, HSSFWorkbook.PICTURE_TYPE_JPEG);
group.createPicture(new HSSFChildAnchor(), index);
HSSFPolygon polygon = group.createPolygon(new HSSFChildAnchor());
polygon.setPoints(new int[]{1,100, 1}, new int[]{1, 50, 100});
group.createTextbox(new HSSFChildAnchor());
group.createShape(new HSSFChildAnchor());
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sheet = wb.getSheetAt(0);
patriarch = sheet.getDrawingPatriarch();
assertEquals(1, patriarch.getChildren().size());
assertTrue(patriarch.getChildren().get(0) instanceof HSSFShapeGroup);
group = (HSSFShapeGroup) patriarch.getChildren().get(0);
assertEquals(group.getChildren().size(), 4);
assertTrue(group.getChildren().get(0) instanceof HSSFPicture);
assertTrue(group.getChildren().get(1) instanceof HSSFPolygon);
assertTrue(group.getChildren().get(2) instanceof HSSFTextbox);
assertTrue(group.getChildren().get(3) instanceof HSSFSimpleShape);
HSSFShapeGroup group2 = patriarch.createGroup(new HSSFClientAnchor());
index = wb.addPicture(new byte[]{2,2,2}, HSSFWorkbook.PICTURE_TYPE_JPEG);
group2.createPicture(new HSSFChildAnchor(), index);
polygon = group2.createPolygon(new HSSFChildAnchor());
polygon.setPoints(new int[]{1,100, 1}, new int[]{1, 50, 100});
group2.createTextbox(new HSSFChildAnchor());
group2.createShape(new HSSFChildAnchor());
group2.createShape(new HSSFChildAnchor());
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sheet = wb.getSheetAt(0);
patriarch = sheet.getDrawingPatriarch();
assertEquals(2, patriarch.getChildren().size());
group = (HSSFShapeGroup) patriarch.getChildren().get(1);
assertEquals(group.getChildren().size(), 5);
assertTrue(group.getChildren().get(0) instanceof HSSFPicture);
assertTrue(group.getChildren().get(1) instanceof HSSFPolygon);
assertTrue(group.getChildren().get(2) instanceof HSSFTextbox);
assertTrue(group.getChildren().get(3) instanceof HSSFSimpleShape);
assertTrue(group.getChildren().get(4) instanceof HSSFSimpleShape);
group.getShapeId();
}
public void testSpgrRecord(){
HSSFWorkbook wb = new HSSFWorkbook();
// create a sheet with a text box
HSSFSheet sheet = wb.createSheet();
HSSFPatriarch patriarch = sheet.createDrawingPatriarch();
HSSFShapeGroup group = patriarch.createGroup(new HSSFClientAnchor());
assertSame(((EscherContainerRecord)group.getEscherContainer().getChild(0)).getChildById(EscherSpgrRecord.RECORD_ID), getSpgrRecord(group));
}
private static EscherSpgrRecord getSpgrRecord(HSSFShapeGroup group) {
Field spgrField = null;
try {
spgrField = group.getClass().getDeclaredField("_spgrRecord");
spgrField.setAccessible(true);
return (EscherSpgrRecord) spgrField.get(group);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
public void testClearShapes(){
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet();
HSSFPatriarch patriarch = sheet.createDrawingPatriarch();
HSSFShapeGroup group = patriarch.createGroup(new HSSFClientAnchor());
group.createShape(new HSSFChildAnchor());
group.createShape(new HSSFChildAnchor());
EscherAggregate agg = HSSFTestHelper.getEscherAggregate(patriarch);
assertEquals(agg.getShapeToObjMapping().size(), 5);
assertEquals(agg.getTailRecords().size(), 0);
assertEquals(group.getChildren().size(), 2);
group.clear();
assertEquals(agg.getShapeToObjMapping().size(), 1);
assertEquals(agg.getTailRecords().size(), 0);
assertEquals(group.getChildren().size(), 0);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sheet = wb.getSheetAt(0);
patriarch = sheet.getDrawingPatriarch();
group = (HSSFShapeGroup) patriarch.getChildren().get(0);
assertEquals(agg.getShapeToObjMapping().size(), 1);
assertEquals(agg.getTailRecords().size(), 0);
assertEquals(group.getChildren().size(), 0);
}
}

View File

@ -0,0 +1,199 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.usermodel;
import junit.framework.TestCase;
import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.hssf.model.HSSFTestModelHelper;
import org.apache.poi.hssf.model.TextboxShape;
import org.apache.poi.hssf.record.CommonObjectDataSubRecord;
import org.apache.poi.hssf.record.ObjRecord;
import org.apache.poi.hssf.record.TextObjectRecord;
import java.util.Arrays;
/**
* @author Evgeniy Berlog
* @date 25.06.12
*/
public class TestText extends TestCase {
public void testResultEqualsToAbstractShape() {
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sh = wb.createSheet();
HSSFPatriarch patriarch = sh.createDrawingPatriarch();
HSSFTextbox textbox = patriarch.createTextbox(new HSSFClientAnchor());
TextboxShape textboxShape = HSSFTestModelHelper.createTextboxShape(1025, textbox);
assertEquals(textbox.getEscherContainer().getChildRecords().size(), 5);
assertEquals(textboxShape.getSpContainer().getChildRecords().size(), 5);
//sp record
byte[] expected = textboxShape.getSpContainer().getChild(0).serialize();
byte[] actual = textbox.getEscherContainer().getChild(0).serialize();
assertEquals(expected.length, actual.length);
assertTrue(Arrays.equals(expected, actual));
expected = textboxShape.getSpContainer().getChild(2).serialize();
actual = textbox.getEscherContainer().getChild(2).serialize();
assertEquals(expected.length, actual.length);
assertTrue(Arrays.equals(expected, actual));
expected = textboxShape.getSpContainer().getChild(3).serialize();
actual = textbox.getEscherContainer().getChild(3).serialize();
assertEquals(expected.length, actual.length);
assertTrue(Arrays.equals(expected, actual));
expected = textboxShape.getSpContainer().getChild(4).serialize();
actual = textbox.getEscherContainer().getChild(4).serialize();
assertEquals(expected.length, actual.length);
assertTrue(Arrays.equals(expected, actual));
ObjRecord obj = textbox.getObjRecord();
ObjRecord objShape = textboxShape.getObjRecord();
expected = obj.serialize();
actual = objShape.serialize();
TextObjectRecord tor = textbox.getTextObjectRecord();
TextObjectRecord torShape = textboxShape.getTextObjectRecord();
expected = tor.serialize();
actual = torShape.serialize();
assertEquals(expected.length, actual.length);
assertTrue(Arrays.equals(expected, actual));
}
public void testAddTextToExistingFile() {
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sh = wb.createSheet();
HSSFPatriarch patriarch = sh.createDrawingPatriarch();
HSSFTextbox textbox = patriarch.createTextbox(new HSSFClientAnchor());
textbox.setString(new HSSFRichTextString("just for test"));
HSSFTextbox textbox2 = patriarch.createTextbox(new HSSFClientAnchor());
textbox2.setString(new HSSFRichTextString("just for test2"));
assertEquals(patriarch.getChildren().size(), 2);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sh = wb.getSheetAt(0);
patriarch = sh.getDrawingPatriarch();
assertEquals(patriarch.getChildren().size(), 2);
HSSFTextbox text3 = patriarch.createTextbox(new HSSFClientAnchor());
text3.setString(new HSSFRichTextString("text3"));
assertEquals(patriarch.getChildren().size(), 3);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sh = wb.getSheetAt(0);
patriarch = sh.getDrawingPatriarch();
assertEquals(patriarch.getChildren().size(), 3);
assertEquals(((HSSFTextbox) patriarch.getChildren().get(0)).getString().getString(), "just for test");
assertEquals(((HSSFTextbox) patriarch.getChildren().get(1)).getString().getString(), "just for test2");
assertEquals(((HSSFTextbox) patriarch.getChildren().get(2)).getString().getString(), "text3");
}
public void testSetGetProperties() {
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sh = wb.createSheet();
HSSFPatriarch patriarch = sh.createDrawingPatriarch();
HSSFTextbox textbox = patriarch.createTextbox(new HSSFClientAnchor());
textbox.setString(new HSSFRichTextString("test"));
assertEquals(textbox.getString().getString(), "test");
textbox.setHorizontalAlignment((short) 5);
assertEquals(textbox.getHorizontalAlignment(), 5);
textbox.setVerticalAlignment((short) 6);
assertEquals(textbox.getVerticalAlignment(), (short) 6);
textbox.setMarginBottom(7);
assertEquals(textbox.getMarginBottom(), 7);
textbox.setMarginLeft(8);
assertEquals(textbox.getMarginLeft(), 8);
textbox.setMarginRight(9);
assertEquals(textbox.getMarginRight(), 9);
textbox.setMarginTop(10);
assertEquals(textbox.getMarginTop(), 10);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sh = wb.getSheetAt(0);
patriarch = sh.getDrawingPatriarch();
textbox = (HSSFTextbox) patriarch.getChildren().get(0);
assertEquals(textbox.getString().getString(), "test");
assertEquals(textbox.getHorizontalAlignment(), 5);
assertEquals(textbox.getVerticalAlignment(), (short) 6);
assertEquals(textbox.getMarginBottom(), 7);
assertEquals(textbox.getMarginLeft(), 8);
assertEquals(textbox.getMarginRight(), 9);
assertEquals(textbox.getMarginTop(), 10);
textbox.setString(new HSSFRichTextString("test1"));
textbox.setHorizontalAlignment(HSSFTextbox.HORIZONTAL_ALIGNMENT_CENTERED);
textbox.setVerticalAlignment(HSSFTextbox.VERTICAL_ALIGNMENT_TOP);
textbox.setMarginBottom(71);
textbox.setMarginLeft(81);
textbox.setMarginRight(91);
textbox.setMarginTop(101);
assertEquals(textbox.getString().getString(), "test1");
assertEquals(textbox.getHorizontalAlignment(), HSSFTextbox.HORIZONTAL_ALIGNMENT_CENTERED);
assertEquals(textbox.getVerticalAlignment(), HSSFTextbox.VERTICAL_ALIGNMENT_TOP);
assertEquals(textbox.getMarginBottom(), 71);
assertEquals(textbox.getMarginLeft(), 81);
assertEquals(textbox.getMarginRight(), 91);
assertEquals(textbox.getMarginTop(), 101);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sh = wb.getSheetAt(0);
patriarch = sh.getDrawingPatriarch();
textbox = (HSSFTextbox) patriarch.getChildren().get(0);
assertEquals(textbox.getString().getString(), "test1");
assertEquals(textbox.getHorizontalAlignment(), HSSFTextbox.HORIZONTAL_ALIGNMENT_CENTERED);
assertEquals(textbox.getVerticalAlignment(), HSSFTextbox.VERTICAL_ALIGNMENT_TOP);
assertEquals(textbox.getMarginBottom(), 71);
assertEquals(textbox.getMarginLeft(), 81);
assertEquals(textbox.getMarginRight(), 91);
assertEquals(textbox.getMarginTop(), 101);
}
public void testExistingFileWithText(){
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("drawings.xls");
HSSFSheet sheet = wb.getSheet("text");
HSSFPatriarch drawing = sheet.getDrawingPatriarch();
assertEquals(1, drawing.getChildren().size());
HSSFTextbox textbox = (HSSFTextbox) drawing.getChildren().get(0);
assertEquals(textbox.getHorizontalAlignment(), HSSFTextbox.HORIZONTAL_ALIGNMENT_LEFT);
assertEquals(textbox.getVerticalAlignment(), HSSFTextbox.VERTICAL_ALIGNMENT_TOP);
assertEquals(textbox.getMarginTop(), 0);
assertEquals(textbox.getMarginBottom(), 3600000);
assertEquals(textbox.getMarginLeft(), 3600000);
assertEquals(textbox.getMarginRight(), 0);
assertEquals(textbox.getString().getString(), "teeeeesssstttt");
}
}

BIN
test-data/spreadsheet/45129.xls Executable file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
test-data/spreadsheet/dg-text.xls Executable file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.