package info.opencards.pptintegration;
import info.opencards.Utils;
import info.opencards.core.CardFile;
import org.apache.poi.hslf.record.TextHeaderAtom;
import org.apache.poi.hslf.usermodel.HSLFAutoShape;
import org.apache.poi.hslf.usermodel.HSLFShape;
import org.apache.poi.hslf.usermodel.HSLFSlide;
import org.apache.poi.hslf.usermodel.HSLFSlideMaster;
import org.apache.poi.sl.draw.DrawFactory;
import org.apache.poi.sl.usermodel.AutoShape;
import org.apache.poi.sl.usermodel.Slide;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.AffineTransform;
/**
* Allows to render incomplete powerpoint slides (given as poi-objects)
*
* @author Holger Brandl
*/
public class PPTSlideRenderPanel extends JPanel {
private HSLFSlide slide;
private boolean showTitleShape;
private boolean showContent;
private Dimension baseSize;
private CardFile curCardFile;
public PPTSlideRenderPanel() {
addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent mouseEvent) {
if (mouseEvent.getClickCount() == 2) {
// show the slide in the system's ppt-editor
OpenCurrentSlide.showCurrentSlideInPPTEditor(curCardFile, slide);
}
}
});
}
private void drawSlidesPartially(Graphics2D graphics, HSLFSlide slide) {
HSLFSlideMaster master = (HSLFSlideMaster) slide.getMasterSheet();
if (slide.getFollowMasterBackground() && master.getBackground() != null) {
// master.getBackground().draw(graphics, null);
factoryDraw(graphics, master.getBackground());
}
if (slide.getFollowMasterObjects()) {
java.util.List<HSLFShape> sh = master.getShapes();
for (HSLFShape aSh : sh) {
if (aSh.isPlaceholder()) continue;
aSh.draw(graphics, null);
}
}
HSLFShape titleShape = getTitleShape(slide);
for (HSLFShape shape : slide.getShapes()) {
boolean isTitleShape = shape.getShapeId() == titleShape.getShapeId();
if (isTitleShape && showTitleShape) {
// shape.draw(graphics);
factoryDraw(graphics, shape);
}
if (!isTitleShape && showContent) {
// shape.draw(graphics);
factoryDraw(graphics, shape);
}
}
}
private void factoryDraw(Graphics2D graphics, HSLFShape shape) {
DrawFactory.getInstance(graphics).getDrawable(shape).draw(graphics);
}
private HSLFShape getTitleShape(HSLFSlide slide) {
String slideTitle = slide.getTitle();
for (HSLFShape shape : slide.getShapes()) {
if (shape instanceof AutoShape) {
HSLFAutoShape autoShape = (HSLFAutoShape) shape;
if (autoShape.getText() != null && autoShape.getText().equals(slideTitle)) {
int type = autoShape.getRunType();
if (type == TextHeaderAtom.CENTER_TITLE_TYPE || type == TextHeaderAtom.TITLE_TYPE) {
return shape;
}
}
}
}
// When you have a XSLFSlide object you can use .getShapes() to get all shapes in the slide. If the shape is a
// XSLFTextShape you can use .getTextType() to check if it's a title, .getTextParagraphs() to get the paragraphs and
// .getTextRuns() on the paragraphs to get the text runs with the text. That should give you
return null;
// can not work as we don't have a slide title for slides without a title element
// // if we don't find a title shape than use the most topwards element as question
// if(slide.getShapes().length ==0)
// return null;
//
// return Collections.max(Arrays.asList(slide.getShapes()), new Comparator<Shape>() {
// @Override
// public int compare(Shape o1, Shape o2) {
// return o1.getAnchor().getCenterY() - o2.getAnchor().getCenterY() < 0 ? -1 : 1;
// }
// });
}
@Override
protected void paintComponent(Graphics graphics) {
Graphics2D g2d = (Graphics2D) graphics;
if (!Utils.isMacOSX()) {
RenderingHints renderHints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
renderHints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHints(renderHints);
}
super.paintComponent(graphics);
if (slide == null) {
return;
}
// System.err.println("dimension: " + getSize());
// System.err.println("baseSize: " + baseSize);
// System.err.println("scaling: " + slideScaleTransform);
double slideRatio = baseSize.getWidth() / baseSize.getHeight();
double containerRatio = getSize().getWidth() / getSize().getHeight();
AffineTransform slideScaleTransform = new AffineTransform();
if (slideRatio < containerRatio) {
// scaleDim = new Dimension(getWidth(), (int) (getSize().getHeight() / slideRatio));
// y is limitting expansionhere
double yScale = getSize().getHeight() / baseSize.getHeight();
slideScaleTransform.scale(yScale, yScale);
slideScaleTransform.translate((getSize().getWidth() - yScale * baseSize.getWidth()) * 0.5 / yScale, 0);
} else {
double xScale = getSize().getWidth() / baseSize.getWidth();
slideScaleTransform.scale(xScale, xScale);
slideScaleTransform.translate(0, (getSize().getHeight() - xScale * baseSize.getHeight()) * 0.5 / xScale);
}
// ...or adjust to full width
// double xScale = scaleDim.getWidth() / getWidth();
// double yScale = scaleDim.getHeight() / getHeight();
//
// slideScaleTransform.scale(xScale, yScale);
// slideScaleTransform.translate(xScale, yScale);
g2d.setTransform(slideScaleTransform);
if (showContent && showTitleShape) {
slide.draw(g2d);
} else {
drawSlidesPartially(g2d, slide);
}
}
public void configure(Slide slide, boolean showTitle, boolean showContent) {
this.slide = (HSLFSlide) slide;
this.showTitleShape = showTitle;
this.showContent = showContent;
repaint();
}
public void setBaseSize(Dimension baseSize) {
this.baseSize = baseSize;
}
public void setCardFile(CardFile cardFile) {
curCardFile = cardFile;
}
}