#41047 - Support hyperlinks in HSLF shapes and textruns
#47291 - Cannot open link correctly which insert in ppt HSLF hyperlink code was all over the place - moved most of it into HSLFHyperlink extended common sl for hyperlinks extended XSLF shape linking and added XSLFTextShape.appendText to go along with HSLF adapted/fixed documentation added convenience methods to the hyperlink classes to address the different targets git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1726458 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
6d56feee90
commit
5fad9af36f
@ -39,38 +39,26 @@ public abstract class CreateHyperlink {
|
|||||||
HSLFSlide slideC = ppt.createSlide();
|
HSLFSlide slideC = ppt.createSlide();
|
||||||
|
|
||||||
// link to a URL
|
// link to a URL
|
||||||
HSLFTextBox textBox1 = new HSLFTextBox();
|
HSLFTextBox textBox1 = slideA.createTextBox();
|
||||||
textBox1.setText("Apache POI");
|
textBox1.setText("Apache POI");
|
||||||
textBox1.setAnchor(new Rectangle(100, 100, 200, 50));
|
textBox1.setAnchor(new Rectangle(100, 100, 200, 50));
|
||||||
|
|
||||||
String text = textBox1.getText();
|
HSLFHyperlink link1 = textBox1.getTextParagraphs().get(0).getTextRuns().get(0).createHyperlink();
|
||||||
HSLFHyperlink link = new HSLFHyperlink();
|
link1.linkToUrl("http://www.apache.org");
|
||||||
link.setAddress("http://www.apache.org");
|
link1.setLabel(textBox1.getText());
|
||||||
link.setLabel(textBox1.getText());
|
|
||||||
int linkId = ppt.addHyperlink(link);
|
|
||||||
|
|
||||||
// apply link to the text
|
|
||||||
textBox1.setHyperlink(linkId, 0, text.length());
|
|
||||||
|
|
||||||
slideA.addShape(textBox1);
|
|
||||||
|
|
||||||
// link to another slide
|
// link to another slide
|
||||||
HSLFTextBox textBox2 = new HSLFTextBox();
|
HSLFTextBox textBox2 = slideA.createTextBox();
|
||||||
textBox2.setText("Go to slide #3");
|
textBox2.setText("Go to slide #3");
|
||||||
textBox2.setAnchor(new Rectangle(100, 300, 200, 50));
|
textBox2.setAnchor(new Rectangle(100, 300, 200, 50));
|
||||||
|
|
||||||
HSLFHyperlink link2 = new HSLFHyperlink();
|
HSLFHyperlink link2 = textBox2.getTextParagraphs().get(0).getTextRuns().get(0).createHyperlink();
|
||||||
link2.setAddress(slideC);
|
link2.linkToSlide(slideC);
|
||||||
ppt.addHyperlink(link2);
|
|
||||||
|
|
||||||
// apply link to the whole shape
|
|
||||||
textBox2.setHyperlink(link2);
|
|
||||||
|
|
||||||
slideA.addShape(textBox2);
|
|
||||||
|
|
||||||
FileOutputStream out = new FileOutputStream("hyperlink.ppt");
|
FileOutputStream out = new FileOutputStream("hyperlink.ppt");
|
||||||
ppt.write(out);
|
ppt.write(out);
|
||||||
out.close();
|
out.close();
|
||||||
|
|
||||||
|
ppt.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,12 +19,15 @@ package org.apache.poi.hslf.examples;
|
|||||||
|
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
import org.apache.poi.hslf.usermodel.HSLFHyperlink;
|
import org.apache.poi.hslf.usermodel.HSLFHyperlink;
|
||||||
import org.apache.poi.hslf.usermodel.HSLFShape;
|
import org.apache.poi.hslf.usermodel.HSLFShape;
|
||||||
|
import org.apache.poi.hslf.usermodel.HSLFSimpleShape;
|
||||||
import org.apache.poi.hslf.usermodel.HSLFSlide;
|
import org.apache.poi.hslf.usermodel.HSLFSlide;
|
||||||
import org.apache.poi.hslf.usermodel.HSLFSlideShow;
|
import org.apache.poi.hslf.usermodel.HSLFSlideShow;
|
||||||
import org.apache.poi.hslf.usermodel.HSLFTextParagraph;
|
import org.apache.poi.hslf.usermodel.HSLFTextParagraph;
|
||||||
|
import org.apache.poi.hslf.usermodel.HSLFTextRun;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Demonstrates how to read hyperlinks from a presentation
|
* Demonstrates how to read hyperlinks from a presentation
|
||||||
@ -44,12 +47,14 @@ public final class Hyperlinks {
|
|||||||
|
|
||||||
// read hyperlinks from the slide's text runs
|
// read hyperlinks from the slide's text runs
|
||||||
System.out.println("- reading hyperlinks from the text runs");
|
System.out.println("- reading hyperlinks from the text runs");
|
||||||
for (List<HSLFTextParagraph> txtParas : slide.getTextParagraphs()) {
|
for (List<HSLFTextParagraph> paras : slide.getTextParagraphs()) {
|
||||||
List<HSLFHyperlink> links = HSLFHyperlink.find(txtParas);
|
for (HSLFTextParagraph para : paras) {
|
||||||
String text = HSLFTextParagraph.getRawText(txtParas);
|
for (HSLFTextRun run : para) {
|
||||||
|
HSLFHyperlink link = run.getHyperlink();
|
||||||
for (HSLFHyperlink link : links) {
|
if (link != null) {
|
||||||
System.out.println(toStr(link, text));
|
System.out.println(toStr(link, run.getRawText()));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,18 +63,21 @@ public final class Hyperlinks {
|
|||||||
// read such hyperlinks
|
// read such hyperlinks
|
||||||
System.out.println("- reading hyperlinks from the slide's shapes");
|
System.out.println("- reading hyperlinks from the slide's shapes");
|
||||||
for (HSLFShape sh : slide.getShapes()) {
|
for (HSLFShape sh : slide.getShapes()) {
|
||||||
HSLFHyperlink link = HSLFHyperlink.find(sh);
|
if (sh instanceof HSLFSimpleShape) {
|
||||||
if (link == null) continue;
|
HSLFHyperlink link = ((HSLFSimpleShape)sh).getHyperlink();
|
||||||
System.out.println(toStr(link, null));
|
if (link != null) {
|
||||||
|
System.out.println(toStr(link, null));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ppt.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static String toStr(HSLFHyperlink link, String rawText) {
|
static String toStr(HSLFHyperlink link, String rawText) {
|
||||||
//in ppt end index is inclusive
|
//in ppt end index is inclusive
|
||||||
String formatStr = "title: %1$s, address: %2$s" + (rawText == null ? "" : ", start: %3$s, end: %4$s, substring: %5$s");
|
String formatStr = "title: %1$s, address: %2$s" + (rawText == null ? "" : ", start: %3$s, end: %4$s, substring: %5$s");
|
||||||
String substring = (rawText == null) ? "" : rawText.substring(link.getStartIndex(), link.getEndIndex()-1);
|
return String.format(Locale.ROOT, formatStr, link.getLabel(), link.getAddress(), link.getStartIndex(), link.getEndIndex(), rawText);
|
||||||
return String.format(formatStr, link.getLabel(), link.getAddress(), link.getStartIndex(), link.getEndIndex(), substring);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,7 @@ public class Tutorial6 {
|
|||||||
XSLFTextRun r2 = shape2.addNewTextParagraph().addNewTextRun();
|
XSLFTextRun r2 = shape2.addNewTextParagraph().addNewTextRun();
|
||||||
XSLFHyperlink link2 = r2.createHyperlink();
|
XSLFHyperlink link2 = r2.createHyperlink();
|
||||||
r2.setText("Go to the second slide"); // visible text
|
r2.setText("Go to the second slide"); // visible text
|
||||||
link2.setAddress(slide2); // link address
|
link2.linkToSlide(slide2); // link address
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ public class DrawPictureShape extends DrawSimpleShape {
|
|||||||
* Returns an ImageRenderer for the PictureData
|
* Returns an ImageRenderer for the PictureData
|
||||||
*
|
*
|
||||||
* @param graphics
|
* @param graphics
|
||||||
* @return
|
* @return the image renderer
|
||||||
*/
|
*/
|
||||||
public static ImageRenderer getImageRenderer(Graphics2D graphics, String contentType) {
|
public static ImageRenderer getImageRenderer(Graphics2D graphics, String contentType) {
|
||||||
ImageRenderer renderer = (ImageRenderer)graphics.getRenderingHint(Drawable.IMAGE_RENDERER);
|
ImageRenderer renderer = (ImageRenderer)graphics.getRenderingHint(Drawable.IMAGE_RENDERER);
|
||||||
|
@ -20,5 +20,59 @@ package org.apache.poi.sl.usermodel;
|
|||||||
/**
|
/**
|
||||||
* A PowerPoint hyperlink
|
* A PowerPoint hyperlink
|
||||||
*/
|
*/
|
||||||
public interface Hyperlink extends org.apache.poi.common.usermodel.Hyperlink {
|
public interface Hyperlink<
|
||||||
|
S extends Shape<S,P>,
|
||||||
|
P extends TextParagraph<S,P,?>
|
||||||
|
> extends org.apache.poi.common.usermodel.Hyperlink {
|
||||||
|
/**
|
||||||
|
* Link to an email
|
||||||
|
*
|
||||||
|
* @param emailAddress the email address
|
||||||
|
* @since POI 3.14-Beta2
|
||||||
|
*/
|
||||||
|
void linkToEmail(String emailAddress);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Link to a web page / URL
|
||||||
|
*
|
||||||
|
* @param url the url
|
||||||
|
* @since POI 3.14-Beta2
|
||||||
|
*/
|
||||||
|
void linkToUrl(String url);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Link to a slide in this slideshow
|
||||||
|
*
|
||||||
|
* @param slide the linked slide
|
||||||
|
* @since POI 3.14-Beta2
|
||||||
|
*/
|
||||||
|
void linkToSlide(Slide<S,P> slide);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Link to the next slide (relative from the current)
|
||||||
|
*
|
||||||
|
* @since POI 3.14-Beta2
|
||||||
|
*/
|
||||||
|
void linkToNextSlide();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Link to the previous slide (relative from the current)
|
||||||
|
*
|
||||||
|
* @since POI 3.14-Beta2
|
||||||
|
*/
|
||||||
|
void linkToPreviousSlide();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Link to the first slide in this slideshow
|
||||||
|
*
|
||||||
|
* @since POI 3.14-Beta2
|
||||||
|
*/
|
||||||
|
void linkToFirstSlide();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Link to the last slide in this slideshow
|
||||||
|
*
|
||||||
|
* @since POI 3.14-Beta2
|
||||||
|
*/
|
||||||
|
void linkToLastSlide();
|
||||||
}
|
}
|
||||||
|
@ -83,4 +83,24 @@ public interface SimpleShape<
|
|||||||
* the solid fill attribute from the underlying implementation
|
* the solid fill attribute from the underlying implementation
|
||||||
*/
|
*/
|
||||||
void setFillColor(Color color);
|
void setFillColor(Color color);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the hyperlink assigned to this shape
|
||||||
|
*
|
||||||
|
* @return the hyperlink assigned to this shape
|
||||||
|
* or <code>null</code> if not found.
|
||||||
|
*
|
||||||
|
* @since POI 3.14-Beta1
|
||||||
|
*/
|
||||||
|
Hyperlink<S,P> getHyperlink();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a hyperlink and asigns it to this shape.
|
||||||
|
* If the shape has already a hyperlink assigned, return it instead
|
||||||
|
*
|
||||||
|
* @return the hyperlink assigned to this shape
|
||||||
|
*
|
||||||
|
* @since POI 3.14-Beta1
|
||||||
|
*/
|
||||||
|
Hyperlink<S,P> createHyperlink();
|
||||||
}
|
}
|
||||||
|
@ -161,6 +161,19 @@ public interface TextRun {
|
|||||||
* Return the associated hyperlink
|
* Return the associated hyperlink
|
||||||
*
|
*
|
||||||
* @return the associated hyperlink or null if no hyperlink was set
|
* @return the associated hyperlink or null if no hyperlink was set
|
||||||
|
*
|
||||||
|
* @since POI 3.14-Beta2
|
||||||
*/
|
*/
|
||||||
Hyperlink getHyperlink();
|
Hyperlink<?,?> getHyperlink();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new hyperlink and assigns it to this text run.
|
||||||
|
* If the text run has already a hyperlink assigned, return it instead
|
||||||
|
*
|
||||||
|
* @return the associated hyperlink
|
||||||
|
*
|
||||||
|
* @since POI 3.14-Beta2
|
||||||
|
*/
|
||||||
|
Hyperlink<?,?> createHyperlink();
|
||||||
}
|
}
|
||||||
|
@ -118,6 +118,16 @@ public interface TextShape<
|
|||||||
OTHER
|
OTHER
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the text contained in this text frame, which has been made safe
|
||||||
|
* for printing and other use.
|
||||||
|
*
|
||||||
|
* @return the text string for this textbox.
|
||||||
|
*
|
||||||
|
* @since POI 3.14-Beta2
|
||||||
|
*/
|
||||||
|
String getText();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets (overwrites) the current text.
|
* Sets (overwrites) the current text.
|
||||||
* Uses the properties of the first paragraph / textrun.
|
* Uses the properties of the first paragraph / textrun.
|
||||||
@ -129,6 +139,18 @@ public interface TextShape<
|
|||||||
* @return the last text run of the - potential split - text
|
* @return the last text run of the - potential split - text
|
||||||
*/
|
*/
|
||||||
TextRun setText(String text);
|
TextRun setText(String text);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the supplied text onto the end of the TextParagraphs,
|
||||||
|
* creating a new RichTextRun for it to sit in.
|
||||||
|
*
|
||||||
|
* @param text the text string to be appended.
|
||||||
|
* @param newParagraph if true, a new paragraph will be added,
|
||||||
|
* which will contain the added text
|
||||||
|
*
|
||||||
|
* @since POI 3.14-Beta1
|
||||||
|
*/
|
||||||
|
TextRun appendText(String text, boolean newParagraph);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the TextParagraphs for this text box
|
* @return the TextParagraphs for this text box
|
||||||
|
@ -16,20 +16,23 @@
|
|||||||
==================================================================== */
|
==================================================================== */
|
||||||
package org.apache.poi.xslf.usermodel;
|
package org.apache.poi.xslf.usermodel;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
import org.apache.poi.openxml4j.opc.PackagePart;
|
||||||
|
import org.apache.poi.openxml4j.opc.PackagePartName;
|
||||||
import org.apache.poi.openxml4j.opc.PackageRelationship;
|
import org.apache.poi.openxml4j.opc.PackageRelationship;
|
||||||
import org.apache.poi.openxml4j.opc.TargetMode;
|
import org.apache.poi.openxml4j.opc.TargetMode;
|
||||||
import org.apache.poi.sl.usermodel.Hyperlink;
|
import org.apache.poi.sl.usermodel.Hyperlink;
|
||||||
|
import org.apache.poi.sl.usermodel.Slide;
|
||||||
import org.apache.poi.util.Internal;
|
import org.apache.poi.util.Internal;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTHyperlink;
|
import org.openxmlformats.schemas.drawingml.x2006.main.CTHyperlink;
|
||||||
|
|
||||||
import java.net.URI;
|
public class XSLFHyperlink implements Hyperlink<XSLFShape,XSLFTextParagraph> {
|
||||||
|
final XSLFSheet _sheet;
|
||||||
public class XSLFHyperlink implements Hyperlink {
|
|
||||||
final XSLFTextRun _r;
|
|
||||||
final CTHyperlink _link;
|
final CTHyperlink _link;
|
||||||
|
|
||||||
XSLFHyperlink(CTHyperlink link, XSLFTextRun r){
|
XSLFHyperlink(CTHyperlink link, XSLFSheet sheet){
|
||||||
_r = r;
|
_sheet = sheet;
|
||||||
_link = link;
|
_link = link;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,24 +42,27 @@ public class XSLFHyperlink implements Hyperlink {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setAddress(String address){
|
public void setAddress(String address) {
|
||||||
XSLFSheet sheet = _r.getParentParagraph().getParentShape().getSheet();
|
linkToUrl(address);
|
||||||
PackageRelationship rel =
|
|
||||||
sheet.getPackagePart().
|
|
||||||
addExternalRelationship(address, XSLFRelation.HYPERLINK.getRelation());
|
|
||||||
_link.setId(rel.getId());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getAddress() {
|
public String getAddress() {
|
||||||
return getTargetURI().toASCIIString();
|
if (!_link.isSetId()) {
|
||||||
|
return _link.getAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
String id = _link.getId();
|
||||||
|
URI targetURI = _sheet.getPackagePart().getRelationship(id).getTargetURI();
|
||||||
|
|
||||||
|
return targetURI.toASCIIString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getLabel() {
|
public String getLabel() {
|
||||||
return _link.getTooltip();
|
return _link.getTooltip();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setLabel(String label) {
|
public void setLabel(String label) {
|
||||||
_link.setTooltip(label);
|
_link.setTooltip(label);
|
||||||
@ -64,28 +70,88 @@ public class XSLFHyperlink implements Hyperlink {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getType() {
|
public int getType() {
|
||||||
// TODO: currently this just returns nonsense
|
String action = _link.getAction();
|
||||||
if ("ppaction://hlinksldjump".equals(_link.getAction())) {
|
if (action == null) {
|
||||||
|
action = "";
|
||||||
|
}
|
||||||
|
if (action.equals("ppaction://hlinksldjump") || action.startsWith("ppaction://hlinkshowjump")) {
|
||||||
return LINK_DOCUMENT;
|
return LINK_DOCUMENT;
|
||||||
}
|
}
|
||||||
return LINK_URL;
|
|
||||||
|
String address = getAddress();
|
||||||
|
if (address == null) {
|
||||||
|
address = "";
|
||||||
|
}
|
||||||
|
if (address.startsWith("mailto:")) {
|
||||||
|
return LINK_EMAIL;
|
||||||
|
} else {
|
||||||
|
return LINK_URL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAddress(XSLFSlide slide){
|
@Override
|
||||||
XSLFSheet sheet = _r.getParentParagraph().getParentShape().getSheet();
|
public void linkToEmail(String emailAddress) {
|
||||||
|
linkToExternal("mailto:"+emailAddress);
|
||||||
|
setLabel(emailAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void linkToUrl(String url) {
|
||||||
|
linkToExternal(url);
|
||||||
|
setLabel(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void linkToExternal(String url) {
|
||||||
|
PackagePart thisPP = _sheet.getPackagePart();
|
||||||
|
if (_link.isSetId() && !_link.getId().isEmpty()) {
|
||||||
|
thisPP.removeRelationship(_link.getId());
|
||||||
|
}
|
||||||
|
PackageRelationship rel = thisPP.addExternalRelationship(url, XSLFRelation.HYPERLINK.getRelation());
|
||||||
|
_link.setId(rel.getId());
|
||||||
|
if (_link.isSetAction()) {
|
||||||
|
_link.unsetAction();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void linkToSlide(Slide<XSLFShape,XSLFTextParagraph> slide) {
|
||||||
|
PackagePart thisPP = _sheet.getPackagePart();
|
||||||
|
PackagePartName otherPPN = ((XSLFSheet)slide).getPackagePart().getPartName();
|
||||||
|
if (_link.isSetId() && !_link.getId().isEmpty()) {
|
||||||
|
thisPP.removeRelationship(_link.getId());
|
||||||
|
}
|
||||||
PackageRelationship rel =
|
PackageRelationship rel =
|
||||||
sheet.getPackagePart().
|
thisPP.addRelationship(otherPPN, TargetMode.INTERNAL, XSLFRelation.SLIDE.getRelation());
|
||||||
addRelationship(slide.getPackagePart().getPartName(),
|
|
||||||
TargetMode.INTERNAL,
|
|
||||||
XSLFRelation.SLIDE.getRelation());
|
|
||||||
_link.setId(rel.getId());
|
_link.setId(rel.getId());
|
||||||
_link.setAction("ppaction://hlinksldjump");
|
_link.setAction("ppaction://hlinksldjump");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Internal
|
@Override
|
||||||
public URI getTargetURI(){
|
public void linkToNextSlide() {
|
||||||
XSLFSheet sheet = _r.getParentParagraph().getParentShape().getSheet();
|
linkToRelativeSlide("nextslide");
|
||||||
String id = _link.getId();
|
|
||||||
return sheet.getPackagePart().getRelationship(id).getTargetURI();
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
@Override
|
||||||
|
public void linkToPreviousSlide() {
|
||||||
|
linkToRelativeSlide("previousslide");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void linkToFirstSlide() {
|
||||||
|
linkToRelativeSlide("firstslide");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void linkToLastSlide() {
|
||||||
|
linkToRelativeSlide("lastslide");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void linkToRelativeSlide(String jump) {
|
||||||
|
PackagePart thisPP = _sheet.getPackagePart();
|
||||||
|
if (_link.isSetId() && !_link.getId().isEmpty()) {
|
||||||
|
thisPP.removeRelationship(_link.getId());
|
||||||
|
}
|
||||||
|
_link.setId("");
|
||||||
|
_link.setAction("ppaction://hlinkshowjump?jump="+jump);
|
||||||
|
}
|
||||||
|
}
|
@ -34,8 +34,8 @@ import org.apache.poi.sl.usermodel.LineDecoration;
|
|||||||
import org.apache.poi.sl.usermodel.LineDecoration.DecorationShape;
|
import org.apache.poi.sl.usermodel.LineDecoration.DecorationShape;
|
||||||
import org.apache.poi.sl.usermodel.LineDecoration.DecorationSize;
|
import org.apache.poi.sl.usermodel.LineDecoration.DecorationSize;
|
||||||
import org.apache.poi.sl.usermodel.PaintStyle;
|
import org.apache.poi.sl.usermodel.PaintStyle;
|
||||||
import org.apache.poi.sl.usermodel.Placeholder;
|
|
||||||
import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
|
import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
|
||||||
|
import org.apache.poi.sl.usermodel.Placeholder;
|
||||||
import org.apache.poi.sl.usermodel.ShapeType;
|
import org.apache.poi.sl.usermodel.ShapeType;
|
||||||
import org.apache.poi.sl.usermodel.SimpleShape;
|
import org.apache.poi.sl.usermodel.SimpleShape;
|
||||||
import org.apache.poi.sl.usermodel.StrokeStyle;
|
import org.apache.poi.sl.usermodel.StrokeStyle;
|
||||||
@ -53,6 +53,7 @@ import org.openxmlformats.schemas.drawingml.x2006.main.CTGeomGuide;
|
|||||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTLineEndProperties;
|
import org.openxmlformats.schemas.drawingml.x2006.main.CTLineEndProperties;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTLineProperties;
|
import org.openxmlformats.schemas.drawingml.x2006.main.CTLineProperties;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTLineStyleList;
|
import org.openxmlformats.schemas.drawingml.x2006.main.CTLineStyleList;
|
||||||
|
import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTOuterShadowEffect;
|
import org.openxmlformats.schemas.drawingml.x2006.main.CTOuterShadowEffect;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D;
|
import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D;
|
import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D;
|
||||||
@ -923,4 +924,23 @@ public abstract class XSLFSimpleShape extends XSLFShape
|
|||||||
public void setPlaceholder(Placeholder placeholder) {
|
public void setPlaceholder(Placeholder placeholder) {
|
||||||
super.setPlaceholder(placeholder);
|
super.setPlaceholder(placeholder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XSLFHyperlink getHyperlink() {
|
||||||
|
CTNonVisualDrawingProps cNvPr = getCNvPr();
|
||||||
|
if (!cNvPr.isSetHlinkClick()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return new XSLFHyperlink(cNvPr.getHlinkClick(), getSheet());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XSLFHyperlink createHyperlink() {
|
||||||
|
XSLFHyperlink hl = getHyperlink();
|
||||||
|
if (hl == null) {
|
||||||
|
CTNonVisualDrawingProps cNvPr = getCNvPr();
|
||||||
|
hl = new XSLFHyperlink(cNvPr.addNewHlinkClick(), getSheet());
|
||||||
|
}
|
||||||
|
return hl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -994,4 +994,26 @@ public class XSLFTextParagraph implements TextParagraph<XSLFShape,XSLFTextParagr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method for appending text and keeping paragraph and character properties.
|
||||||
|
* The character properties are moved to the end paragraph marker
|
||||||
|
*/
|
||||||
|
/* package */ void clearButKeepProperties() {
|
||||||
|
CTTextParagraph thisP = getXmlObject();
|
||||||
|
for (int i=thisP.sizeOfBrArray(); i>0; i--) {
|
||||||
|
thisP.removeBr(i-1);
|
||||||
|
}
|
||||||
|
for (int i=thisP.sizeOfFldArray(); i>0; i--) {
|
||||||
|
thisP.removeFld(i-1);
|
||||||
|
}
|
||||||
|
if (!_runs.isEmpty()) {
|
||||||
|
int size = _runs.size();
|
||||||
|
thisP.setEndParaRPr(_runs.get(size-1).getRPr());
|
||||||
|
for (int i=size; i>0; i--) {
|
||||||
|
thisP.removeR(i-1);
|
||||||
|
}
|
||||||
|
_runs.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -444,17 +444,19 @@ public class XSLFTextRun implements TextRun {
|
|||||||
return "[" + getClass() + "]" + getRawText();
|
return "[" + getClass() + "]" + getRawText();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public XSLFHyperlink createHyperlink(){
|
public XSLFHyperlink createHyperlink(){
|
||||||
XSLFHyperlink link = new XSLFHyperlink(_r.getRPr().addNewHlinkClick(), this);
|
XSLFHyperlink hl = getHyperlink();
|
||||||
return link;
|
if (hl == null) {
|
||||||
|
hl = new XSLFHyperlink(_r.getRPr().addNewHlinkClick(), _p.getParentShape().getSheet());
|
||||||
|
}
|
||||||
|
return hl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public XSLFHyperlink getHyperlink(){
|
public XSLFHyperlink getHyperlink(){
|
||||||
if(!_r.getRPr().isSetHlinkClick()) return null;
|
if(!_r.getRPr().isSetHlinkClick()) return null;
|
||||||
|
return new XSLFHyperlink(_r.getRPr().getHlinkClick(), _p.getParentShape().getSheet());
|
||||||
|
|
||||||
return new XSLFHyperlink(_r.getRPr().getHlinkClick(), this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean fetchCharacterProperty(CharacterPropertyFetcher<?> fetcher){
|
private boolean fetchCharacterProperty(CharacterPropertyFetcher<?> fetcher){
|
||||||
|
@ -71,10 +71,7 @@ public abstract class XSLFTextShape extends XSLFSimpleShape
|
|||||||
return getTextParagraphs().iterator();
|
return getTextParagraphs().iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
*
|
|
||||||
* @return text contained within this shape or empty string
|
|
||||||
*/
|
|
||||||
public String getText() {
|
public String getText() {
|
||||||
StringBuilder out = new StringBuilder();
|
StringBuilder out = new StringBuilder();
|
||||||
for (XSLFTextParagraph p : _paragraphs) {
|
for (XSLFTextParagraph p : _paragraphs) {
|
||||||
@ -95,50 +92,76 @@ public abstract class XSLFTextShape extends XSLFSimpleShape
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public XSLFTextRun setText(String text) {
|
public XSLFTextRun setText(String text) {
|
||||||
// copy properties from first paragraph / textrun
|
// calling clearText or setting to a new Array leads to a XmlValueDisconnectedException
|
||||||
|
if (!_paragraphs.isEmpty()) {
|
||||||
|
CTTextBody txBody = getTextBody(false);
|
||||||
|
int cntPs = txBody.sizeOfPArray();
|
||||||
|
for (int i = cntPs; i > 1; i--) {
|
||||||
|
txBody.removeP(i-1);
|
||||||
|
_paragraphs.remove(i-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
_paragraphs.get(0).clearButKeepProperties();
|
||||||
|
}
|
||||||
|
|
||||||
|
return appendText(text, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XSLFTextRun appendText(String text, boolean newParagraph) {
|
||||||
|
if (text == null) return null;
|
||||||
|
|
||||||
|
// copy properties from last paragraph / textrun or paragraph end marker
|
||||||
CTTextParagraphProperties pPr = null;
|
CTTextParagraphProperties pPr = null;
|
||||||
CTTextCharacterProperties rPr = null;
|
CTTextCharacterProperties rPr = null;
|
||||||
if (!_paragraphs.isEmpty()) {
|
|
||||||
XSLFTextParagraph p0 = _paragraphs.get(0);
|
boolean firstPara;
|
||||||
pPr = p0.getXmlObject().getPPr();
|
XSLFTextParagraph para;
|
||||||
if (!p0.getTextRuns().isEmpty()) {
|
if (_paragraphs.isEmpty()) {
|
||||||
XSLFTextRun r0 = p0.getTextRuns().get(0);
|
firstPara = false;
|
||||||
|
para = null;
|
||||||
|
} else {
|
||||||
|
firstPara = !newParagraph;
|
||||||
|
para = _paragraphs.get(_paragraphs.size()-1);
|
||||||
|
CTTextParagraph ctp = para.getXmlObject();
|
||||||
|
pPr = ctp.getPPr();
|
||||||
|
List<XSLFTextRun> runs = para.getTextRuns();
|
||||||
|
if (!runs.isEmpty()) {
|
||||||
|
XSLFTextRun r0 = runs.get(runs.size()-1);
|
||||||
rPr = r0.getXmlObject().getRPr();
|
rPr = r0.getXmlObject().getRPr();
|
||||||
|
} else if (ctp.isSetEndParaRPr()) {
|
||||||
|
rPr = ctp.getEndParaRPr();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// can't call clearText otherwise we receive a XmlValueDisconnectedException
|
|
||||||
_paragraphs.clear();
|
|
||||||
CTTextBody txBody = getTextBody(true);
|
|
||||||
int cntPs = txBody.sizeOfPArray();
|
|
||||||
|
|
||||||
// split text by paragraph and new line char
|
XSLFTextRun run = null;
|
||||||
XSLFTextRun r = null;
|
for (String lineTxt : text.split("\\r\\n?|\\n")) {
|
||||||
for (String paraText : text.split("\\r\\n?|\\n")) {
|
if (!firstPara) {
|
||||||
XSLFTextParagraph para = addNewTextParagraph();
|
if (para != null && para.getXmlObject().isSetEndParaRPr()) {
|
||||||
if (pPr != null) {
|
para.getXmlObject().unsetEndParaRPr();
|
||||||
para.getXmlObject().setPPr(pPr);
|
}
|
||||||
|
para = addNewTextParagraph();
|
||||||
|
if (pPr != null) {
|
||||||
|
para.getXmlObject().setPPr(pPr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
boolean first = true;
|
boolean firstRun = true;
|
||||||
for (String runText : paraText.split("[\u000b]")) {
|
for (String runText : lineTxt.split("[\u000b]")) {
|
||||||
if (!first) {
|
if (!firstRun) {
|
||||||
para.addLineBreak();
|
para.addLineBreak();
|
||||||
}
|
}
|
||||||
r = para.addNewTextRun();
|
run = para.addNewTextRun();
|
||||||
r.setText(runText);
|
run.setText(runText);
|
||||||
if (rPr != null) {
|
if (rPr != null) {
|
||||||
r.getXmlObject().setRPr(rPr);
|
run.getXmlObject().setRPr(rPr);
|
||||||
}
|
}
|
||||||
first = false;
|
firstRun = false;
|
||||||
}
|
}
|
||||||
|
firstPara = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// simply setting a new pArray leads to XmlValueDisconnectedException
|
assert(run != null);
|
||||||
for (int i = cntPs-1; i >= 0; i--) {
|
return run;
|
||||||
txBody.removeP(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -19,19 +19,17 @@ package org.apache.poi.xslf.usermodel;
|
|||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
|
||||||
|
import java.awt.geom.Rectangle2D;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URI;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
|
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
|
||||||
import org.apache.poi.openxml4j.opc.PackageRelationship;
|
import org.apache.poi.openxml4j.opc.PackageRelationship;
|
||||||
import org.apache.poi.openxml4j.opc.TargetMode;
|
import org.apache.poi.openxml4j.opc.TargetMode;
|
||||||
|
import org.apache.poi.sl.usermodel.Hyperlink;
|
||||||
import org.apache.poi.xslf.XSLFTestDataSamples;
|
import org.apache.poi.xslf.XSLFTestDataSamples;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Yegor Kozlov
|
|
||||||
*/
|
|
||||||
public class TestXSLFHyperlink {
|
public class TestXSLFHyperlink {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -45,19 +43,19 @@ public class TestXSLFHyperlink {
|
|||||||
assertEquals("Web Page", cell1.getText());
|
assertEquals("Web Page", cell1.getText());
|
||||||
XSLFHyperlink link1 = cell1.getTextParagraphs().get(0).getTextRuns().get(0).getHyperlink();
|
XSLFHyperlink link1 = cell1.getTextParagraphs().get(0).getTextRuns().get(0).getHyperlink();
|
||||||
assertNotNull(link1);
|
assertNotNull(link1);
|
||||||
assertEquals(URI.create("http://poi.apache.org/"), link1.getTargetURI());
|
assertEquals("http://poi.apache.org/", link1.getAddress());
|
||||||
|
|
||||||
XSLFTableCell cell2 = tbl.getRows().get(2).getCells().get(0);
|
XSLFTableCell cell2 = tbl.getRows().get(2).getCells().get(0);
|
||||||
assertEquals("Place in this document", cell2.getText());
|
assertEquals("Place in this document", cell2.getText());
|
||||||
XSLFHyperlink link2 = cell2.getTextParagraphs().get(0).getTextRuns().get(0).getHyperlink();
|
XSLFHyperlink link2 = cell2.getTextParagraphs().get(0).getTextRuns().get(0).getHyperlink();
|
||||||
assertNotNull(link2);
|
assertNotNull(link2);
|
||||||
assertEquals(URI.create("/ppt/slides/slide2.xml"), link2.getTargetURI());
|
assertEquals("/ppt/slides/slide2.xml", link2.getAddress());
|
||||||
|
|
||||||
XSLFTableCell cell3 = tbl.getRows().get(3).getCells().get(0);
|
XSLFTableCell cell3 = tbl.getRows().get(3).getCells().get(0);
|
||||||
assertEquals("Email", cell3.getText());
|
assertEquals("Email", cell3.getText());
|
||||||
XSLFHyperlink link3 = cell3.getTextParagraphs().get(0).getTextRuns().get(0).getHyperlink();
|
XSLFHyperlink link3 = cell3.getTextParagraphs().get(0).getTextRuns().get(0).getHyperlink();
|
||||||
assertNotNull(link3);
|
assertNotNull(link3);
|
||||||
assertEquals(URI.create("mailto:dev@poi.apache.org?subject=Hi%20There"), link3.getTargetURI());
|
assertEquals("mailto:dev@poi.apache.org?subject=Hi%20There", link3.getAddress());
|
||||||
|
|
||||||
ppt.close();
|
ppt.close();
|
||||||
}
|
}
|
||||||
@ -75,7 +73,7 @@ public class TestXSLFHyperlink {
|
|||||||
r1.setText("Web Page");
|
r1.setText("Web Page");
|
||||||
XSLFHyperlink link1 = r1.createHyperlink();
|
XSLFHyperlink link1 = r1.createHyperlink();
|
||||||
link1.setAddress("http://poi.apache.org/");
|
link1.setAddress("http://poi.apache.org/");
|
||||||
assertEquals(URI.create("http://poi.apache.org/"), link1.getTargetURI());
|
assertEquals("http://poi.apache.org/", link1.getAddress());
|
||||||
assertEquals(numRel + 1, slide1.getPackagePart().getRelationships().size());
|
assertEquals(numRel + 1, slide1.getPackagePart().getRelationships().size());
|
||||||
|
|
||||||
String id1 = link1.getXmlObject().getId();
|
String id1 = link1.getXmlObject().getId();
|
||||||
@ -90,8 +88,8 @@ public class TestXSLFHyperlink {
|
|||||||
XSLFTextRun r2 = sh2.addNewTextParagraph().addNewTextRun();
|
XSLFTextRun r2 = sh2.addNewTextParagraph().addNewTextRun();
|
||||||
r2.setText("Place in this document");
|
r2.setText("Place in this document");
|
||||||
XSLFHyperlink link2 = r2.createHyperlink();
|
XSLFHyperlink link2 = r2.createHyperlink();
|
||||||
link2.setAddress(slide2);
|
link2.linkToSlide(slide2);
|
||||||
assertEquals(URI.create("/ppt/slides/slide2.xml"), link2.getTargetURI());
|
assertEquals("/ppt/slides/slide2.xml", link2.getAddress());
|
||||||
assertEquals(numRel + 2, slide1.getPackagePart().getRelationships().size());
|
assertEquals(numRel + 2, slide1.getPackagePart().getRelationships().size());
|
||||||
|
|
||||||
String id2 = link2.getXmlObject().getId();
|
String id2 = link2.getXmlObject().getId();
|
||||||
@ -104,4 +102,76 @@ public class TestXSLFHyperlink {
|
|||||||
|
|
||||||
ppt.close();
|
ppt.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void bug47291() throws IOException {
|
||||||
|
Rectangle2D anchor = new Rectangle2D.Double(100,100,100,100);
|
||||||
|
XMLSlideShow ppt1 = new XMLSlideShow();
|
||||||
|
XSLFSlide slide1 = ppt1.createSlide();
|
||||||
|
XSLFTextBox tb1 = slide1.createTextBox();
|
||||||
|
tb1.setAnchor(anchor);
|
||||||
|
XSLFTextRun r1 = tb1.setText("page1");
|
||||||
|
XSLFHyperlink hl1 = r1.createHyperlink();
|
||||||
|
hl1.linkToEmail("dev@poi.apache.org");
|
||||||
|
XSLFTextBox tb2 = ppt1.createSlide().createTextBox();
|
||||||
|
tb2.setAnchor(anchor);
|
||||||
|
XSLFTextRun r2 = tb2.setText("page2");
|
||||||
|
XSLFHyperlink hl2 = r2.createHyperlink();
|
||||||
|
hl2.linkToLastSlide();
|
||||||
|
XSLFSlide sl3 = ppt1.createSlide();
|
||||||
|
XSLFTextBox tb3 = sl3.createTextBox();
|
||||||
|
tb3.setAnchor(anchor);
|
||||||
|
tb3.setText("text1 ");
|
||||||
|
XSLFTextRun r3 = tb3.appendText("lin\u000bk", false);
|
||||||
|
tb3.appendText(" text2", false);
|
||||||
|
XSLFHyperlink hl3 = r3.createHyperlink();
|
||||||
|
hl3.linkToSlide(slide1);
|
||||||
|
XSLFTextBox tb4 = ppt1.createSlide().createTextBox();
|
||||||
|
tb4.setAnchor(anchor);
|
||||||
|
XSLFTextRun r4 = tb4.setText("page4");
|
||||||
|
XSLFHyperlink hl4 = r4.createHyperlink();
|
||||||
|
hl4.linkToUrl("http://poi.apache.org");
|
||||||
|
XSLFTextBox tb5 = ppt1.createSlide().createTextBox();
|
||||||
|
tb5.setAnchor(anchor);
|
||||||
|
tb5.setText("page5");
|
||||||
|
XSLFHyperlink hl5 = tb5.createHyperlink();
|
||||||
|
hl5.linkToFirstSlide();
|
||||||
|
|
||||||
|
XMLSlideShow ppt2 = XSLFTestDataSamples.writeOutAndReadBack(ppt1);
|
||||||
|
ppt1.close();
|
||||||
|
|
||||||
|
List<XSLFSlide> slides = ppt2.getSlides();
|
||||||
|
tb1 = (XSLFTextBox)slides.get(0).getShapes().get(0);
|
||||||
|
hl1 = tb1.getTextParagraphs().get(0).getTextRuns().get(0).getHyperlink();
|
||||||
|
assertNotNull(hl1);
|
||||||
|
assertEquals("dev@poi.apache.org", hl1.getLabel());
|
||||||
|
assertEquals(Hyperlink.LINK_EMAIL, hl1.getType());
|
||||||
|
|
||||||
|
tb2 = (XSLFTextBox)slides.get(1).getShapes().get(0);
|
||||||
|
hl2 = tb2.getTextParagraphs().get(0).getTextRuns().get(0).getHyperlink();
|
||||||
|
assertNotNull(hl2);
|
||||||
|
assertEquals("lastslide", hl2.getXmlObject().getAction().split("=")[1]);
|
||||||
|
assertEquals(Hyperlink.LINK_DOCUMENT, hl2.getType());
|
||||||
|
|
||||||
|
tb3 = (XSLFTextBox)slides.get(2).getShapes().get(0);
|
||||||
|
hl3 = tb3.getTextParagraphs().get(0).getTextRuns().get(3).getHyperlink();
|
||||||
|
assertNotNull(hl3);
|
||||||
|
assertEquals("/ppt/slides/slide1.xml", hl3.getAddress());
|
||||||
|
assertEquals(Hyperlink.LINK_DOCUMENT, hl3.getType());
|
||||||
|
|
||||||
|
tb4 = (XSLFTextBox)slides.get(3).getShapes().get(0);
|
||||||
|
hl4 = tb4.getTextParagraphs().get(0).getTextRuns().get(0).getHyperlink();
|
||||||
|
assertNotNull(hl4);
|
||||||
|
assertEquals("http://poi.apache.org", hl4.getLabel());
|
||||||
|
assertEquals(Hyperlink.LINK_URL, hl4.getType());
|
||||||
|
|
||||||
|
tb5 = (XSLFTextBox)slides.get(4).getShapes().get(0);
|
||||||
|
hl5 = tb5.getHyperlink();
|
||||||
|
assertNotNull(hl5);
|
||||||
|
assertEquals("firstslide", hl5.getXmlObject().getAction().split("=")[1]);
|
||||||
|
assertEquals(Hyperlink.LINK_DOCUMENT, hl5.getType());
|
||||||
|
|
||||||
|
ppt2.close();
|
||||||
|
}
|
||||||
}
|
}
|
@ -160,7 +160,7 @@ public final class OLEShape extends HSLFPictureShape {
|
|||||||
if(_exEmbed == null){
|
if(_exEmbed == null){
|
||||||
HSLFSlideShow ppt = getSheet().getSlideShow();
|
HSLFSlideShow ppt = getSheet().getSlideShow();
|
||||||
|
|
||||||
ExObjList lst = ppt.getDocumentRecord().getExObjList();
|
ExObjList lst = ppt.getDocumentRecord().getExObjList(false);
|
||||||
if(lst == null){
|
if(lst == null){
|
||||||
logger.log(POILogger.WARN, "ExObjList not found");
|
logger.log(POILogger.WARN, "ExObjList not found");
|
||||||
return null;
|
return null;
|
||||||
|
@ -46,22 +46,33 @@ public final class Document extends PositionDependentRecordContainer
|
|||||||
* Returns the DocumentAtom of this Document
|
* Returns the DocumentAtom of this Document
|
||||||
*/
|
*/
|
||||||
public DocumentAtom getDocumentAtom() { return documentAtom; }
|
public DocumentAtom getDocumentAtom() { return documentAtom; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the Environment of this Notes, which lots of
|
* Returns the Environment of this Notes, which lots of
|
||||||
* settings for the document in it
|
* settings for the document in it
|
||||||
*/
|
*/
|
||||||
public Environment getEnvironment() { return environment; }
|
public Environment getEnvironment() { return environment; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the PPDrawingGroup, which holds an Escher Structure
|
* Returns the PPDrawingGroup, which holds an Escher Structure
|
||||||
* that contains information on pictures in the slides.
|
* that contains information on pictures in the slides.
|
||||||
*/
|
*/
|
||||||
public PPDrawingGroup getPPDrawingGroup() { return ppDrawing; }
|
public PPDrawingGroup getPPDrawingGroup() { return ppDrawing; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the ExObjList, which holds the references to
|
* Returns the ExObjList, which holds the references to
|
||||||
* external objects used in the slides. This may be null, if
|
* external objects used in the slides. This may be null, if
|
||||||
* there are no external references.
|
* there are no external references.
|
||||||
|
*
|
||||||
|
* @param create if true, create an ExObjList if it doesn't exist
|
||||||
*/
|
*/
|
||||||
public ExObjList getExObjList() { return exObjList; }
|
public ExObjList getExObjList(boolean create) {
|
||||||
|
if (exObjList == null && create) {
|
||||||
|
exObjList = new ExObjList();
|
||||||
|
addChildAfter(exObjList, getDocumentAtom());
|
||||||
|
}
|
||||||
|
return exObjList;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all the SlideListWithTexts that are defined for
|
* Returns all the SlideListWithTexts that are defined for
|
||||||
|
@ -67,9 +67,9 @@ public class ExHyperlink extends RecordContainer {
|
|||||||
linkDetailsB.setText(url);
|
linkDetailsB.setText(url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public void setLinkURL(String url, int options) {
|
|
||||||
|
public void setLinkOptions(int options) {
|
||||||
if(linkDetailsB != null) {
|
if(linkDetailsB != null) {
|
||||||
linkDetailsB.setText(url);
|
|
||||||
linkDetailsB.setOptions(options);
|
linkDetailsB.setOptions(options);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -79,7 +79,7 @@ public class ExHyperlink extends RecordContainer {
|
|||||||
linkDetailsA.setText(title);
|
linkDetailsA.setText(title);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the link details (field A)
|
* Get the link details (field A)
|
||||||
*/
|
*/
|
||||||
|
@ -23,6 +23,7 @@ import java.util.List;
|
|||||||
import java.util.ListIterator;
|
import java.util.ListIterator;
|
||||||
|
|
||||||
import org.apache.poi.hslf.record.ExHyperlink;
|
import org.apache.poi.hslf.record.ExHyperlink;
|
||||||
|
import org.apache.poi.hslf.record.ExHyperlinkAtom;
|
||||||
import org.apache.poi.hslf.record.ExObjList;
|
import org.apache.poi.hslf.record.ExObjList;
|
||||||
import org.apache.poi.hslf.record.HSLFEscherClientDataRecord;
|
import org.apache.poi.hslf.record.HSLFEscherClientDataRecord;
|
||||||
import org.apache.poi.hslf.record.InteractiveInfo;
|
import org.apache.poi.hslf.record.InteractiveInfo;
|
||||||
@ -30,24 +31,95 @@ import org.apache.poi.hslf.record.InteractiveInfoAtom;
|
|||||||
import org.apache.poi.hslf.record.Record;
|
import org.apache.poi.hslf.record.Record;
|
||||||
import org.apache.poi.hslf.record.TxInteractiveInfoAtom;
|
import org.apache.poi.hslf.record.TxInteractiveInfoAtom;
|
||||||
import org.apache.poi.sl.usermodel.Hyperlink;
|
import org.apache.poi.sl.usermodel.Hyperlink;
|
||||||
|
import org.apache.poi.sl.usermodel.Slide;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a hyperlink in a PowerPoint document
|
* Represents a hyperlink in a PowerPoint document
|
||||||
*/
|
*/
|
||||||
public final class HSLFHyperlink implements Hyperlink {
|
public final class HSLFHyperlink implements Hyperlink<HSLFShape,HSLFTextParagraph> {
|
||||||
public static final byte LINK_NEXTSLIDE = InteractiveInfoAtom.LINK_NextSlide;
|
private final ExHyperlink exHyper;
|
||||||
public static final byte LINK_PREVIOUSSLIDE = InteractiveInfoAtom.LINK_PreviousSlide;
|
private final InteractiveInfo info;
|
||||||
public static final byte LINK_FIRSTSLIDE = InteractiveInfoAtom.LINK_FirstSlide;
|
private TxInteractiveInfoAtom txinfo;
|
||||||
public static final byte LINK_LASTSLIDE = InteractiveInfoAtom.LINK_LastSlide;
|
|
||||||
public static final byte LINK_SLIDENUMBER = InteractiveInfoAtom.LINK_SlideNumber;
|
|
||||||
public static final byte LINK_URL = InteractiveInfoAtom.LINK_Url;
|
|
||||||
public static final byte LINK_NULL = InteractiveInfoAtom.LINK_NULL;
|
|
||||||
|
|
||||||
private int id=-1;
|
protected HSLFHyperlink(ExHyperlink exHyper, InteractiveInfo info) {
|
||||||
private int type;
|
this.info = info;
|
||||||
private String address;
|
this.exHyper = exHyper;
|
||||||
private String label;
|
}
|
||||||
private int startIndex, endIndex;
|
|
||||||
|
public ExHyperlink getExHyperlink() {
|
||||||
|
return exHyper;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InteractiveInfo getInfo() {
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TxInteractiveInfoAtom getTextRunInfo() {
|
||||||
|
return txinfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setTextRunInfo(TxInteractiveInfoAtom txinfo) {
|
||||||
|
this.txinfo = txinfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new Hyperlink and assign it to a shape
|
||||||
|
* This is only a helper method - use {@link HSLFSimpleShape#createHyperlink()} instead!
|
||||||
|
*
|
||||||
|
* @param shape the shape which receives the hyperlink
|
||||||
|
* @return the new hyperlink
|
||||||
|
*
|
||||||
|
* @see HSLFShape#createHyperlink()
|
||||||
|
*/
|
||||||
|
/* package */ static HSLFHyperlink createHyperlink(HSLFSimpleShape shape) {
|
||||||
|
// TODO: check if a hyperlink already exists
|
||||||
|
ExHyperlink exHyper = new ExHyperlink();
|
||||||
|
int linkId = shape.getSheet().getSlideShow().addToObjListAtom(exHyper);
|
||||||
|
ExHyperlinkAtom obj = exHyper.getExHyperlinkAtom();
|
||||||
|
obj.setNumber(linkId);
|
||||||
|
InteractiveInfo info = new InteractiveInfo();
|
||||||
|
info.getInteractiveInfoAtom().setHyperlinkID(linkId);
|
||||||
|
HSLFEscherClientDataRecord cldata = shape.getClientData(true);
|
||||||
|
cldata.addChild(info);
|
||||||
|
HSLFHyperlink hyper = new HSLFHyperlink(exHyper, info);
|
||||||
|
hyper.linkToNextSlide();
|
||||||
|
shape.setHyperlink(hyper);
|
||||||
|
return hyper;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new Hyperlink for a textrun.
|
||||||
|
* This is only a helper method - use {@link HSLFTextRun#createHyperlink()} instead!
|
||||||
|
*
|
||||||
|
* @param run the run which receives the hyperlink
|
||||||
|
* @return the new hyperlink
|
||||||
|
*
|
||||||
|
* @see HSLFTextRun#createHyperlink()
|
||||||
|
*/
|
||||||
|
/* package */ static HSLFHyperlink createHyperlink(HSLFTextRun run) {
|
||||||
|
// TODO: check if a hyperlink already exists
|
||||||
|
ExHyperlink exHyper = new ExHyperlink();
|
||||||
|
int linkId = run.getTextParagraph().getSheet().getSlideShow().addToObjListAtom(exHyper);
|
||||||
|
ExHyperlinkAtom obj = exHyper.getExHyperlinkAtom();
|
||||||
|
obj.setNumber(linkId);
|
||||||
|
InteractiveInfo info = new InteractiveInfo();
|
||||||
|
info.getInteractiveInfoAtom().setHyperlinkID(linkId);
|
||||||
|
// don't add the hyperlink now to text paragraph records
|
||||||
|
// this will be done, when the paragraph is saved
|
||||||
|
HSLFHyperlink hyper = new HSLFHyperlink(exHyper, info);
|
||||||
|
hyper.linkToNextSlide();
|
||||||
|
|
||||||
|
TxInteractiveInfoAtom txinfo = new TxInteractiveInfoAtom();
|
||||||
|
int startIdx = run.getTextParagraph().getStartIdxOfTextRun(run);
|
||||||
|
int endIdx = startIdx + run.getLength();
|
||||||
|
txinfo.setStartIndex(startIdx);
|
||||||
|
txinfo.setEndIndex(endIdx);
|
||||||
|
hyper.setTextRunInfo(txinfo);
|
||||||
|
|
||||||
|
run.setHyperlink(hyper);
|
||||||
|
return hyper;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the type of the hyperlink action.
|
* Gets the type of the hyperlink action.
|
||||||
@ -58,70 +130,130 @@ public final class HSLFHyperlink implements Hyperlink {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int getType() {
|
public int getType() {
|
||||||
return type;
|
switch (info.getInteractiveInfoAtom().getHyperlinkType()) {
|
||||||
}
|
case InteractiveInfoAtom.LINK_Url:
|
||||||
|
return (exHyper.getLinkURL().startsWith("mailto:")) ? LINK_EMAIL : LINK_URL;
|
||||||
public void setType(int val) {
|
case InteractiveInfoAtom.LINK_NextSlide:
|
||||||
type = val;
|
case InteractiveInfoAtom.LINK_PreviousSlide:
|
||||||
switch(type){
|
case InteractiveInfoAtom.LINK_FirstSlide:
|
||||||
case LINK_NEXTSLIDE:
|
case InteractiveInfoAtom.LINK_LastSlide:
|
||||||
label = "NEXT";
|
case InteractiveInfoAtom.LINK_SlideNumber:
|
||||||
address = "1,-1,NEXT";
|
return LINK_DOCUMENT;
|
||||||
break;
|
case InteractiveInfoAtom.LINK_CustomShow:
|
||||||
case LINK_PREVIOUSSLIDE:
|
case InteractiveInfoAtom.LINK_OtherPresentation:
|
||||||
label = "PREV";
|
case InteractiveInfoAtom.LINK_OtherFile:
|
||||||
address = "1,-1,PREV";
|
return LINK_FILE;
|
||||||
break;
|
default:
|
||||||
case LINK_FIRSTSLIDE:
|
case InteractiveInfoAtom.LINK_NULL:
|
||||||
label = "FIRST";
|
return -1;
|
||||||
address = "1,-1,FIRST";
|
|
||||||
break;
|
|
||||||
case LINK_LASTSLIDE:
|
|
||||||
label = "LAST";
|
|
||||||
address = "1,-1,LAST";
|
|
||||||
break;
|
|
||||||
case LINK_SLIDENUMBER:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
label = "";
|
|
||||||
address = "";
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getAddress() {
|
public void linkToEmail(String emailAddress) {
|
||||||
return address;
|
InteractiveInfoAtom iia = info.getInteractiveInfoAtom();
|
||||||
|
iia.setAction(InteractiveInfoAtom.ACTION_HYPERLINK);
|
||||||
|
iia.setJump(InteractiveInfoAtom.JUMP_NONE);
|
||||||
|
iia.setHyperlinkType(InteractiveInfoAtom.LINK_Url);
|
||||||
|
exHyper.setLinkURL("mailto:"+emailAddress);
|
||||||
|
exHyper.setLinkTitle(emailAddress);
|
||||||
|
exHyper.setLinkOptions(0x10);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAddress(HSLFSlide slide) {
|
@Override
|
||||||
String href = slide._getSheetNumber() + ","+slide.getSlideNumber()+",Slide " + slide.getSlideNumber();
|
public void linkToUrl(String url) {
|
||||||
setAddress(href);;
|
InteractiveInfoAtom iia = info.getInteractiveInfoAtom();
|
||||||
setLabel("Slide " + slide.getSlideNumber());
|
iia.setAction(InteractiveInfoAtom.ACTION_HYPERLINK);
|
||||||
setType(HSLFHyperlink.LINK_SLIDENUMBER);
|
iia.setJump(InteractiveInfoAtom.JUMP_NONE);
|
||||||
|
iia.setHyperlinkType(InteractiveInfoAtom.LINK_Url);
|
||||||
|
exHyper.setLinkURL(url);
|
||||||
|
exHyper.setLinkTitle(url);
|
||||||
|
exHyper.setLinkOptions(0x10);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void linkToSlide(Slide<HSLFShape,HSLFTextParagraph> slide) {
|
||||||
|
assert(slide instanceof HSLFSlide);
|
||||||
|
HSLFSlide sl = (HSLFSlide)slide;
|
||||||
|
int slideNum = slide.getSlideNumber();
|
||||||
|
String alias = "Slide "+slideNum;
|
||||||
|
|
||||||
|
InteractiveInfoAtom iia = info.getInteractiveInfoAtom();
|
||||||
|
iia.setAction(InteractiveInfoAtom.ACTION_HYPERLINK);
|
||||||
|
iia.setJump(InteractiveInfoAtom.JUMP_NONE);
|
||||||
|
iia.setHyperlinkType(InteractiveInfoAtom.LINK_SlideNumber);
|
||||||
|
|
||||||
|
linkToDocument(sl._getSheetNumber(),slideNum,alias,0x30);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void linkToNextSlide() {
|
||||||
|
InteractiveInfoAtom iia = info.getInteractiveInfoAtom();
|
||||||
|
iia.setAction(InteractiveInfoAtom.ACTION_JUMP);
|
||||||
|
iia.setJump(InteractiveInfoAtom.JUMP_NEXTSLIDE);
|
||||||
|
iia.setHyperlinkType(InteractiveInfoAtom.LINK_NextSlide);
|
||||||
|
|
||||||
|
linkToDocument(1,-1,"NEXT",0x10);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void linkToPreviousSlide() {
|
||||||
|
InteractiveInfoAtom iia = info.getInteractiveInfoAtom();
|
||||||
|
iia.setAction(InteractiveInfoAtom.ACTION_JUMP);
|
||||||
|
iia.setJump(InteractiveInfoAtom.JUMP_PREVIOUSSLIDE);
|
||||||
|
iia.setHyperlinkType(InteractiveInfoAtom.LINK_PreviousSlide);
|
||||||
|
|
||||||
|
linkToDocument(1,-1,"PREV",0x10);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void linkToFirstSlide() {
|
||||||
|
InteractiveInfoAtom iia = info.getInteractiveInfoAtom();
|
||||||
|
iia.setAction(InteractiveInfoAtom.ACTION_JUMP);
|
||||||
|
iia.setJump(InteractiveInfoAtom.JUMP_FIRSTSLIDE);
|
||||||
|
iia.setHyperlinkType(InteractiveInfoAtom.LINK_FirstSlide);
|
||||||
|
|
||||||
|
linkToDocument(1,-1,"FIRST",0x10);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void linkToLastSlide() {
|
||||||
|
InteractiveInfoAtom iia = info.getInteractiveInfoAtom();
|
||||||
|
iia.setAction(InteractiveInfoAtom.ACTION_JUMP);
|
||||||
|
iia.setJump(InteractiveInfoAtom.JUMP_LASTSLIDE);
|
||||||
|
iia.setHyperlinkType(InteractiveInfoAtom.LINK_LastSlide);
|
||||||
|
|
||||||
|
linkToDocument(1,-1,"LAST",0x10);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void linkToDocument(int sheetNumber, int slideNumber, String alias, int options) {
|
||||||
|
exHyper.setLinkURL(sheetNumber+","+slideNumber+","+alias);
|
||||||
|
exHyper.setLinkTitle(alias);
|
||||||
|
exHyper.setLinkOptions(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAddress() {
|
||||||
|
return exHyper.getLinkURL();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setAddress(String str) {
|
public void setAddress(String str) {
|
||||||
address = str;
|
exHyper.setLinkURL(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getId() {
|
public int getId() {
|
||||||
return id;
|
return exHyper.getExHyperlinkAtom().getNumber();
|
||||||
}
|
|
||||||
|
|
||||||
public void setId(int id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getLabel() {
|
public String getLabel() {
|
||||||
return label;
|
return exHyper.getLinkTitle();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setLabel(String str) {
|
public void setLabel(String label) {
|
||||||
label = str;
|
exHyper.setLinkTitle(label);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -130,7 +262,7 @@ public final class HSLFHyperlink implements Hyperlink {
|
|||||||
* @return the beginning character position
|
* @return the beginning character position
|
||||||
*/
|
*/
|
||||||
public int getStartIndex() {
|
public int getStartIndex() {
|
||||||
return startIndex;
|
return (txinfo == null) ? -1 : txinfo.getStartIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -139,16 +271,18 @@ public final class HSLFHyperlink implements Hyperlink {
|
|||||||
* @param startIndex the beginning character position
|
* @param startIndex the beginning character position
|
||||||
*/
|
*/
|
||||||
public void setStartIndex(int startIndex) {
|
public void setStartIndex(int startIndex) {
|
||||||
this.startIndex = startIndex;
|
if (txinfo != null) {
|
||||||
|
txinfo.setStartIndex(startIndex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the ending character position
|
* Gets the ending character position
|
||||||
*
|
*
|
||||||
* @return the ending character position
|
* @return the ending character position
|
||||||
*/
|
*/
|
||||||
public int getEndIndex() {
|
public int getEndIndex() {
|
||||||
return endIndex;
|
return (txinfo == null) ? -1 : txinfo.getEndIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -157,9 +291,11 @@ public final class HSLFHyperlink implements Hyperlink {
|
|||||||
* @param endIndex the ending character position
|
* @param endIndex the ending character position
|
||||||
*/
|
*/
|
||||||
public void setEndIndex(int endIndex) {
|
public void setEndIndex(int endIndex) {
|
||||||
this.endIndex = endIndex;
|
if (txinfo != null) {
|
||||||
|
txinfo.setEndIndex(endIndex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find hyperlinks in a text shape
|
* Find hyperlinks in a text shape
|
||||||
*
|
*
|
||||||
@ -177,15 +313,15 @@ public final class HSLFHyperlink implements Hyperlink {
|
|||||||
* @return found hyperlinks
|
* @return found hyperlinks
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("resource")
|
@SuppressWarnings("resource")
|
||||||
public static List<HSLFHyperlink> find(List<HSLFTextParagraph> paragraphs){
|
protected static List<HSLFHyperlink> find(List<HSLFTextParagraph> paragraphs){
|
||||||
List<HSLFHyperlink> lst = new ArrayList<HSLFHyperlink>();
|
List<HSLFHyperlink> lst = new ArrayList<HSLFHyperlink>();
|
||||||
if (paragraphs == null || paragraphs.isEmpty()) return lst;
|
if (paragraphs == null || paragraphs.isEmpty()) return lst;
|
||||||
|
|
||||||
HSLFTextParagraph firstPara = paragraphs.get(0);
|
HSLFTextParagraph firstPara = paragraphs.get(0);
|
||||||
|
|
||||||
HSLFSlideShow ppt = firstPara.getSheet().getSlideShow();
|
HSLFSlideShow ppt = firstPara.getSheet().getSlideShow();
|
||||||
//document-level container which stores info about all links in a presentation
|
//document-level container which stores info about all links in a presentation
|
||||||
ExObjList exobj = ppt.getDocumentRecord().getExObjList();
|
ExObjList exobj = ppt.getDocumentRecord().getExObjList(false);
|
||||||
if (exobj != null) {
|
if (exobj != null) {
|
||||||
Record[] records = firstPara.getRecords();
|
Record[] records = firstPara.getRecords();
|
||||||
find(Arrays.asList(records), exobj, lst);
|
find(Arrays.asList(records), exobj, lst);
|
||||||
@ -201,10 +337,10 @@ public final class HSLFHyperlink implements Hyperlink {
|
|||||||
* @return found hyperlink or <code>null</code>
|
* @return found hyperlink or <code>null</code>
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("resource")
|
@SuppressWarnings("resource")
|
||||||
public static HSLFHyperlink find(HSLFShape shape){
|
protected static HSLFHyperlink find(HSLFShape shape){
|
||||||
HSLFSlideShow ppt = shape.getSheet().getSlideShow();
|
HSLFSlideShow ppt = shape.getSheet().getSlideShow();
|
||||||
//document-level container which stores info about all links in a presentation
|
//document-level container which stores info about all links in a presentation
|
||||||
ExObjList exobj = ppt.getDocumentRecord().getExObjList();
|
ExObjList exobj = ppt.getDocumentRecord().getExObjList(false);
|
||||||
HSLFEscherClientDataRecord cldata = shape.getClientData(false);
|
HSLFEscherClientDataRecord cldata = shape.getClientData(false);
|
||||||
|
|
||||||
if (exobj != null && cldata != null) {
|
if (exobj != null && cldata != null) {
|
||||||
@ -228,16 +364,12 @@ public final class HSLFHyperlink implements Hyperlink {
|
|||||||
InteractiveInfo hldr = (InteractiveInfo)r;
|
InteractiveInfo hldr = (InteractiveInfo)r;
|
||||||
InteractiveInfoAtom info = hldr.getInteractiveInfoAtom();
|
InteractiveInfoAtom info = hldr.getInteractiveInfoAtom();
|
||||||
int id = info.getHyperlinkID();
|
int id = info.getHyperlinkID();
|
||||||
ExHyperlink linkRecord = exobj.get(id);
|
ExHyperlink exHyper = exobj.get(id);
|
||||||
if (linkRecord == null) {
|
if (exHyper == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
HSLFHyperlink link = new HSLFHyperlink();
|
HSLFHyperlink link = new HSLFHyperlink(exHyper, hldr);
|
||||||
link.setId(id);
|
|
||||||
link.setType(info.getAction());
|
|
||||||
link.setLabel(linkRecord.getLinkTitle());
|
|
||||||
link.setAddress(linkRecord.getLinkURL());
|
|
||||||
out.add(link);
|
out.add(link);
|
||||||
|
|
||||||
if (iter.hasNext()) {
|
if (iter.hasNext()) {
|
||||||
@ -246,9 +378,7 @@ public final class HSLFHyperlink implements Hyperlink {
|
|||||||
iter.previous();
|
iter.previous();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
TxInteractiveInfoAtom txinfo = (TxInteractiveInfoAtom)r;
|
link.setTextRunInfo((TxInteractiveInfoAtom)r);
|
||||||
link.setStartIndex(txinfo.getStartIndex());
|
|
||||||
link.setEndIndex(txinfo.getEndIndex());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,6 @@ import org.apache.poi.ddf.EscherChildAnchorRecord;
|
|||||||
import org.apache.poi.ddf.EscherClientAnchorRecord;
|
import org.apache.poi.ddf.EscherClientAnchorRecord;
|
||||||
import org.apache.poi.ddf.EscherColorRef;
|
import org.apache.poi.ddf.EscherColorRef;
|
||||||
import org.apache.poi.ddf.EscherContainerRecord;
|
import org.apache.poi.ddf.EscherContainerRecord;
|
||||||
import org.apache.poi.ddf.EscherOptRecord;
|
|
||||||
import org.apache.poi.ddf.EscherProperties;
|
import org.apache.poi.ddf.EscherProperties;
|
||||||
import org.apache.poi.ddf.EscherProperty;
|
import org.apache.poi.ddf.EscherProperty;
|
||||||
import org.apache.poi.ddf.EscherRecord;
|
import org.apache.poi.ddf.EscherRecord;
|
||||||
@ -60,8 +59,6 @@ import org.apache.poi.util.Units;
|
|||||||
* in points (72 points = 1 inch).
|
* in points (72 points = 1 inch).
|
||||||
* </p>
|
* </p>
|
||||||
* <p>
|
* <p>
|
||||||
*
|
|
||||||
* @author Yegor Kozlov
|
|
||||||
*/
|
*/
|
||||||
public abstract class HSLFShape implements Shape<HSLFShape,HSLFTextParagraph> {
|
public abstract class HSLFShape implements Shape<HSLFShape,HSLFTextParagraph> {
|
||||||
|
|
||||||
@ -89,7 +86,7 @@ public abstract class HSLFShape implements Shape<HSLFShape,HSLFTextParagraph> {
|
|||||||
* Fill
|
* Fill
|
||||||
*/
|
*/
|
||||||
protected HSLFFill _fill;
|
protected HSLFFill _fill;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a Shape object. This constructor is used when an existing Shape is read from from a PowerPoint document.
|
* Create a Shape object. This constructor is used when an existing Shape is read from from a PowerPoint document.
|
||||||
*
|
*
|
||||||
@ -445,16 +442,6 @@ public abstract class HSLFShape implements Shape<HSLFShape,HSLFTextParagraph> {
|
|||||||
return getFill().getFillStyle();
|
return getFill().getFillStyle();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the hyperlink assigned to this shape
|
|
||||||
*
|
|
||||||
* @return the hyperlink assigned to this shape
|
|
||||||
* or <code>null</code> if not found.
|
|
||||||
*/
|
|
||||||
public HSLFHyperlink getHyperlink(){
|
|
||||||
return HSLFHyperlink.find(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void draw(Graphics2D graphics){
|
public void draw(Graphics2D graphics){
|
||||||
logger.log(POILogger.INFO, "Rendering " + getShapeName());
|
logger.log(POILogger.INFO, "Rendering " + getShapeName());
|
||||||
}
|
}
|
||||||
|
@ -134,6 +134,7 @@ public abstract class HSLFSheet implements HSLFShapeContainer, Sheet<HSLFShape,H
|
|||||||
if (trs == null) return;
|
if (trs == null) return;
|
||||||
for (List<HSLFTextParagraph> ltp : trs) {
|
for (List<HSLFTextParagraph> ltp : trs) {
|
||||||
HSLFTextParagraph.supplySheet(ltp, this);
|
HSLFTextParagraph.supplySheet(ltp, this);
|
||||||
|
HSLFTextParagraph.applyHyperlinks(ltp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,6 +172,14 @@ public abstract class HSLFSheet implements HSLFShapeContainer, Sheet<HSLFShape,H
|
|||||||
EscherContainerRecord sp = (EscherContainerRecord) it.next();
|
EscherContainerRecord sp = (EscherContainerRecord) it.next();
|
||||||
HSLFShape sh = HSLFShapeFactory.createShape(sp, null);
|
HSLFShape sh = HSLFShapeFactory.createShape(sp, null);
|
||||||
sh.setSheet(this);
|
sh.setSheet(this);
|
||||||
|
|
||||||
|
if (sh instanceof HSLFSimpleShape) {
|
||||||
|
HSLFHyperlink link = HSLFHyperlink.find(sh);
|
||||||
|
if (link != null) {
|
||||||
|
((HSLFSimpleShape)sh).setHyperlink(link);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
shapeList.add(sh);
|
shapeList.add(sh);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,8 +32,6 @@ import org.apache.poi.ddf.EscherSimpleProperty;
|
|||||||
import org.apache.poi.ddf.EscherSpRecord;
|
import org.apache.poi.ddf.EscherSpRecord;
|
||||||
import org.apache.poi.hslf.exceptions.HSLFException;
|
import org.apache.poi.hslf.exceptions.HSLFException;
|
||||||
import org.apache.poi.hslf.record.HSLFEscherClientDataRecord;
|
import org.apache.poi.hslf.record.HSLFEscherClientDataRecord;
|
||||||
import org.apache.poi.hslf.record.InteractiveInfo;
|
|
||||||
import org.apache.poi.hslf.record.InteractiveInfoAtom;
|
|
||||||
import org.apache.poi.hslf.record.OEPlaceholderAtom;
|
import org.apache.poi.hslf.record.OEPlaceholderAtom;
|
||||||
import org.apache.poi.hslf.record.Record;
|
import org.apache.poi.hslf.record.Record;
|
||||||
import org.apache.poi.hslf.record.RoundTripHFPlaceholder12;
|
import org.apache.poi.hslf.record.RoundTripHFPlaceholder12;
|
||||||
@ -69,6 +67,11 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape<H
|
|||||||
|
|
||||||
public final static double DEFAULT_LINE_WIDTH = 0.75;
|
public final static double DEFAULT_LINE_WIDTH = 0.75;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hyperlink
|
||||||
|
*/
|
||||||
|
protected HSLFHyperlink _hyperlink;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a SimpleShape object and initialize it from the supplied Record container.
|
* Create a SimpleShape object and initialize it from the supplied Record container.
|
||||||
*
|
*
|
||||||
@ -270,56 +273,6 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape<H
|
|||||||
getFill().setForegroundColor(color);
|
getFill().setForegroundColor(color);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHyperlink(HSLFHyperlink link){
|
|
||||||
if(link.getId() == -1){
|
|
||||||
throw new HSLFException("You must call SlideShow.addHyperlink(Hyperlink link) first");
|
|
||||||
}
|
|
||||||
|
|
||||||
InteractiveInfo info = new InteractiveInfo();
|
|
||||||
InteractiveInfoAtom infoAtom = info.getInteractiveInfoAtom();
|
|
||||||
|
|
||||||
switch(link.getType()){
|
|
||||||
case HSLFHyperlink.LINK_FIRSTSLIDE:
|
|
||||||
infoAtom.setAction(InteractiveInfoAtom.ACTION_JUMP);
|
|
||||||
infoAtom.setJump(InteractiveInfoAtom.JUMP_FIRSTSLIDE);
|
|
||||||
infoAtom.setHyperlinkType(InteractiveInfoAtom.LINK_FirstSlide);
|
|
||||||
break;
|
|
||||||
case HSLFHyperlink.LINK_LASTSLIDE:
|
|
||||||
infoAtom.setAction(InteractiveInfoAtom.ACTION_JUMP);
|
|
||||||
infoAtom.setJump(InteractiveInfoAtom.JUMP_LASTSLIDE);
|
|
||||||
infoAtom.setHyperlinkType(InteractiveInfoAtom.LINK_LastSlide);
|
|
||||||
break;
|
|
||||||
case HSLFHyperlink.LINK_NEXTSLIDE:
|
|
||||||
infoAtom.setAction(InteractiveInfoAtom.ACTION_JUMP);
|
|
||||||
infoAtom.setJump(InteractiveInfoAtom.JUMP_NEXTSLIDE);
|
|
||||||
infoAtom.setHyperlinkType(InteractiveInfoAtom.LINK_NextSlide);
|
|
||||||
break;
|
|
||||||
case HSLFHyperlink.LINK_PREVIOUSSLIDE:
|
|
||||||
infoAtom.setAction(InteractiveInfoAtom.ACTION_JUMP);
|
|
||||||
infoAtom.setJump(InteractiveInfoAtom.JUMP_PREVIOUSSLIDE);
|
|
||||||
infoAtom.setHyperlinkType(InteractiveInfoAtom.LINK_PreviousSlide);
|
|
||||||
break;
|
|
||||||
case HSLFHyperlink.LINK_URL:
|
|
||||||
infoAtom.setAction(InteractiveInfoAtom.ACTION_HYPERLINK);
|
|
||||||
infoAtom.setJump(InteractiveInfoAtom.JUMP_NONE);
|
|
||||||
infoAtom.setHyperlinkType(InteractiveInfoAtom.LINK_Url);
|
|
||||||
break;
|
|
||||||
case HSLFHyperlink.LINK_SLIDENUMBER:
|
|
||||||
infoAtom.setAction(InteractiveInfoAtom.ACTION_HYPERLINK);
|
|
||||||
infoAtom.setJump(InteractiveInfoAtom.JUMP_NONE);
|
|
||||||
infoAtom.setHyperlinkType(InteractiveInfoAtom.LINK_SlideNumber);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
logger.log(POILogger.WARN, "Ignore unknown hyperlink type : "+link.getLabel());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
infoAtom.setHyperlinkID(link.getId());
|
|
||||||
|
|
||||||
HSLFEscherClientDataRecord cldata = getClientData(true);
|
|
||||||
cldata.addChild(info);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Guide getAdjustValue(String name) {
|
public Guide getAdjustValue(String name) {
|
||||||
if (name == null || !name.matches("adj([1-9]|10)?")) {
|
if (name == null || !name.matches("adj([1-9]|10)?")) {
|
||||||
throw new IllegalArgumentException("Adjust value '"+name+"' not supported.");
|
throw new IllegalArgumentException("Adjust value '"+name+"' not supported.");
|
||||||
@ -653,4 +606,26 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape<H
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HSLFHyperlink getHyperlink(){
|
||||||
|
return _hyperlink;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HSLFHyperlink createHyperlink() {
|
||||||
|
if (_hyperlink == null) {
|
||||||
|
_hyperlink = HSLFHyperlink.createHyperlink(this);
|
||||||
|
}
|
||||||
|
return _hyperlink;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the hyperlink - used when the document is parsed
|
||||||
|
*
|
||||||
|
* @param link the hyperlink
|
||||||
|
*/
|
||||||
|
protected void setHyperlink(HSLFHyperlink link) {
|
||||||
|
_hyperlink = link;
|
||||||
|
}
|
||||||
}
|
}
|
@ -1010,28 +1010,6 @@ public final class HSLFSlideShow implements SlideShow<HSLFShape,HSLFTextParagrap
|
|||||||
return objectId;
|
return objectId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a hyperlink to this presentation
|
|
||||||
*
|
|
||||||
* @return 0-based index of the hyperlink
|
|
||||||
*/
|
|
||||||
public int addHyperlink(HSLFHyperlink link) {
|
|
||||||
ExHyperlink ctrl = new ExHyperlink();
|
|
||||||
ExHyperlinkAtom obj = ctrl.getExHyperlinkAtom();
|
|
||||||
if(link.getType() == HSLFHyperlink.LINK_SLIDENUMBER) {
|
|
||||||
ctrl.setLinkURL(link.getAddress(), 0x30);
|
|
||||||
} else {
|
|
||||||
ctrl.setLinkURL(link.getAddress());
|
|
||||||
}
|
|
||||||
ctrl.setLinkTitle(link.getLabel());
|
|
||||||
|
|
||||||
int objectId = addToObjListAtom(ctrl);
|
|
||||||
link.setId(objectId);
|
|
||||||
obj.setNumber(objectId);
|
|
||||||
|
|
||||||
return objectId;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a embedded object to this presentation
|
* Add a embedded object to this presentation
|
||||||
*
|
*
|
||||||
@ -1104,11 +1082,7 @@ public final class HSLFSlideShow implements SlideShow<HSLFShape,HSLFTextParagrap
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected int addToObjListAtom(RecordContainer exObj) {
|
protected int addToObjListAtom(RecordContainer exObj) {
|
||||||
ExObjList lst = (ExObjList) _documentRecord.findFirstOfType(RecordTypes.ExObjList.typeID);
|
ExObjList lst = getDocumentRecord().getExObjList(true);
|
||||||
if (lst == null) {
|
|
||||||
lst = new ExObjList();
|
|
||||||
_documentRecord.addChildAfter(lst, _documentRecord.getDocumentAtom());
|
|
||||||
}
|
|
||||||
ExObjListAtom objAtom = lst.getExObjListAtom();
|
ExObjListAtom objAtom = lst.getExObjListAtom();
|
||||||
// increment the object ID seed
|
// increment the object ID seed
|
||||||
int objectId = (int) objAtom.getObjectIDSeed() + 1;
|
int objectId = (int) objAtom.getObjectIDSeed() + 1;
|
||||||
|
@ -22,7 +22,6 @@ import static org.apache.poi.hslf.record.RecordTypes.OutlineTextRefAtom;
|
|||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -40,6 +39,7 @@ import org.apache.poi.hslf.model.textproperties.TextPropCollection.TextPropType;
|
|||||||
import org.apache.poi.hslf.record.ColorSchemeAtom;
|
import org.apache.poi.hslf.record.ColorSchemeAtom;
|
||||||
import org.apache.poi.hslf.record.EscherTextboxWrapper;
|
import org.apache.poi.hslf.record.EscherTextboxWrapper;
|
||||||
import org.apache.poi.hslf.record.FontCollection;
|
import org.apache.poi.hslf.record.FontCollection;
|
||||||
|
import org.apache.poi.hslf.record.InteractiveInfo;
|
||||||
import org.apache.poi.hslf.record.MasterTextPropAtom;
|
import org.apache.poi.hslf.record.MasterTextPropAtom;
|
||||||
import org.apache.poi.hslf.record.OutlineTextRefAtom;
|
import org.apache.poi.hslf.record.OutlineTextRefAtom;
|
||||||
import org.apache.poi.hslf.record.PPDrawing;
|
import org.apache.poi.hslf.record.PPDrawing;
|
||||||
@ -55,6 +55,7 @@ import org.apache.poi.hslf.record.TextCharsAtom;
|
|||||||
import org.apache.poi.hslf.record.TextHeaderAtom;
|
import org.apache.poi.hslf.record.TextHeaderAtom;
|
||||||
import org.apache.poi.hslf.record.TextRulerAtom;
|
import org.apache.poi.hslf.record.TextRulerAtom;
|
||||||
import org.apache.poi.hslf.record.TextSpecInfoAtom;
|
import org.apache.poi.hslf.record.TextSpecInfoAtom;
|
||||||
|
import org.apache.poi.hslf.record.TxInteractiveInfoAtom;
|
||||||
import org.apache.poi.sl.draw.DrawPaint;
|
import org.apache.poi.sl.draw.DrawPaint;
|
||||||
import org.apache.poi.sl.usermodel.AutoNumberingScheme;
|
import org.apache.poi.sl.usermodel.AutoNumberingScheme;
|
||||||
import org.apache.poi.sl.usermodel.PaintStyle;
|
import org.apache.poi.sl.usermodel.PaintStyle;
|
||||||
@ -102,7 +103,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
|
|||||||
private StyleTextProp9Atom styleTextProp9Atom;
|
private StyleTextProp9Atom styleTextProp9Atom;
|
||||||
|
|
||||||
private boolean _dirty = false;
|
private boolean _dirty = false;
|
||||||
|
|
||||||
private final List<HSLFTextParagraph> parentList;
|
private final List<HSLFTextParagraph> parentList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -162,14 +163,14 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
|
|||||||
* Setting a master style reference
|
* Setting a master style reference
|
||||||
*
|
*
|
||||||
* @param paragraphStyle the master style reference
|
* @param paragraphStyle the master style reference
|
||||||
*
|
*
|
||||||
* @since POI 3.14-Beta1
|
* @since POI 3.14-Beta1
|
||||||
*/
|
*/
|
||||||
@Internal
|
@Internal
|
||||||
/* package */ void setMasterStyleReference(TextPropCollection paragraphStyle) {
|
/* package */ void setMasterStyleReference(TextPropCollection paragraphStyle) {
|
||||||
_paragraphStyle = paragraphStyle;
|
_paragraphStyle = paragraphStyle;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Supply the Sheet we belong to, which might have an assigned SlideShow
|
* Supply the Sheet we belong to, which might have an assigned SlideShow
|
||||||
* Also passes it on to our child RichTextRuns
|
* Also passes it on to our child RichTextRuns
|
||||||
@ -183,9 +184,8 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
|
|||||||
}
|
}
|
||||||
|
|
||||||
assert(sheet.getSlideShow() != null);
|
assert(sheet.getSlideShow() != null);
|
||||||
applyHyperlinks(paragraphs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Supply the Sheet we belong to, which might have an assigned SlideShow
|
* Supply the Sheet we belong to, which might have an assigned SlideShow
|
||||||
* Also passes it on to our child RichTextRuns
|
* Also passes it on to our child RichTextRuns
|
||||||
@ -519,7 +519,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HSLFTextShape getParentShape() {
|
public HSLFTextShape getParentShape() {
|
||||||
return _parentShape;
|
return _parentShape;
|
||||||
@ -603,12 +603,12 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
|
|||||||
if (_runs.isEmpty()) {
|
if (_runs.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
SolidPaint sp = _runs.get(0).getFontColor();
|
SolidPaint sp = _runs.get(0).getFontColor();
|
||||||
if(sp == null) {
|
if(sp == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return DrawPaint.applyColorTransform(sp.getSolidColor());
|
return DrawPaint.applyColorTransform(sp.getSolidColor());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -709,7 +709,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
|
|||||||
* Fetch the value of the given Paragraph related TextProp. Returns null if
|
* Fetch the value of the given Paragraph related TextProp. Returns null if
|
||||||
* that TextProp isn't present. If the TextProp isn't present, the value
|
* that TextProp isn't present. If the TextProp isn't present, the value
|
||||||
* from the appropriate Master Sheet will apply.
|
* from the appropriate Master Sheet will apply.
|
||||||
*
|
*
|
||||||
* The propName can be a comma-separated list, in case multiple equivalent values
|
* The propName can be a comma-separated list, in case multiple equivalent values
|
||||||
* are queried
|
* are queried
|
||||||
*/
|
*/
|
||||||
@ -733,12 +733,12 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
|
|||||||
}
|
}
|
||||||
|
|
||||||
boolean isChar = props.getTextPropType() == TextPropType.character;
|
boolean isChar = props.getTextPropType() == TextPropType.character;
|
||||||
|
|
||||||
for (String pn : propNames) {
|
for (String pn : propNames) {
|
||||||
TextProp prop = master.getStyleAttribute(txtype, paragraph.getIndentLevel(), pn, isChar);
|
TextProp prop = master.getStyleAttribute(txtype, paragraph.getIndentLevel(), pn, isChar);
|
||||||
if (prop != null) return prop;
|
if (prop != null) return prop;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -821,8 +821,21 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
|
|||||||
*/
|
*/
|
||||||
protected static void storeText(List<HSLFTextParagraph> paragraphs) {
|
protected static void storeText(List<HSLFTextParagraph> paragraphs) {
|
||||||
fixLineEndings(paragraphs);
|
fixLineEndings(paragraphs);
|
||||||
|
updateTextAtom(paragraphs);
|
||||||
|
updateStyles(paragraphs);
|
||||||
|
updateHyperlinks(paragraphs);
|
||||||
|
refreshRecords(paragraphs);
|
||||||
|
|
||||||
String rawText = toInternalString(getRawText(paragraphs));
|
for (HSLFTextParagraph p : paragraphs) {
|
||||||
|
p._dirty = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the correct text atom depending on the multibyte usage
|
||||||
|
*/
|
||||||
|
private static void updateTextAtom(List<HSLFTextParagraph> paragraphs) {
|
||||||
|
final String rawText = toInternalString(getRawText(paragraphs));
|
||||||
|
|
||||||
// Will it fit in a 8 bit atom?
|
// Will it fit in a 8 bit atom?
|
||||||
boolean isUnicode = StringUtil.hasMultibyte(rawText);
|
boolean isUnicode = StringUtil.hasMultibyte(rawText);
|
||||||
@ -888,6 +901,16 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update paragraph and character styles - merges them when subsequential styles match
|
||||||
|
*/
|
||||||
|
private static void updateStyles(List<HSLFTextParagraph> paragraphs) {
|
||||||
|
final String rawText = toInternalString(getRawText(paragraphs));
|
||||||
|
TextHeaderAtom headerAtom = paragraphs.get(0)._headerAtom;
|
||||||
|
StyleTextPropAtom styleAtom = findStyleAtomPresent(headerAtom, rawText.length());
|
||||||
|
|
||||||
// Update the text length for its Paragraph and Character stylings
|
// Update the text length for its Paragraph and Character stylings
|
||||||
// * reset the length, to the new string's length
|
// * reset the length, to the new string's length
|
||||||
// * add on +1 if the last block
|
// * add on +1 if the last block
|
||||||
@ -933,7 +956,54 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void updateHyperlinks(List<HSLFTextParagraph> paragraphs) {
|
||||||
|
TextHeaderAtom headerAtom = paragraphs.get(0)._headerAtom;
|
||||||
|
RecordContainer _txtbox = headerAtom.getParentRecord();
|
||||||
|
// remove existing hyperlink records
|
||||||
|
for (Record r : _txtbox.getChildRecords()) {
|
||||||
|
if (r instanceof InteractiveInfo || r instanceof TxInteractiveInfoAtom) {
|
||||||
|
_txtbox.removeChild(r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// now go through all the textruns and check for hyperlinks
|
||||||
|
HSLFHyperlink lastLink = null;
|
||||||
|
for (HSLFTextParagraph para : paragraphs) {
|
||||||
|
for (HSLFTextRun run : para) {
|
||||||
|
HSLFHyperlink thisLink = run.getHyperlink();
|
||||||
|
if (thisLink != null && thisLink == lastLink) {
|
||||||
|
// the hyperlink extends over this text run, increase its length
|
||||||
|
// TODO: the text run might be longer than the hyperlink
|
||||||
|
thisLink.setEndIndex(thisLink.getEndIndex()+run.getLength());
|
||||||
|
} else {
|
||||||
|
if (lastLink != null) {
|
||||||
|
InteractiveInfo info = lastLink.getInfo();
|
||||||
|
TxInteractiveInfoAtom txinfo = lastLink.getTextRunInfo();
|
||||||
|
assert(info != null && txinfo != null);
|
||||||
|
_txtbox.appendChildRecord(info);
|
||||||
|
_txtbox.appendChildRecord(txinfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lastLink = thisLink;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastLink != null) {
|
||||||
|
InteractiveInfo info = lastLink.getInfo();
|
||||||
|
TxInteractiveInfoAtom txinfo = lastLink.getTextRunInfo();
|
||||||
|
assert(info != null && txinfo != null);
|
||||||
|
_txtbox.appendChildRecord(info);
|
||||||
|
_txtbox.appendChildRecord(txinfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes the textbox records back to the document record
|
||||||
|
*/
|
||||||
|
private static void refreshRecords(List<HSLFTextParagraph> paragraphs) {
|
||||||
|
TextHeaderAtom headerAtom = paragraphs.get(0)._headerAtom;
|
||||||
|
RecordContainer _txtbox = headerAtom.getParentRecord();
|
||||||
if (_txtbox instanceof EscherTextboxWrapper) {
|
if (_txtbox instanceof EscherTextboxWrapper) {
|
||||||
try {
|
try {
|
||||||
((EscherTextboxWrapper) _txtbox).writeOut(null);
|
((EscherTextboxWrapper) _txtbox).writeOut(null);
|
||||||
@ -941,10 +1011,6 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
|
|||||||
throw new RuntimeException("failed dummy write", e);
|
throw new RuntimeException("failed dummy write", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (HSLFTextParagraph p : paragraphs) {
|
|
||||||
p._dirty = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1043,7 +1109,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
|
|||||||
}
|
}
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
@ -1266,20 +1332,46 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
|
|||||||
|
|
||||||
protected static void applyHyperlinks(List<HSLFTextParagraph> paragraphs) {
|
protected static void applyHyperlinks(List<HSLFTextParagraph> paragraphs) {
|
||||||
List<HSLFHyperlink> links = HSLFHyperlink.find(paragraphs);
|
List<HSLFHyperlink> links = HSLFHyperlink.find(paragraphs);
|
||||||
|
|
||||||
for (HSLFHyperlink h : links) {
|
for (HSLFHyperlink h : links) {
|
||||||
int csIdx = 0;
|
int csIdx = 0;
|
||||||
for (HSLFTextParagraph p : paragraphs) {
|
for (HSLFTextParagraph p : paragraphs) {
|
||||||
for (HSLFTextRun r : p) {
|
if (csIdx > h.getEndIndex()) break;
|
||||||
if (h.getStartIndex() <= csIdx && csIdx < h.getEndIndex()) {
|
List<HSLFTextRun> runs = p.getTextRuns();
|
||||||
r.setHyperlinkId(h.getId());
|
for (int rlen=0,rIdx=0; rIdx < runs.size(); csIdx+=rlen, rIdx++) {
|
||||||
|
HSLFTextRun run = runs.get(rIdx);
|
||||||
|
rlen = run.getLength();
|
||||||
|
if (csIdx < h.getEndIndex() && h.getStartIndex() < csIdx+rlen) {
|
||||||
|
String rawText = run.getRawText();
|
||||||
|
int startIdx = h.getStartIndex()-csIdx;
|
||||||
|
if (startIdx > 0) {
|
||||||
|
// hyperlink starts within current textrun
|
||||||
|
HSLFTextRun newRun = new HSLFTextRun(p);
|
||||||
|
newRun.setCharacterStyle(run.getCharacterStyle());
|
||||||
|
newRun.setText(rawText.substring(startIdx));
|
||||||
|
run.setText(rawText.substring(0, startIdx));
|
||||||
|
runs.add(rIdx+1, newRun);
|
||||||
|
rlen = startIdx;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int endIdx = Math.min(rlen, h.getEndIndex()-h.getStartIndex());
|
||||||
|
if (endIdx < rlen) {
|
||||||
|
// hyperlink ends before end of current textrun
|
||||||
|
HSLFTextRun newRun = new HSLFTextRun(p);
|
||||||
|
newRun.setCharacterStyle(run.getCharacterStyle());
|
||||||
|
newRun.setText(rawText.substring(0, endIdx));
|
||||||
|
run.setText(rawText.substring(endIdx));
|
||||||
|
runs.add(rIdx, newRun);
|
||||||
|
rlen = endIdx;
|
||||||
|
run = newRun;
|
||||||
|
}
|
||||||
|
run.setHyperlink(h);
|
||||||
}
|
}
|
||||||
csIdx += r.getLength();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static void applyCharacterStyles(List<HSLFTextParagraph> paragraphs, List<TextPropCollection> charStyles) {
|
protected static void applyCharacterStyles(List<HSLFTextParagraph> paragraphs, List<TextPropCollection> charStyles) {
|
||||||
int paraIdx = 0, runIdx = 0;
|
int paraIdx = 0, runIdx = 0;
|
||||||
HSLFTextRun trun;
|
HSLFTextRun trun;
|
||||||
@ -1444,7 +1536,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
|
|||||||
public boolean isDirty() {
|
public boolean isDirty() {
|
||||||
return _dirty;
|
return _dirty;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates the start index of the given text run
|
* Calculates the start index of the given text run
|
||||||
*
|
*
|
||||||
|
@ -27,10 +27,6 @@ import org.apache.poi.hslf.model.textproperties.CharFlagsTextProp;
|
|||||||
import org.apache.poi.hslf.model.textproperties.TextProp;
|
import org.apache.poi.hslf.model.textproperties.TextProp;
|
||||||
import org.apache.poi.hslf.model.textproperties.TextPropCollection;
|
import org.apache.poi.hslf.model.textproperties.TextPropCollection;
|
||||||
import org.apache.poi.hslf.model.textproperties.TextPropCollection.TextPropType;
|
import org.apache.poi.hslf.model.textproperties.TextPropCollection.TextPropType;
|
||||||
import org.apache.poi.hslf.record.ExHyperlink;
|
|
||||||
import org.apache.poi.hslf.record.InteractiveInfo;
|
|
||||||
import org.apache.poi.hslf.record.InteractiveInfoAtom;
|
|
||||||
import org.apache.poi.hslf.record.Record;
|
|
||||||
import org.apache.poi.sl.draw.DrawPaint;
|
import org.apache.poi.sl.draw.DrawPaint;
|
||||||
import org.apache.poi.sl.usermodel.PaintStyle;
|
import org.apache.poi.sl.usermodel.PaintStyle;
|
||||||
import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
|
import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
|
||||||
@ -51,7 +47,7 @@ public final class HSLFTextRun implements TextRun {
|
|||||||
private HSLFTextParagraph parentParagraph;
|
private HSLFTextParagraph parentParagraph;
|
||||||
private String _runText = "";
|
private String _runText = "";
|
||||||
private String _fontFamily;
|
private String _fontFamily;
|
||||||
private int hyperlinkId = -1;
|
private HSLFHyperlink link;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Our paragraph and character style.
|
* Our paragraph and character style.
|
||||||
@ -395,64 +391,27 @@ public final class HSLFTextRun implements TextRun {
|
|||||||
public byte getPitchAndFamily() {
|
public byte getPitchAndFamily() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the associated hyperlink id - currently this is only used while parsing and
|
|
||||||
* can't be used for update a ppt
|
|
||||||
*
|
|
||||||
* @param hyperlinkId the id or -1 to unset it
|
|
||||||
*/
|
|
||||||
public void setHyperlinkId(int hyperlinkId) {
|
|
||||||
this.hyperlinkId = hyperlinkId;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the associated hyperlink id
|
|
||||||
*
|
|
||||||
* @return the hyperlink id
|
|
||||||
*/
|
|
||||||
public int getHyperlinkId() {
|
|
||||||
return hyperlinkId;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the hyperlink - used when parsing the document
|
||||||
|
*
|
||||||
|
* @param link the hyperlink
|
||||||
|
*/
|
||||||
|
protected void setHyperlink(HSLFHyperlink link) {
|
||||||
|
this.link = link;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HSLFHyperlink getHyperlink() {
|
public HSLFHyperlink getHyperlink() {
|
||||||
if (hyperlinkId == -1) {
|
return link;
|
||||||
return null;
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HSLFHyperlink createHyperlink() {
|
||||||
|
if (link == null) {
|
||||||
|
link = HSLFHyperlink.createHyperlink(this);
|
||||||
|
parentParagraph.setDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
ExHyperlink linkRecord = parentParagraph.getSheet().getSlideShow().getDocumentRecord().getExObjList().get(hyperlinkId);
|
|
||||||
if (linkRecord == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
InteractiveInfoAtom info = null;
|
|
||||||
for (Record r : parentParagraph.getRecords()) {
|
|
||||||
if (r instanceof InteractiveInfo) {
|
|
||||||
InteractiveInfo ii = (InteractiveInfo)r;
|
|
||||||
InteractiveInfoAtom iia = ii.getInteractiveInfoAtom();
|
|
||||||
if (iia.getHyperlinkID() == hyperlinkId) {
|
|
||||||
info = iia;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (info == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: check previous/next sibling runs for same hyperlink id and return the whole string length
|
|
||||||
int startIdx = parentParagraph.getStartIdxOfTextRun(this);
|
|
||||||
|
|
||||||
HSLFHyperlink link = new HSLFHyperlink();
|
|
||||||
link.setId(hyperlinkId);
|
|
||||||
link.setType(info.getAction());
|
|
||||||
link.setLabel(linkRecord.getLinkTitle());
|
|
||||||
link.setAddress(linkRecord.getLinkURL());
|
|
||||||
link.setStartIndex(startIdx);
|
|
||||||
link.setEndIndex(startIdx+getLength());
|
|
||||||
|
|
||||||
return link;
|
return link;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,13 +35,10 @@ import org.apache.poi.ddf.EscherTextboxRecord;
|
|||||||
import org.apache.poi.hslf.exceptions.HSLFException;
|
import org.apache.poi.hslf.exceptions.HSLFException;
|
||||||
import org.apache.poi.hslf.model.HSLFMetroShape;
|
import org.apache.poi.hslf.model.HSLFMetroShape;
|
||||||
import org.apache.poi.hslf.record.EscherTextboxWrapper;
|
import org.apache.poi.hslf.record.EscherTextboxWrapper;
|
||||||
import org.apache.poi.hslf.record.InteractiveInfo;
|
|
||||||
import org.apache.poi.hslf.record.InteractiveInfoAtom;
|
|
||||||
import org.apache.poi.hslf.record.OEPlaceholderAtom;
|
import org.apache.poi.hslf.record.OEPlaceholderAtom;
|
||||||
import org.apache.poi.hslf.record.PPDrawing;
|
import org.apache.poi.hslf.record.PPDrawing;
|
||||||
import org.apache.poi.hslf.record.RoundTripHFPlaceholder12;
|
import org.apache.poi.hslf.record.RoundTripHFPlaceholder12;
|
||||||
import org.apache.poi.hslf.record.TextHeaderAtom;
|
import org.apache.poi.hslf.record.TextHeaderAtom;
|
||||||
import org.apache.poi.hslf.record.TxInteractiveInfoAtom;
|
|
||||||
import org.apache.poi.sl.draw.DrawFactory;
|
import org.apache.poi.sl.draw.DrawFactory;
|
||||||
import org.apache.poi.sl.draw.DrawTextShape;
|
import org.apache.poi.sl.draw.DrawTextShape;
|
||||||
import org.apache.poi.sl.usermodel.Insets2D;
|
import org.apache.poi.sl.usermodel.Insets2D;
|
||||||
@ -622,33 +619,6 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
|
|||||||
return getClientDataRecord(RoundTripHFPlaceholder12.typeID);
|
return getClientDataRecord(RoundTripHFPlaceholder12.typeID);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Assigns a hyperlink to this text shape
|
|
||||||
*
|
|
||||||
* @param linkId id of the hyperlink, @see org.apache.poi.hslf.usermodel.SlideShow#addHyperlink(Hyperlink)
|
|
||||||
* @param beginIndex the beginning index, inclusive.
|
|
||||||
* @param endIndex the ending index, exclusive.
|
|
||||||
* @see org.apache.poi.hslf.usermodel.HSLFSlideShow#addHyperlink(HSLFHyperlink)
|
|
||||||
*/
|
|
||||||
public void setHyperlink(int linkId, int beginIndex, int endIndex){
|
|
||||||
//TODO validate beginIndex and endIndex and throw IllegalArgumentException
|
|
||||||
|
|
||||||
InteractiveInfo info = new InteractiveInfo();
|
|
||||||
InteractiveInfoAtom infoAtom = info.getInteractiveInfoAtom();
|
|
||||||
infoAtom.setAction(org.apache.poi.hslf.record.InteractiveInfoAtom.ACTION_HYPERLINK);
|
|
||||||
infoAtom.setHyperlinkType(org.apache.poi.hslf.record.InteractiveInfoAtom.LINK_Url);
|
|
||||||
infoAtom.setHyperlinkID(linkId);
|
|
||||||
|
|
||||||
_txtbox.appendChildRecord(info);
|
|
||||||
|
|
||||||
TxInteractiveInfoAtom txiatom = new TxInteractiveInfoAtom();
|
|
||||||
txiatom.setStartIndex(beginIndex);
|
|
||||||
txiatom.setEndIndex(endIndex);
|
|
||||||
_txtbox.appendChildRecord(txiatom);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isPlaceholder() {
|
public boolean isPlaceholder() {
|
||||||
OEPlaceholderAtom oep = getPlaceholderAtom();
|
OEPlaceholderAtom oep = getPlaceholderAtom();
|
||||||
@ -729,50 +699,38 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
|
|||||||
return HSLFTextParagraph.getRawText(getTextParagraphs());
|
return HSLFTextParagraph.getRawText(getTextParagraphs());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Returns the text contained in this text frame, which has been made safe
|
|
||||||
* for printing and other use.
|
|
||||||
*
|
|
||||||
* @return the text string for this textbox.
|
|
||||||
*/
|
|
||||||
public String getText() {
|
public String getText() {
|
||||||
String rawText = getRawText();
|
String rawText = getRawText();
|
||||||
return HSLFTextParagraph.toExternalString(rawText, getRunType());
|
return HSLFTextParagraph.toExternalString(rawText, getRunType());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HSLFTextRun appendText(String text, boolean newParagraph) {
|
||||||
|
// init paragraphs
|
||||||
|
List<HSLFTextParagraph> paras = getTextParagraphs();
|
||||||
|
HSLFTextRun htr = HSLFTextParagraph.appendText(paras, text, newParagraph);
|
||||||
|
setTextId(getRawText().hashCode());
|
||||||
|
return htr;
|
||||||
|
}
|
||||||
|
|
||||||
// Update methods follow
|
@Override
|
||||||
|
public HSLFTextRun setText(String text) {
|
||||||
|
// init paragraphs
|
||||||
|
List<HSLFTextParagraph> paras = getTextParagraphs();
|
||||||
|
HSLFTextRun htr = HSLFTextParagraph.setText(paras, text);
|
||||||
|
setTextId(getRawText().hashCode());
|
||||||
|
return htr;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds the supplied text onto the end of the TextParagraphs,
|
* Saves the modified paragraphs/textrun to the records.
|
||||||
* creating a new RichTextRun for it to sit in.
|
* Also updates the styles to the correct text length.
|
||||||
*
|
*/
|
||||||
* @param text the text string used by this object.
|
protected void storeText() {
|
||||||
*/
|
List<HSLFTextParagraph> paras = getTextParagraphs();
|
||||||
public HSLFTextRun appendText(String text, boolean newParagraph) {
|
HSLFTextParagraph.storeText(paras);
|
||||||
// init paragraphs
|
}
|
||||||
List<HSLFTextParagraph> paras = getTextParagraphs();
|
|
||||||
return HSLFTextParagraph.appendText(paras, text, newParagraph);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HSLFTextRun setText(String text) {
|
|
||||||
// init paragraphs
|
|
||||||
List<HSLFTextParagraph> paras = getTextParagraphs();
|
|
||||||
HSLFTextRun htr = HSLFTextParagraph.setText(paras, text);
|
|
||||||
setTextId(text.hashCode());
|
|
||||||
return htr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Saves the modified paragraphs/textrun to the records.
|
|
||||||
* Also updates the styles to the correct text length.
|
|
||||||
*/
|
|
||||||
protected void storeText() {
|
|
||||||
List<HSLFTextParagraph> paras = getTextParagraphs();
|
|
||||||
HSLFTextParagraph.storeText(paras);
|
|
||||||
}
|
|
||||||
// Accesser methods follow
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the array of all hyperlinks in this text run
|
* Returns the array of all hyperlinks in this text run
|
||||||
|
@ -22,16 +22,25 @@ import static org.apache.poi.hslf.usermodel.HSLFTextParagraph.toExternalString;
|
|||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
|
||||||
|
import java.awt.geom.Rectangle2D;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.poi.POIDataSamples;
|
import org.apache.poi.POIDataSamples;
|
||||||
import org.apache.poi.hslf.usermodel.*;
|
import org.apache.poi.hslf.HSLFTestDataSamples;
|
||||||
|
import org.apache.poi.hslf.record.InteractiveInfoAtom;
|
||||||
|
import org.apache.poi.hslf.usermodel.HSLFHyperlink;
|
||||||
|
import org.apache.poi.hslf.usermodel.HSLFSlide;
|
||||||
|
import org.apache.poi.hslf.usermodel.HSLFSlideShow;
|
||||||
|
import org.apache.poi.hslf.usermodel.HSLFTextBox;
|
||||||
|
import org.apache.poi.hslf.usermodel.HSLFTextParagraph;
|
||||||
|
import org.apache.poi.hslf.usermodel.HSLFTextRun;
|
||||||
|
import org.apache.poi.sl.usermodel.Hyperlink;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test Hyperlink.
|
* Test Hyperlink.
|
||||||
*
|
|
||||||
* @author Yegor Kozlov
|
|
||||||
*/
|
*/
|
||||||
public final class TestHyperlink {
|
public final class TestHyperlink {
|
||||||
private static POIDataSamples _slTests = POIDataSamples.getSlideShowInstance();
|
private static POIDataSamples _slTests = POIDataSamples.getSlideShowInstance();
|
||||||
@ -42,7 +51,7 @@ public final class TestHyperlink {
|
|||||||
|
|
||||||
HSLFSlide slide = ppt.getSlides().get(0);
|
HSLFSlide slide = ppt.getSlides().get(0);
|
||||||
List<HSLFTextParagraph> para = slide.getTextParagraphs().get(1);
|
List<HSLFTextParagraph> para = slide.getTextParagraphs().get(1);
|
||||||
|
|
||||||
String rawText = toExternalString(getRawText(para), para.get(0).getRunType());
|
String rawText = toExternalString(getRawText(para), para.get(0).getRunType());
|
||||||
String expected =
|
String expected =
|
||||||
"This page has two links:\n"+
|
"This page has two links:\n"+
|
||||||
@ -52,9 +61,8 @@ public final class TestHyperlink {
|
|||||||
"\n"+
|
"\n"+
|
||||||
"In addition, its notes has one link";
|
"In addition, its notes has one link";
|
||||||
assertEquals(expected, rawText);
|
assertEquals(expected, rawText);
|
||||||
|
|
||||||
List<HSLFHyperlink> links = HSLFHyperlink.find(para);
|
List<HSLFHyperlink> links = findHyperlinks(para);
|
||||||
assertNotNull(links);
|
|
||||||
assertEquals(2, links.size());
|
assertEquals(2, links.size());
|
||||||
|
|
||||||
assertEquals("http://jakarta.apache.org/poi/", links.get(0).getLabel());
|
assertEquals("http://jakarta.apache.org/poi/", links.get(0).getLabel());
|
||||||
@ -68,17 +76,97 @@ public final class TestHyperlink {
|
|||||||
slide = ppt.getSlides().get(1);
|
slide = ppt.getSlides().get(1);
|
||||||
para = slide.getTextParagraphs().get(1);
|
para = slide.getTextParagraphs().get(1);
|
||||||
rawText = toExternalString(getRawText(para), para.get(0).getRunType());
|
rawText = toExternalString(getRawText(para), para.get(0).getRunType());
|
||||||
expected =
|
expected =
|
||||||
"I have the one link:\n" +
|
"I have the one link:\n" +
|
||||||
"Jakarta HSSF";
|
"Jakarta HSSF";
|
||||||
assertEquals(expected, rawText);
|
assertEquals(expected, rawText);
|
||||||
|
|
||||||
links = HSLFHyperlink.find(para);
|
links.clear();
|
||||||
|
|
||||||
|
links = findHyperlinks(para);
|
||||||
assertNotNull(links);
|
assertNotNull(links);
|
||||||
assertEquals(1, links.size());
|
assertEquals(1, links.size());
|
||||||
|
|
||||||
assertEquals("Open Jakarta POI HSSF module test ", links.get(0).getLabel());
|
assertEquals("Open Jakarta POI HSSF module test ", links.get(0).getLabel());
|
||||||
assertEquals("http://jakarta.apache.org/poi/hssf/", links.get(0).getAddress());
|
assertEquals("http://jakarta.apache.org/poi/hssf/", links.get(0).getAddress());
|
||||||
assertEquals("Jakarta HSSF", rawText.substring(links.get(0).getStartIndex(), links.get(0).getEndIndex()-1));
|
assertEquals("Jakarta HSSF", rawText.substring(links.get(0).getStartIndex(), links.get(0).getEndIndex()-1));
|
||||||
|
|
||||||
|
ppt.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void bug47291() throws IOException {
|
||||||
|
HSLFSlideShow ppt1 = new HSLFSlideShow();
|
||||||
|
HSLFSlide slide1 = ppt1.createSlide();
|
||||||
|
HSLFTextRun r1 = slide1.createTextBox().setText("page1");
|
||||||
|
HSLFHyperlink hl1 = r1.createHyperlink();
|
||||||
|
hl1.linkToEmail("dev@poi.apache.org");
|
||||||
|
HSLFTextRun r2 = ppt1.createSlide().createTextBox().setText("page2");
|
||||||
|
HSLFHyperlink hl2 = r2.createHyperlink();
|
||||||
|
hl2.linkToLastSlide();
|
||||||
|
HSLFSlide sl1 = ppt1.createSlide();
|
||||||
|
HSLFTextBox tb1 = sl1.createTextBox();
|
||||||
|
tb1.setAnchor(new Rectangle2D.Double(100,100,100,100));
|
||||||
|
tb1.appendText("text1 ", false);
|
||||||
|
HSLFTextRun r3 = tb1.appendText("lin\u000bk", false);
|
||||||
|
tb1.appendText(" text2", false);
|
||||||
|
HSLFHyperlink hl3 = r3.createHyperlink();
|
||||||
|
hl3.linkToSlide(slide1);
|
||||||
|
HSLFTextRun r4 = ppt1.createSlide().createTextBox().setText("page4");
|
||||||
|
HSLFHyperlink hl4 = r4.createHyperlink();
|
||||||
|
hl4.linkToUrl("http://poi.apache.org");
|
||||||
|
HSLFTextBox tb5 = ppt1.createSlide().createTextBox();
|
||||||
|
tb5.setText("page5");
|
||||||
|
HSLFHyperlink hl5 = tb5.createHyperlink();
|
||||||
|
hl5.linkToFirstSlide();
|
||||||
|
|
||||||
|
HSLFSlideShow ppt2 = HSLFTestDataSamples.writeOutAndReadBack(ppt1);
|
||||||
|
ppt1.close();
|
||||||
|
|
||||||
|
List<HSLFSlide> slides = ppt2.getSlides();
|
||||||
|
tb1 = (HSLFTextBox)slides.get(0).getShapes().get(0);
|
||||||
|
hl1 = tb1.getTextParagraphs().get(0).getTextRuns().get(0).getHyperlink();
|
||||||
|
assertNotNull(hl1);
|
||||||
|
assertEquals("dev@poi.apache.org", hl1.getLabel());
|
||||||
|
assertEquals(Hyperlink.LINK_EMAIL, hl1.getType());
|
||||||
|
|
||||||
|
HSLFTextBox tb2 = (HSLFTextBox)slides.get(1).getShapes().get(0);
|
||||||
|
hl2 = tb2.getTextParagraphs().get(0).getTextRuns().get(0).getHyperlink();
|
||||||
|
assertNotNull(hl2);
|
||||||
|
assertEquals(InteractiveInfoAtom.LINK_LastSlide, hl2.getInfo().getInteractiveInfoAtom().getHyperlinkType());
|
||||||
|
assertEquals(Hyperlink.LINK_DOCUMENT, hl2.getType());
|
||||||
|
|
||||||
|
HSLFTextBox tb3 = (HSLFTextBox)slides.get(2).getShapes().get(0);
|
||||||
|
hl3 = tb3.getTextParagraphs().get(0).getTextRuns().get(1).getHyperlink();
|
||||||
|
assertNotNull(hl3);
|
||||||
|
assertEquals(ppt2.getSlides().get(0)._getSheetNumber(), Integer.parseInt(hl3.getAddress().split(",")[0]));
|
||||||
|
assertEquals(Hyperlink.LINK_DOCUMENT, hl3.getType());
|
||||||
|
|
||||||
|
HSLFTextBox tb4 = (HSLFTextBox)slides.get(3).getShapes().get(0);
|
||||||
|
hl4 = tb4.getTextParagraphs().get(0).getTextRuns().get(0).getHyperlink();
|
||||||
|
assertNotNull(hl4);
|
||||||
|
assertEquals("http://poi.apache.org", hl4.getLabel());
|
||||||
|
assertEquals(Hyperlink.LINK_URL, hl4.getType());
|
||||||
|
|
||||||
|
tb5 = (HSLFTextBox)slides.get(4).getShapes().get(0);
|
||||||
|
hl5 = tb5.getHyperlink();
|
||||||
|
assertNotNull(hl5);
|
||||||
|
assertEquals(InteractiveInfoAtom.LINK_FirstSlide, hl5.getInfo().getInteractiveInfoAtom().getHyperlinkType());
|
||||||
|
assertEquals(Hyperlink.LINK_DOCUMENT, hl5.getType());
|
||||||
|
|
||||||
|
ppt2.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<HSLFHyperlink> findHyperlinks(List<HSLFTextParagraph> paras) {
|
||||||
|
List<HSLFHyperlink> links = new ArrayList<HSLFHyperlink>();
|
||||||
|
for (HSLFTextParagraph p : paras) {
|
||||||
|
for (HSLFTextRun r : p) {
|
||||||
|
HSLFHyperlink hl = r.getHyperlink();
|
||||||
|
if (hl != null) {
|
||||||
|
links.add(hl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return links;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ public class TestExObjList extends TestCase {
|
|||||||
// Get the document
|
// Get the document
|
||||||
Document doc = ss.getDocumentRecord();
|
Document doc = ss.getDocumentRecord();
|
||||||
// Get the ExObjList
|
// Get the ExObjList
|
||||||
ExObjList exObjList = doc.getExObjList();
|
ExObjList exObjList = doc.getExObjList(false);
|
||||||
assertNotNull(exObjList);
|
assertNotNull(exObjList);
|
||||||
assertEquals(1033l, exObjList.getRecordType());
|
assertEquals(1033l, exObjList.getRecordType());
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user