You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. /* ====================================================================
  2. Licensed to the Apache Software Foundation (ASF) under one or more
  3. contributor license agreements. See the NOTICE file distributed with
  4. this work for additional information regarding copyright ownership.
  5. The ASF licenses this file to You under the Apache License, Version 2.0
  6. (the "License"); you may not use this file except in compliance with
  7. the License. You may obtain a copy of the License at
  8. http://www.apache.org/licenses/LICENSE-2.0
  9. Unless required by applicable law or agreed to in writing, software
  10. distributed under the License is distributed on an "AS IS" BASIS,
  11. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. See the License for the specific language governing permissions and
  13. limitations under the License.
  14. ==================================================================== */
  15. package org.apache.poi.xslf.usermodel;
  16. import org.apache.poi.POIXMLDocumentPart;
  17. import org.apache.poi.openxml4j.opc.PackagePart;
  18. import org.apache.poi.openxml4j.opc.PackageRelationship;
  19. import org.apache.poi.openxml4j.opc.TargetMode;
  20. import org.apache.poi.util.Beta;
  21. import org.apache.poi.util.Internal;
  22. import org.apache.xmlbeans.XmlObject;
  23. import org.apache.xmlbeans.XmlOptions;
  24. import org.openxmlformats.schemas.officeDocument.x2006.relationships.STRelationshipId;
  25. import org.openxmlformats.schemas.presentationml.x2006.main.CTCommonSlideData;
  26. import org.openxmlformats.schemas.presentationml.x2006.main.CTConnector;
  27. import org.openxmlformats.schemas.presentationml.x2006.main.CTGraphicalObjectFrame;
  28. import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShape;
  29. import org.openxmlformats.schemas.presentationml.x2006.main.CTPicture;
  30. import org.openxmlformats.schemas.presentationml.x2006.main.CTShape;
  31. import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder;
  32. import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D;
  33. import org.openxmlformats.schemas.drawingml.x2006.main.CTTextListStyle;
  34. import javax.xml.namespace.QName;
  35. import java.awt.Graphics2D;
  36. import java.awt.geom.AffineTransform;
  37. import java.io.IOException;
  38. import java.io.OutputStream;
  39. import java.util.ArrayList;
  40. import java.util.HashMap;
  41. import java.util.List;
  42. import java.util.Map;
  43. import java.util.regex.Pattern;
  44. @Beta
  45. public abstract class XSLFSheet extends POIXMLDocumentPart {
  46. private XSLFCommonSlideData _commonSlideData;
  47. private XSLFDrawing _drawing;
  48. private List<XSLFShape> _shapes;
  49. private CTGroupShape _spTree;
  50. private Map<Integer, XSLFSimpleShape> _placeholderByIdMap;
  51. private Map<Integer, XSLFSimpleShape> _placeholderByTypeMap;
  52. public XSLFSheet() {
  53. super();
  54. }
  55. public XSLFSheet(PackagePart part, PackageRelationship rel){
  56. super(part, rel);
  57. }
  58. public XMLSlideShow getSlideShow() {
  59. return (XMLSlideShow)getParent();
  60. }
  61. protected List<XSLFShape> buildShapes(CTGroupShape spTree){
  62. List<XSLFShape> shapes = new ArrayList<XSLFShape>();
  63. for(XmlObject ch : spTree.selectPath("*")){
  64. if(ch instanceof CTShape){ // simple shape
  65. XSLFAutoShape shape = XSLFAutoShape.create((CTShape)ch, this);
  66. shapes.add(shape);
  67. } else if (ch instanceof CTGroupShape){
  68. shapes.add(new XSLFGroupShape((CTGroupShape)ch, this));
  69. } else if (ch instanceof CTConnector){
  70. shapes.add(new XSLFConnectorShape((CTConnector)ch, this));
  71. } else if (ch instanceof CTPicture){
  72. shapes.add(new XSLFPictureShape((CTPicture)ch, this));
  73. } else if (ch instanceof CTGraphicalObjectFrame){
  74. XSLFGraphicFrame shape = XSLFGraphicFrame.create((CTGraphicalObjectFrame)ch, this);
  75. shapes.add(shape);
  76. }
  77. }
  78. return shapes;
  79. }
  80. public abstract XmlObject getXmlObject();
  81. public XSLFCommonSlideData getCommonSlideData() {
  82. return _commonSlideData;
  83. }
  84. protected void setCommonSlideData(CTCommonSlideData data) {
  85. if(data == null) {
  86. _commonSlideData = null;
  87. } else {
  88. _commonSlideData = new XSLFCommonSlideData(data);
  89. }
  90. }
  91. private XSLFDrawing getDrawing(){
  92. if(_drawing == null) {
  93. _drawing = new XSLFDrawing(this, getSpTree());
  94. }
  95. return _drawing;
  96. }
  97. private List<XSLFShape> getShapeList(){
  98. if(_shapes == null){
  99. _shapes = buildShapes(getSpTree());
  100. }
  101. return _shapes;
  102. }
  103. // shape factory methods
  104. public XSLFAutoShape createAutoShape(){
  105. List<XSLFShape> shapes = getShapeList();
  106. XSLFAutoShape sh = getDrawing().createAutoShape();
  107. shapes.add(sh);
  108. return sh;
  109. }
  110. public XSLFFreeformShape createFreeform(){
  111. List<XSLFShape> shapes = getShapeList();
  112. XSLFFreeformShape sh = getDrawing().createFreeform();
  113. shapes.add(sh);
  114. return sh;
  115. }
  116. public XSLFTextBox createTextBox(){
  117. List<XSLFShape> shapes = getShapeList();
  118. XSLFTextBox sh = getDrawing().createTextBox();
  119. shapes.add(sh);
  120. return sh;
  121. }
  122. public XSLFConnectorShape createConnector(){
  123. List<XSLFShape> shapes = getShapeList();
  124. XSLFConnectorShape sh = getDrawing().createConnector();
  125. shapes.add(sh);
  126. return sh;
  127. }
  128. public XSLFGroupShape createGroup(){
  129. List<XSLFShape> shapes = getShapeList();
  130. XSLFGroupShape sh = getDrawing().createGroup();
  131. shapes.add(sh);
  132. return sh;
  133. }
  134. public XSLFPictureShape createPicture(int pictureIndex){
  135. List<PackagePart> pics = getPackagePart().getPackage()
  136. .getPartsByName(Pattern.compile("/ppt/media/.*?"));
  137. PackagePart pic = pics.get(pictureIndex);
  138. PackageRelationship rel = getPackagePart().addRelationship(
  139. pic.getPartName(), TargetMode.INTERNAL, XSLFRelation.IMAGES.getRelation());
  140. addRelation(rel.getId(), new XSLFPictureData(pic, rel));
  141. XSLFPictureShape sh = getDrawing().createPicture(rel.getId());
  142. sh.resize();
  143. getShapeList().add(sh);
  144. return sh;
  145. }
  146. public XSLFTable createTable(){
  147. List<XSLFShape> shapes = getShapeList();
  148. XSLFTable sh = getDrawing().createTable();
  149. shapes.add(sh);
  150. return sh;
  151. }
  152. public XSLFShape[] getShapes(){
  153. return getShapeList().toArray(new XSLFShape[_shapes.size()]);
  154. }
  155. public boolean removeShape(XSLFShape xShape) {
  156. XmlObject obj = xShape.getXmlObject();
  157. CTGroupShape spTree = getSpTree();
  158. if(obj instanceof CTShape){
  159. spTree.getSpList().remove(obj);
  160. } else if (obj instanceof CTGroupShape){
  161. spTree.getGrpSpList().remove(obj);
  162. } else if (obj instanceof CTConnector){
  163. spTree.getCxnSpList().remove(obj);
  164. } else {
  165. throw new IllegalArgumentException("Unsupported shape: " + xShape);
  166. }
  167. return getShapeList().remove(xShape);
  168. }
  169. public XSLFBackground getBackground(){
  170. return null;
  171. }
  172. protected abstract String getRootElementName();
  173. protected CTGroupShape getSpTree(){
  174. if(_spTree == null) {
  175. XmlObject root = getXmlObject();
  176. XmlObject[] sp = root.selectPath(
  177. "declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' .//*/p:spTree");
  178. if(sp.length == 0) throw new IllegalStateException("CTGroupShape was not found");
  179. _spTree = (CTGroupShape)sp[0];
  180. }
  181. return _spTree;
  182. }
  183. protected final void commit() throws IOException {
  184. XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS);
  185. Map<String, String> map = new HashMap<String, String>();
  186. map.put(STRelationshipId.type.getName().getNamespaceURI(), "r");
  187. map.put("http://schemas.openxmlformats.org/drawingml/2006/main", "a");
  188. map.put("http://schemas.openxmlformats.org/presentationml/2006/main", "p");
  189. xmlOptions.setSaveSuggestedPrefixes(map);
  190. String docName = getRootElementName();
  191. if(docName != null) {
  192. xmlOptions.setSaveSyntheticDocumentElement(
  193. new QName("http://schemas.openxmlformats.org/presentationml/2006/main", docName));
  194. }
  195. PackagePart part = getPackagePart();
  196. OutputStream out = part.getOutputStream();
  197. getXmlObject().save(out, xmlOptions);
  198. out.close();
  199. }
  200. /**
  201. * Set the contents of this sheet to be a copy of the source sheet.
  202. *
  203. * @param src the source sheet to copy data from
  204. */
  205. public void copy(XSLFSheet src){
  206. _shapes = null;
  207. _spTree = null;
  208. _drawing = null;
  209. getXmlObject().set(src.getXmlObject());
  210. }
  211. public XSLFTheme getTheme(){
  212. return null;
  213. }
  214. public XSLFSlideMaster getSlideMaster(){
  215. return null;
  216. }
  217. public XSLFSlideLayout getSlideLayout(){
  218. return null;
  219. }
  220. protected CTTextListStyle getTextProperties(Placeholder textType) {
  221. return null;
  222. }
  223. protected XSLFTextShape getTextShapeByType(Placeholder type){
  224. for(XSLFShape shape : this.getShapes()){
  225. if(shape instanceof XSLFTextShape) {
  226. XSLFTextShape txt = (XSLFTextShape)shape;
  227. if(txt.getTextType() == type) {
  228. return txt;
  229. }
  230. }
  231. }
  232. return null;
  233. }
  234. XSLFSimpleShape getPlaceholder(CTPlaceholder ph) {
  235. XSLFSimpleShape shape = null;
  236. if(ph.isSetIdx()) shape = getPlaceholderById((int)ph.getIdx());
  237. if (shape == null && ph.isSetType()) {
  238. shape = getPlaceholderByType(ph.getType().intValue());
  239. }
  240. return shape;
  241. }
  242. XSLFSimpleShape getPlaceholderById(int id) {
  243. if(_placeholderByIdMap == null) {
  244. _placeholderByIdMap = new HashMap<Integer, XSLFSimpleShape>();
  245. for(XSLFShape sh : getShapes()){
  246. if(sh instanceof XSLFSimpleShape){
  247. XSLFSimpleShape sShape = (XSLFSimpleShape)sh;
  248. CTPlaceholder ph = sShape.getCTPlaceholder();
  249. if(ph != null && ph.isSetIdx()){
  250. int idx = (int)ph.getIdx();
  251. _placeholderByIdMap.put(idx, sShape);
  252. }
  253. }
  254. }
  255. }
  256. return _placeholderByIdMap.get(id);
  257. }
  258. XSLFSimpleShape getPlaceholderByType(int ordinal) {
  259. if(_placeholderByTypeMap == null) {
  260. _placeholderByTypeMap = new HashMap<Integer, XSLFSimpleShape>();
  261. for(XSLFShape sh : getShapes()){
  262. if(sh instanceof XSLFSimpleShape){
  263. XSLFSimpleShape sShape = (XSLFSimpleShape)sh;
  264. CTPlaceholder ph = sShape.getCTPlaceholder();
  265. if(ph != null && ph.isSetType()){
  266. _placeholderByTypeMap.put(ph.getType().intValue(), sShape);
  267. }
  268. }
  269. }
  270. }
  271. return _placeholderByTypeMap.get(ordinal);
  272. }
  273. /**
  274. * Checks if this <code>sheet</code> displays the specified shape.
  275. *
  276. * Subclasses can override it and skip certain shapes from drawings.
  277. */
  278. protected boolean canDraw(XSLFShape shape){
  279. return true;
  280. }
  281. /**
  282. * Render this sheet into the supplied graphics object
  283. *
  284. * @param graphics
  285. */
  286. public void draw(Graphics2D graphics){
  287. XSLFBackground bg = getBackground();
  288. if(bg != null) bg.draw(graphics);
  289. for(XSLFShape shape : getShapeList()) {
  290. if(!canDraw(shape)) continue;
  291. // remember the initial transform and restore it after we are done with drawing
  292. AffineTransform at0 = graphics.getTransform();
  293. graphics.setRenderingHint(XSLFRenderingHint.GSAVE, true);
  294. // apply rotation and flipping
  295. shape.applyTransform(graphics);
  296. shape.draw(graphics);
  297. // restore the coordinate system
  298. graphics.setTransform(at0);
  299. graphics.setRenderingHint(XSLFRenderingHint.GRESTORE, true);
  300. }
  301. }
  302. }