Parcourir la source

#65694 - HSLF - handle date/time fields and formats

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1895248 13f79535-47bb-0310-9956-ffa450edef68
tags/REL_5_2_0
Andreas Beeker il y a 2 ans
Parent
révision
d3ff953cf7

+ 1
- 7
poi-ooxml/src/main/java/org/apache/poi/xslf/usermodel/XSLFSlide.java Voir le fichier

* Construct a SpreadsheetML slide from a package part * Construct a SpreadsheetML slide from a package part
* *
* @param part the package part holding the slide data, * @param part the package part holding the slide data,
* the content type must be <code>application/vnd.openxmlformats-officedocument.slide+xml</code>
* the content type must be {@code application/vnd.openxmlformats-officedocument.slide+xml}
* *
* @since POI 3.14-Beta1 * @since POI 3.14-Beta1
*/ */
draw.draw(graphics); draw.draw(graphics);
} }


@Override
public boolean getDisplayPlaceholder(Placeholder placeholder) {
return false;
}


@Override @Override
public void setHidden(boolean hidden) { public void setHidden(boolean hidden) {
CTSlide sld = getXmlObject(); CTSlide sld = getXmlObject();

+ 33
- 3
poi-scratchpad/src/main/java/org/apache/poi/hslf/model/HeadersFooters.java Voir le fichier



public HeadersFooters(HSLFSheet sheet, short headerFooterType) { public HeadersFooters(HSLFSheet sheet, short headerFooterType) {
_sheet = sheet; _sheet = sheet;
@SuppressWarnings("resource") @SuppressWarnings("resource")
HSLFSlideShow ppt = _sheet.getSlideShow(); HSLFSlideShow ppt = _sheet.getSlideShow();
Document doc = ppt.getDocumentRecord(); Document doc = ppt.getDocumentRecord();
// detect if this ppt was saved in Office2007 // detect if this ppt was saved in Office2007
String tag = ppt.getSlideMasters().get(0).getProgrammableTag(); String tag = ppt.getSlideMasters().get(0).getProgrammableTag();
_ppt2007 = _ppt2007tag.equals(tag); _ppt2007 = _ppt2007tag.equals(tag);
} }
} }
} }
if (hdd == null) { if (hdd == null) {
hdd = new HeadersFootersContainer(headerFooterType); hdd = new HeadersFootersContainer(headerFooterType);
Record lst = doc.findFirstOfType(RecordTypes.List.typeID); Record lst = doc.findFirstOfType(RecordTypes.List.typeID);
return isVisible(HeadersFootersAtom.fHasUserDate, Placeholder.DATETIME); return isVisible(HeadersFootersAtom.fHasUserDate, Placeholder.DATETIME);
} }


public CString getHeaderAtom() {
return _container.getHeaderAtom();
}

public CString getFooterAtom() {
return _container.getFooterAtom();
}

public CString getUserDateAtom() {
return _container.getUserDateAtom();
}

/** /**
* whether the date is displayed in the footer. * whether the date is displayed in the footer.
*/ */
setFlag(HeadersFootersAtom.fHasUserDate, flag); setFlag(HeadersFootersAtom.fHasUserDate, flag);
} }


/**
* whether today's date is used.
*/
public boolean isTodayDateVisible(){
return isVisible(HeadersFootersAtom.fHasTodayDate, Placeholder.DATETIME);
}

/**
* whether the todays date is displayed in the footer.
*/
public void setTodayDateVisible(boolean flag){
setFlag(HeadersFootersAtom.fHasTodayDate, flag);
}

/** /**
* whether the slide number is displayed in the footer. * whether the slide number is displayed in the footer.
*/ */
public boolean isPpt2007() { public boolean isPpt2007() {
return _ppt2007; return _ppt2007;
} }

public HeadersFootersContainer getContainer() {
return _container;
}
} }

+ 125
- 0
poi-scratchpad/src/main/java/org/apache/poi/hslf/record/DateTimeMCAtom.java Voir le fichier

/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */

package org.apache.poi.hslf.record;

import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Map;
import java.util.function.Supplier;

import org.apache.poi.util.GenericRecordUtil;
import org.apache.poi.util.LittleEndian;

public class DateTimeMCAtom extends RecordAtom {

/**
* Record header.
*/
private final byte[] _header;

/**
* A TextPosition that specifies the position of the metacharacter in the corresponding text.
*/
private int position;

/**
* An unsigned byte that specifies the Format ID used to stylize datetime. The identifier specified by
* the Format ID is converted based on the LCID [MS-LCID] into a value or string as specified in the
* following tables. The LCID is specified in TextSIException.lid. If no valid LCID is found in
* TextSIException.lid, TextSIException.altLid (if it exists) is used.
* The value MUST be greater than or equal to 0x0 and MUST be less than or equal to 0xC.
*/
private int index;

private final byte[] unused = new byte[3];

protected DateTimeMCAtom() {
_header = new byte[8];
position = 0;
index = 0;

LittleEndian.putShort(_header, 2, (short)getRecordType());
LittleEndian.putInt(_header, 4, 8);
}

/**
* Constructs the datetime atom record from its source data.
*
* @param source the source data as a byte array.
* @param start the start offset into the byte array.
* @param len the length of the slice in the byte array.
*/
protected DateTimeMCAtom(byte[] source, int start, int len) {
// Get the header.
_header = Arrays.copyOfRange(source, start, start+8);

position = LittleEndian.getInt(source, start+8);
index = LittleEndian.getUByte(source, start+12);
System.arraycopy(source, start+13, unused, 0, 3);
}

/**
* Write the contents of the record back, so it can be written
* to disk
*
* @param out the output stream to write to.
* @throws IOException if an error occurs.
*/
@Override
public void writeOut(OutputStream out) throws IOException {
out.write(_header);
LittleEndian.putInt(position, out);
out.write(index);
out.write(unused);
}

public int getPosition() {
return position;
}

public void setPosition(int position) {
this.position = position;
}

public int getIndex() {
return index;
}

public void setIndex(int index) {
this.index = index;
}

/**
* Gets the record type.
* @return the record type.
*/
@Override
public long getRecordType() {
return RecordTypes.DateTimeMCAtom.typeID;
}

@Override
public Map<String, Supplier<?>> getGenericProperties() {
return GenericRecordUtil.getGenericProperties(
"position", this::getPosition,
"index", this::getIndex
);
}

}

+ 3
- 27
poi-scratchpad/src/main/java/org/apache/poi/hslf/record/HeadersFootersAtom.java Voir le fichier

package org.apache.poi.hslf.record; package org.apache.poi.hslf.record;


import static org.apache.poi.util.GenericRecordUtil.getBitsAsString; import static org.apache.poi.util.GenericRecordUtil.getBitsAsString;
import static org.apache.poi.util.GenericRecordUtil.safeEnum;


import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;


public final class HeadersFootersAtom extends RecordAtom { public final class HeadersFootersAtom extends RecordAtom {


/** FormatIndex enum without LCID mapping */
public enum FormatIndex {
SHORT_DATE,
LONG_DATE,
LONG_DATE_WITHOUT_WEEKDAY,
ALTERNATE_SHORT_DATE,
ISO_STANDARD_DATE,
SHORT_DATE_WITH_ABBREVIATED_MONTH,
SHORT_DATE_WITH_SLASHES,
ALTERNATE_SHORT_DATE_WITH_ABBREVIATED_MONTH,
ENGLISH_DATE,
MONTH_AND_YEAR,
ABBREVIATED_MONTH_AND_YEAR,
DATE_AND_HOUR12_TIME,
DATE_AND_HOUR12_TIME_WITH_SECONDS,
HOUR12_TIME,
HOUR12_TIME_WITH_SECONDS,
HOUR24_TIME,
HOUR24_TIME_WITH_SECONDS,
CHINESE1,
CHINESE2,
CHINESE3
}

/** /**
* A bit that specifies whether the date is displayed in the footer. * A bit that specifies whether the date is displayed in the footer.
* @see #getMask() * @see #getMask()
/** /**
* Build an instance of {@code HeadersFootersAtom} from on-disk data * Build an instance of {@code HeadersFootersAtom} from on-disk data
*/ */
protected HeadersFootersAtom(byte[] source, int start, int len) {
HeadersFootersAtom(byte[] source, int start, int len) {
// Get the header // Get the header
_header = Arrays.copyOfRange(source, start, start+8); _header = Arrays.copyOfRange(source, start, start+8);


return LittleEndian.getShort(_recdata, 0); return LittleEndian.getShort(_recdata, 0);
} }



/** /**
* A signed integer that specifies the format ID to be used to style the datetime. * A signed integer that specifies the format ID to be used to style the datetime.
* *
@Override @Override
public Map<String, Supplier<?>> getGenericProperties() { public Map<String, Supplier<?>> getGenericProperties() {
return GenericRecordUtil.getGenericProperties( return GenericRecordUtil.getGenericProperties(
"formatIndex", safeEnum(FormatIndex.values(), this::getFormatId),
"formatIndex", this::getFormatId,
"flags", getBitsAsString(this::getMask, PLACEHOLDER_MASKS, PLACEHOLDER_NAMES) "flags", getBitsAsString(this::getMask, PLACEHOLDER_MASKS, PLACEHOLDER_NAMES)
); );
} }

+ 3
- 3
poi-scratchpad/src/main/java/org/apache/poi/hslf/record/OEPlaceholderAtom.java Voir le fichier

*/ */
public static final int PLACEHOLDER_QUARTSIZE = 2; public static final int PLACEHOLDER_QUARTSIZE = 2;


private byte[] _header;
private final byte[] _header;


private int placementId; private int placementId;
private int placeholderId; private int placeholderId;
/** /**
* Build an instance of {@code OEPlaceholderAtom} from on-disk data * Build an instance of {@code OEPlaceholderAtom} from on-disk data
*/ */
protected OEPlaceholderAtom(byte[] source, int start, int len) {
OEPlaceholderAtom(byte[] source, int start, int len) {
_header = Arrays.copyOfRange(source, start, start+8); _header = Arrays.copyOfRange(source, start, start+8);
int offset = start+8; int offset = start+8;


* Sets the placeholder Id.<p> * Sets the placeholder Id.<p>
* *
* placeholder Id specifies the type of the placeholder shape. * placeholder Id specifies the type of the placeholder shape.
* The value MUST be one of the static constants defined in this class
* The value MUST be one of the static constants defined in {@link Placeholder}
* *
* @param id the placeholder Id. * @param id the placeholder Id.
*/ */

+ 1
- 1
poi-scratchpad/src/main/java/org/apache/poi/hslf/record/RecordTypes.java Voir le fichier

InteractiveInfoAtom(4083,InteractiveInfoAtom::new), InteractiveInfoAtom(4083,InteractiveInfoAtom::new),
UserEditAtom(4085,UserEditAtom::new), UserEditAtom(4085,UserEditAtom::new),
CurrentUserAtom(4086,null), CurrentUserAtom(4086,null),
DateTimeMCAtom(4087,null),
DateTimeMCAtom(4087,DateTimeMCAtom::new),
GenericDateMCAtom(4088,null), GenericDateMCAtom(4088,null),
FooterMCAtom(4090,null), FooterMCAtom(4090,null),
ExControlAtom(4091,ExControlAtom::new), ExControlAtom(4091,ExControlAtom::new),

+ 3
- 2
poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFPlaceholderDetails.java Voir le fichier

} }




@Override
public boolean isVisible() { public boolean isVisible() {
final Placeholder ph = getPlaceholder(); final Placeholder ph = getPlaceholder();
if (ph == null) { if (ph == null) {


switch (ph) { switch (ph) {
case HEADER: case HEADER:
case TITLE:
return headersFooters.isHeaderVisible(); return headersFooters.isHeaderVisible();
case FOOTER: case FOOTER:
return headersFooters.isFooterVisible(); return headersFooters.isFooterVisible();
case DATETIME: case DATETIME:
return headersFooters.isDateTimeVisible(); return headersFooters.isDateTimeVisible();
case TITLE:
return headersFooters.isHeaderVisible();
case SLIDE_NUMBER: case SLIDE_NUMBER:
return headersFooters.isSlideNumberVisible(); return headersFooters.isSlideNumberVisible();
default: default:
} }
} }


@Override
public void setVisible(final boolean isVisible) { public void setVisible(final boolean isVisible) {
final Placeholder ph = getPlaceholder(); final Placeholder ph = getPlaceholder();
if (ph == null) { if (ph == null) {

+ 67
- 4
poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFShapePlaceholderDetails.java Voir le fichier



package org.apache.poi.hslf.usermodel; package org.apache.poi.hslf.usermodel;


import java.time.format.DateTimeFormatter;
import java.util.Optional;
import java.util.stream.Stream;

import org.apache.poi.ddf.EscherPropertyTypes; import org.apache.poi.ddf.EscherPropertyTypes;
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.model.HeadersFooters;
import org.apache.poi.hslf.record.CString;
import org.apache.poi.hslf.record.DateTimeMCAtom;
import org.apache.poi.hslf.record.EscherTextboxWrapper;
import org.apache.poi.hslf.record.HSLFEscherClientDataRecord; import org.apache.poi.hslf.record.HSLFEscherClientDataRecord;
import org.apache.poi.hslf.record.HeadersFootersAtom;
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.RecordTypes;
import org.apache.poi.hslf.record.RoundTripHFPlaceholder12; import org.apache.poi.hslf.record.RoundTripHFPlaceholder12;
import org.apache.poi.hslf.record.TextSpecInfoAtom;
import org.apache.poi.hslf.record.TextSpecInfoRun;
import org.apache.poi.hslf.util.LocaleDateFormat;
import org.apache.poi.sl.usermodel.MasterSheet; import org.apache.poi.sl.usermodel.MasterSheet;
import org.apache.poi.sl.usermodel.Placeholder; import org.apache.poi.sl.usermodel.Placeholder;
import org.apache.poi.util.LocaleID;
import org.apache.poi.util.LocaleUtil;


/** /**
* Extended placeholder details for HSLF shapes * Extended placeholder details for HSLF shapes
final HSLFSimpleShape shape; final HSLFSimpleShape shape;
private OEPlaceholderAtom oePlaceholderAtom; private OEPlaceholderAtom oePlaceholderAtom;
private RoundTripHFPlaceholder12 roundTripHFPlaceholder12; private RoundTripHFPlaceholder12 roundTripHFPlaceholder12;
private DateTimeMCAtom localDateTime;




HSLFShapePlaceholderDetails(final HSLFSimpleShape shape) { HSLFShapePlaceholderDetails(final HSLFSimpleShape shape) {
} }
} }


@Override
public Placeholder getPlaceholder() { public Placeholder getPlaceholder() {
updatePlaceholderAtom(false); updatePlaceholderAtom(false);
final int phId; final int phId;
phId = oePlaceholderAtom.getPlaceholderId(); phId = oePlaceholderAtom.getPlaceholderId();
} else if (roundTripHFPlaceholder12 != null) { } else if (roundTripHFPlaceholder12 != null) {
phId = roundTripHFPlaceholder12.getPlaceholderId(); phId = roundTripHFPlaceholder12.getPlaceholderId();
} else if (localDateTime != null) {
return Placeholder.DATETIME;
} else { } else {
return null; return null;
} }
} }
} }


@Override
public void setPlaceholder(final Placeholder placeholder) { public void setPlaceholder(final Placeholder placeholder) {
final EscherSpRecord spRecord = shape.getEscherChild(EscherSpRecord.RECORD_ID); final EscherSpRecord spRecord = shape.getEscherChild(EscherSpRecord.RECORD_ID);
int flags = spRecord.getFlags(); int flags = spRecord.getFlags();
roundTripHFPlaceholder12.setPlaceholderId(phId); roundTripHFPlaceholder12.setPlaceholderId(phId);
} }


@Override
public PlaceholderSize getSize() { public PlaceholderSize getSize() {
final Placeholder ph = getPlaceholder(); final Placeholder ph = getPlaceholder();
if (ph == null) { if (ph == null) {
return null; return null;
} }


final int size = (oePlaceholderAtom != null)
final int size = (oePlaceholderAtom != null)
? oePlaceholderAtom.getPlaceholderSize() ? oePlaceholderAtom.getPlaceholderSize()
: OEPlaceholderAtom.PLACEHOLDER_HALFSIZE; : OEPlaceholderAtom.PLACEHOLDER_HALFSIZE;
switch (size) { switch (size) {
case OEPlaceholderAtom.PLACEHOLDER_FULLSIZE: case OEPlaceholderAtom.PLACEHOLDER_FULLSIZE:
return PlaceholderSize.full; return PlaceholderSize.full;
} }
} }


@Override
public void setSize(final PlaceholderSize size) { public void setSize(final PlaceholderSize size) {
final Placeholder ph = getPlaceholder(); final Placeholder ph = getPlaceholder();
if (ph == null || size == null) { if (ph == null || size == null) {
return; return;
} }
updatePlaceholderAtom(true); updatePlaceholderAtom(true);
final byte ph_size; final byte ph_size;
switch (size) { switch (size) {
case full: case full:
} }


private void updatePlaceholderAtom(final boolean create) { private void updatePlaceholderAtom(final boolean create) {
localDateTime = null;
if (shape instanceof HSLFTextBox) {
EscherTextboxWrapper txtBox = ((HSLFTextBox)shape).getEscherTextboxWrapper();
if (txtBox != null) {
localDateTime = (DateTimeMCAtom)txtBox.findFirstOfType(RecordTypes.DateTimeMCAtom.typeID);
}
}

final HSLFEscherClientDataRecord clientData = shape.getClientData(create); final HSLFEscherClientDataRecord clientData = shape.getClientData(create);
if (clientData == null) { if (clientData == null) {
oePlaceholderAtom = null; oePlaceholderAtom = null;
clientData.addChild(roundTripHFPlaceholder12); clientData.addChild(roundTripHFPlaceholder12);
} }
} }

@Override
public String getUserDate() {
HeadersFooters hf = shape.getSheet().getHeadersFooters();
CString uda = hf.getUserDateAtom();
return hf.isUserDateVisible() && uda != null ? uda.getText() : null;
}

@Override
public DateTimeFormatter getDateFormat() {
int formatId;
if (localDateTime != null) {
formatId = localDateTime.getIndex();
} else {
HeadersFootersAtom hfAtom = shape.getSheet().getHeadersFooters().getContainer().getHeadersFootersAtom();
formatId = hfAtom.getFormatId();
}

LocaleID def = LocaleID.lookupByLanguageTag(LocaleUtil.getUserLocale().toLanguageTag());

// def = LocaleID.EN_US;

LocaleID lcid =
Stream.of(((HSLFTextShape)shape).getTextParagraphs().get(0).getRecords())
.filter(r -> r instanceof TextSpecInfoAtom)
.findFirst()
.map(r -> ((TextSpecInfoAtom)r).getTextSpecInfoRuns()[0])
.map(TextSpecInfoRun::getLangId)
.flatMap(lid -> Optional.ofNullable(LocaleID.lookupByLcid(lid)))
.orElse(def != null ? def : LocaleID.EN_US)
;

return LocaleDateFormat.map(lcid, formatId, LocaleDateFormat.MapFormatId.PPT);
}
} }

+ 28
- 4
poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFSlide.java Voir le fichier

import org.apache.poi.sl.usermodel.Notes; import org.apache.poi.sl.usermodel.Notes;
import org.apache.poi.sl.usermodel.Placeholder; 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.Slide; import org.apache.poi.sl.usermodel.Slide;
import org.apache.poi.sl.usermodel.TextShape.TextPlaceholder; import org.apache.poi.sl.usermodel.TextShape.TextPlaceholder;


* @return set of records inside {@code SlideListWithtext} container * @return set of records inside {@code SlideListWithtext} container
* which hold text data for this slide (typically for placeholders). * which hold text data for this slide (typically for placeholders).
*/ */
protected SlideAtomsSet getSlideAtomsSet() { return _atomSet; }
public SlideAtomsSet getSlideAtomsSet() { return _atomSet; }


/** /**
* Returns master sheet associated with this slide. * Returns master sheet associated with this slide.
(slt == SlideLayoutType.TITLE_SLIDE || slt == SlideLayoutType.TITLE_ONLY || slt == SlideLayoutType.MASTER_TITLE); (slt == SlideLayoutType.TITLE_SLIDE || slt == SlideLayoutType.TITLE_ONLY || slt == SlideLayoutType.MASTER_TITLE);
switch (placeholder) { switch (placeholder) {
case DATETIME: case DATETIME:
return hf.isDateTimeVisible() && !isTitle;
return (hf.isDateTimeVisible() && (hf.isTodayDateVisible() || (hf.isUserDateVisible() && hf.getUserDateAtom() != null))) && !isTitle;
case SLIDE_NUMBER: case SLIDE_NUMBER:
return hf.isSlideNumberVisible() && !isTitle; return hf.isSlideNumberVisible() && !isTitle;
case HEADER: case HEADER:
return hf.isHeaderVisible() && !isTitle;
return hf.isHeaderVisible() && hf.getHeaderAtom() != null && !isTitle;
case FOOTER: case FOOTER:
return hf.isFooterVisible() && !isTitle;
return hf.isFooterVisible() && hf.getFooterAtom() != null && !isTitle;
default: default:
return false; return false;
} }
} }


@Override
public boolean getDisplayPlaceholder(final SimpleShape<?,?> placeholderRef) {
Placeholder placeholder = placeholderRef.getPlaceholder();
if (placeholder == null) {
return false;
}

final HeadersFooters hf = getHeadersFooters();
final SlideLayoutType slt = getSlideRecord().getSlideAtom().getSSlideLayoutAtom().getGeometryType();
final boolean isTitle =
(slt == SlideLayoutType.TITLE_SLIDE || slt == SlideLayoutType.TITLE_ONLY || slt == SlideLayoutType.MASTER_TITLE);
switch (placeholder) {
case HEADER:
return hf.isHeaderVisible() && hf.getHeaderAtom() != null && !isTitle;
case FOOTER:
return hf.isFooterVisible() && hf.getFooterAtom() != null && !isTitle;
case DATETIME:
case SLIDE_NUMBER:
default:
return false;
}
}

@Override @Override
public HSLFMasterSheet getSlideLayout(){ public HSLFMasterSheet getSlideLayout(){
// TODO: find out how we can find the mastersheet base on the slide layout type, i.e. // TODO: find out how we can find the mastersheet base on the slide layout type, i.e.

+ 364
- 0
poi-scratchpad/src/main/java/org/apache/poi/hslf/util/LocaleDateFormat.java Voir le fichier

/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */

package org.apache.poi.hslf.util;

import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.FormatStyle;
import java.util.AbstractMap;
import java.util.Locale;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.apache.poi.util.Internal;
import org.apache.poi.util.LocaleID;
import org.apache.poi.util.SuppressForbidden;

@Internal
public final class LocaleDateFormat {

/**
* Enum to specify initial remapping of the FormatID based on thd LCID
*/
public enum MapFormatId {
NONE, PPT
}

private enum MapFormatPPT {
EN_US(LocaleID.EN_US, "MM/dd/yyyy", 1, 8, "MMMM dd, yyyy", 5, 9, 10, 11, 12, 15, 16, "h:mm a", "h:mm:ss a"),
EN_AU(LocaleID.EN_AU, 0, 1, "d MMMM, yyy", 2, 5, 9, 10, 11, 12, 15, 16, 13, 14),
JA_JP(LocaleID.JA_JP, 4, 8, 7, 3, 0, 9, 5, 11, 12, "HH:mm", "HH:mm:ss", 15, 16),
ZH_TW(LocaleID.ZH_TW, 0, 1, 3, 7, 12, 9, 10, 4, 11, "HH:mm", "HH:mm:ss", "H:mm a", "H:mm:ss a"),
KO_KR(LocaleID.KO_KR, 0, 1, 6, 3, 4, 10, 7, 12, 11, "HH:mm", "HH:mm:ss", 13, 14 ),
AR_SA(LocaleID.AR_SA, 0, 1, 2, 3, 4, 5, 8, 7, 8, 1, 10, 11, 5),
HE_IL(LocaleID.HE_IL, 0, 1, 2, 6, 11, 5, 12, 7, 8, 9, 1, 11, 6),
SV_SE(LocaleID.SV_SE, 0, 1, 3, 2, 7, 9, 10, 11, 12, 15, 16, 13, 14),
ZH_CN(LocaleID.ZH_CN, 0, 1, 2, 2, 4, 9, 5, "yyyy\u5E74M\u6708d\u65E5h\u65F6m\u5206", "yyyy\u5E74M\u6708d\u65E5\u661F\u671fWh\u65F6m\u5206s\u79D2", "HH:mm", "HH:mm:ss", "a h\u65F6m\u5206", "a h\u65F6m\u5206s\u79D2"),
ZH_SG(LocaleID.ZH_SG, 0, 1, 3, 2, 4, 9, 5, "yyyy\u5E74M\u6708d\u65E5h\u65F6m\u5206", "yyyy\u5E74M\u6708d\u65E5\u661F\u671fWh\u65F6m\u5206s\u79D2", "HH:mm", "HH:mm:ss", "a h\u65F6m\u5206", "a h\u65F6m\u5206s\u79D2"),
ZH_MO(LocaleID.ZH_MO, 0, 1, 3, 2, 4, 9, 5, "yyyy\u5E74M\u6708d\u65E5h\u65F6m\u5206", "yyyy\u5E74M\u6708d\u65E5\u661F\u671fWh\u65F6m\u5206s\u79D2", "HH:mm", "HH:mm:ss", "a h\u65F6m\u5206", "a h\u65F6m\u5206s\u79D2"),
ZH_HK(LocaleID.ZH_HK, 0, 1, 3, 2, 4, 9, 5, "yyyy\u5E74M\u6708d\u65E5h\u65F6m\u5206", "yyyy\u5E74M\u6708d\u65E5\u661F\u671fWh\u65F6m\u5206s\u79D2", "HH:mm", "HH:mm:ss", "a h\u65F6m\u5206", "a h\u65F6m\u5206s\u79D2"),
TH_TH(LocaleID.TH_TH, 0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 13, 14),
VI_VN(LocaleID.VI_VN, 0, 1, 2, 3, 5, 6, 10, 11, 12, 13, 14, 15, 16),
HI_IN(LocaleID.HI_IN, 1, 2, 3, 5, 7, 11, 13, 0, 1, 5, 10, 11, 14),
SYR_SY(LocaleID.SYR_SY, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12),
NO_MAP(LocaleID.INVALID_O, 0, 1, 3, 2, 5, 9, 10, 11, 12, 15, 16, 13, 14, 4, 6, 7, 8)
;

private final LocaleID lcid;
private final Object[] mapping;

private static final Map<LocaleID,MapFormatPPT> LCID_LOOKUP =
Stream.of(values()).collect(Collectors.toMap(MapFormatPPT::getLocaleID, Function.identity()));

MapFormatPPT(LocaleID lcid, Object... mapping) {
this.lcid = lcid;
this.mapping = mapping;
}

public LocaleID getLocaleID() {
return lcid;
}

public static Object mapFormatId(LocaleID lcid, int formatId) {
Object[] mapping = LCID_LOOKUP.getOrDefault(lcid, NO_MAP).mapping;
return (formatId >= 0 && formatId < mapping.length) ? mapping[formatId] : formatId;
}
}

private enum MapFormatException {
CHINESE(
new LocaleID[]{LocaleID.ZH, LocaleID.ZH_HANS, LocaleID.ZH_HANT, LocaleID.ZH_CN, LocaleID.ZH_SG, LocaleID.ZH_MO, LocaleID.ZH_HK, LocaleID.ZH_YUE_HK},
0,
1,
"yyyy\u5E74M\u6708d\u65E5\u661F\u671FW",
"yyyy\u5E74M\u6708d\u65E5",
"yyyy/M/d",
"yy.M.d",
"yyyy\u5E74M\u6708d\u65E5\u661F\u671FW",
"yyyy\u5E74M\u6708d\u65E5",
"yyyy\u5E74M\u6708d\u65E5\u661F\u671FW",
"yyyy\u5E74M\u6708",
"yyyy\u5E74M\u6708",
"h\u65F6m\u5206s\u79D2",
"h\u65F6m\u5206",
"h\u65F6m\u5206",
"h\u65F6m\u5206",
"ah\u65F6m\u5206",
"ah\u65F6m\u5206",
// no lunar calendar support
"EEEE\u5E74O\u6708A\u65E5",
"EEEE\u5E74O\u6708A\u65E5\u661F\u671FW",
"EEEE\u5E74O\u6708"
),
// no hindu calendar support
HINDI(
new LocaleID[]{LocaleID.HI, LocaleID.HI_IN},
"dd/M/g",
"dddd, d MMMM yyyy",
"dd MMMM yyyy",
"dd/M/yy",
"yy-M-dd",
"d-MMMM-yyyy",
"dd.M.g",
"dd MMMM. yy",
"dd MMMM yy",
"MMMM YY",
"MMMM-g",
"dd/M/g HH:mm",
"dd/M/g HH:mm:ss",
"HH:mm a",
"HH:mm:ss a",
"HH:mm",
"HH:mm:ss"
),
// https://www.secondsite8.com/customdateformats.htm
// aa or gg or o, r, i, c -> lunar calendar not supported
// (aaa) -> lower case week names ... not supported
JAPANESE(
new LocaleID[]{LocaleID.JA, LocaleID.JA_JP, LocaleID.JA_PLOC_JP},
0,
1,
"EEEy\u5E74M\u6708d\u65E5",
"yyyy\u5E74M\u6708d\u65E5",
"yyyy/M/d",
"yyyy\u5E74M\u6708d\u65E5",
"yy\u5E74M\u6708d\u65E5",
"yyyy\u5E74M\u6708d\u65E5",
"yyyy\u5E74M\u6708d\u65E5(EEE)",
"yyyy\u5E74M\u6708",
"yyyy\u5E74M\u6708",
"yy/M/d H\u6642m\u5206",
"yy/M/d H\u6642m\u5206s\u79D2",
"a h\u6642m\u5206",
"a h\u6642m\u5206s\u79D2",
"H\u6642m\u5206",
"H\u6642m\u5206s\u79D2",
"yyyy\u5E74M\u6708d\u65E5 EEE\u66DC\u65E5"
),
KOREAN(
new LocaleID[]{LocaleID.KO,LocaleID.KO_KR},
0,
1,
"yyyy\uB144 M\uC6D4 d\uC77C EEE\uC694\uC77C",
"yyyy\uB144 M\uC6D4 d\uC77C",
"yyyy/M/d",
"yyMMdd",
"yyyy\uB144 M\uC6D4 d\uC77C",
"yyyy\uB144 M\uC6D4",
"yyyy\uB144 M\uC6D4 d\uC77C",
"yyyy",
"yyyy\uB144 M\uC6D4",
"yyyy\uB144 M\uC6D4 d\uC77C a h\uC2DC m\uBD84",
"yy\uB144 M\uC6D4 d\uC77C H\uC2DC m\uBD84 s\uCD08",
"a h\uC2DC m\uBD84",
"a h\uC2DC m\uBD84 s\uCD08",
"H\uC2DC m\uBD84",
"H\uC2DC m\uBD84 S\uCD08"
),
HUNGARIAN(
new LocaleID[]{LocaleID.HU, LocaleID.HU_HU},
0, 1, 2, 3, 4, 5, 6, "yy. MMM. dd.", "\u2019yy MMM.", "MMMM \u2019yy", 10, 11, 12, "a h:mm", "a h:mm:ss", 15, 16
),
BOKMAL(
new LocaleID[]{LocaleID.NB_NO},
0, 1, 2, 3, 4, "d. MMM. yyyy", "d/m yyyy", "MMM. yy", "yyyy.mm.dd", 9, "d. MMM.", 11, 12, 13, 14, 15, 16
),
CZECH(new LocaleID[]{LocaleID.CS, LocaleID.CS_CZ}, 0, 1, 2, 3, 4, 5, 6, 7, 8, "MMMM \u2019yy", 10, 11, 12, 13, 14, 15, 16),
DANISH(new LocaleID[]{LocaleID.DA, LocaleID.DA_DK}, 0, "d. MMMM yyyy", "yy-MM-dd", "yyyy.MM.dd", 4, "MMMM yyyy", "d.M.yy", "d/M yyyy", "dd.MM.yyyy", "d.M.yyyy", "dd/MM yyyy", 11, 12, 13, 14, 15, 16 ),
DUTCH(new LocaleID[]{LocaleID.NL,LocaleID.NL_BE,LocaleID.NL_NL}, 0, 1, 2, 3, 4, 5, 6, 7, 8, "MMMM \u2019yy", 10, 11, 12, 13, 14, 15, 16),
FINISH(new LocaleID[]{LocaleID.FI, LocaleID.FI_FI}, 0, 1, 2, 3, 4, 5, 6, 7, 8, "MMMM \u2019yy", 10, 11, 12, 13, 14, 15, 16),
FRENCH_CANADIAN(new LocaleID[]{LocaleID.FR_CA}, 0, 1, 2, "yy MM dd", 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16),
GERMAN(new LocaleID[]{LocaleID.DE,LocaleID.DE_AT,LocaleID.DE_CH,LocaleID.DE_DE,LocaleID.DE_LI,LocaleID.DE_LU}, 0, 1, 2, 3, 4, "yy-MM-dd", 6, "dd. MMM. yyyy", 8, 9, 10, 11, 12, 13, 14, 15, 16),
ITALIAN(new LocaleID[]{LocaleID.IT,LocaleID.IT_IT,LocaleID.IT_CH}, 0, 1, 2, 3, 4, "d-MMM.-yy", 6, "d. MMM. yy", "MMM. \u2019yy", "MMMM \u2019yy", 10, 11, 12, 13, 14, 15, 16),
NO_MAP(new LocaleID[]{LocaleID.INVALID_O}, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)
// TODO: add others from [MS-OSHARED] chapter 2.4.4.4
;


private final LocaleID[] lcid;
private final Object[] mapping;

private static final Map<LocaleID, MapFormatException> LCID_LOOKUP =
Stream.of(values()).flatMap(m -> Stream.of(m.lcid).map(l -> new AbstractMap.SimpleEntry<>(l, m)))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

MapFormatException(LocaleID[] lcid, Object... mapping) {
this.lcid = lcid;
this.mapping = mapping;
}

public static Object mapFormatId(LocaleID lcid, int formatId) {
Object[] mapping = LCID_LOOKUP.getOrDefault(lcid, NO_MAP).mapping;
return (formatId >= 0 && formatId < mapping.length) ? mapping[formatId] : formatId;
}
}

/**
* This enum lists and describes the format indices that can be used as inputs to the algorithm. The
* descriptions given are generalized; the actual format produced can vary from the description,
* depending on the input locale.
*/
@SuppressForbidden("DateTimeFormatter::ofLocalizedDate and others will be localized in mapFormatId")
private enum MapFormatBase {
/** 0 - Base short date **/
SHORT_DATE(null, FormatStyle.MEDIUM, DateTimeFormatter::ofLocalizedDate),
/** 1 - Base long date. **/
LONG_DATE(null, FormatStyle.FULL, DateTimeFormatter::ofLocalizedDate),
/**
* 2 - Do the following to base long date:
* - Remove occurrences of "dddd".
* - Remove the comma symbol (0x002C) and space following "dddd" if present.
* - Change occurrences of "dd" to "d".
**/
LONG_DATE_WITHOUT_WEEKDAY("d. MMMM yyyy", null, null),
/**
* 3 - Do the following to base short date:
* - Change occurrences of "yyyy" to "yy".
* - Change occurrences of "yy" to "yyyy".
*/
ALTERNATE_SHORT_DATE("dd/MM/yy", null, null),
/**
* 4 - yyyy-MM-dd
*/
ISO_STANDARD_DATE("yyyy-MM-dd", null, null),
/**
* 5 - If the symbol "y" occurs before the symbol "M" occurs in the base short date, the format is
* "yy-MMM-d". Otherwise, the format is "d-MMM-yy".
*/
SHORT_DATE_WITH_ABBREVIATED_MONTH("d-MMM-yy", null, null),
/**
* 6 - If the forward slash symbol (0x002F) occurs in the base short date, the slash symbol is the
* period symbol (0x002E). Otherwise, the slash symbol is the forward slash (0x002F).
* A group is an uninterrupted sequence of qualified symbols where a qualified symbol is "d",
* "M", or "Y".
* Identify the first three groups that occur in the base short date. The format is formed by
* appending the three groups together with single slash symbols separating the groups.
*/
SHORT_DATE_WITH_SLASHES("d/M/y", null, null),
/**
* 7 - Do the following to base long date:
* - Remove occurrences of "dddd".
* - Remove the comma symbol (0x002C) and space following "dddd" if present.
* - Change occurrences of "dd" to "d".
* - For all right-to-left locales and Lao, change a sequence of any length of "M" to "MMM".
* - For all other locales, change a sequence of any length of "M" to "MMM".
* - Change occurrences of "yyyy" to "yy".
*/
ALTERNATE_SHORT_DATE_WITH_ABBREVIATED_MONTH("d. MMM yy", null, null),
/**
* 8 - For American English and Arabic, the format is "d MMMM yyyy".
* For Hebrew, the format is "d MMMM, yyyy".
* For all other locales, the format is the same as format 6 with the following additional step:
* Change occurrences of "yyyy" to "yy".
*/
ENGLISH_DATE("d MMMM yyyy", null, null),
/**
* 9 - Do the following to base long date:
* - Remove all symbols that occur before the first occurrence of either the "y" symbol or the "M" symbol.
* - Remove all "d" symbols.
* - For all locales except Lithuanian, remove all period symbols (0x002E).
* - Remove all comma symbols (0x002C).
* - Change occurrences of "yyyy" to "yy".
*/
MONTH_AND_YEAR("MMMM yy", null, null),
/**
* 10 - MMM-yy
*/
ABBREVIATED_MONTH_AND_YEAR("LLL-yy", null, null),
/**
* 11 - Base short date followed by a space, followed by base time with seconds removed.
* Seconds are removed by removing all "s" symbols and any symbol that directly precedes an
* "s" symbol that is not an "h" or "m" symbol.
*/
DATE_AND_HOUR12_TIME(null, FormatStyle.MEDIUM, (fs) -> new DateTimeFormatterBuilder().appendLocalized(FormatStyle.SHORT, null).appendLiteral(" ").appendLocalized(null, FormatStyle.SHORT).toFormatter()),
/**
* 12 - Base short date followed by a space, followed by base time.
*/
DATE_AND_HOUR12_TIME_WITH_SECONDS(null, FormatStyle.MEDIUM, (fs) -> new DateTimeFormatterBuilder().appendLocalized(FormatStyle.SHORT, null).appendLiteral(" ").appendLocalized(null, fs).toFormatter()),
/**
* 13 - For Hungarian, the format is "am/pm h:mm".
* For all other locales, the format is "h:mm am/pm".
* In both cases, replace occurrences of the colon symbol (0x003A) with the time separator.
*/
HOUR12_TIME("K:mm", null, null),
/**
* 14 - For Hungarian, the format is "am/pm h:mm:ss".
* For all other locales, the format is "h:mm:ss am/pm".
* In both cases, replace occurrences of the colon symbol (0x003A) with the time separator.
*/
HOUR12_TIME_WITH_SECONDS("K:mm:ss", null, null),
/**
* 15 - "HH" followed by the time separator, followed by "mm".
*/
HOUR24_TIME("HH:mm", null, null),
/**
* 16 - "HH" followed by the time separator, followed by "mm", followed by the time separator
* followed by "ss".
*/
HOUR24_TIME_WITH_SECONDS("HH:mm:ss", null, null),
// CHINESE1(null, null, null),
// CHINESE2(null, null, null),
// CHINESE3(null, null, null)
;


private final String datefmt;
private final FormatStyle formatStyle;
private final Function<FormatStyle,DateTimeFormatter> formatFct;

MapFormatBase(String datefmt, FormatStyle formatStyle, Function<FormatStyle,DateTimeFormatter> formatFct) {
this.formatStyle = formatStyle;
this.datefmt = datefmt;
this.formatFct = formatFct;
}

public static DateTimeFormatter mapFormatId(Locale loc, int formatId) {
MapFormatBase[] mfb = MapFormatBase.values();
if (formatId < 0 || formatId >= mfb.length) {
return DateTimeFormatter.BASIC_ISO_DATE;
}
MapFormatBase mf = mfb[formatId];
return (mf.datefmt == null)
? mf.formatFct.apply(mf.formatStyle).withLocale(loc)
: DateTimeFormatter.ofPattern(mf.datefmt, loc);
}
}

private LocaleDateFormat() {}

public static DateTimeFormatter map(LocaleID lcid, int formatID, MapFormatId mapFormatId) {
final Locale loc = Locale.forLanguageTag(lcid.getLanguageTag());
int mappedFormatId = formatID;
if (mapFormatId == MapFormatId.PPT) {
Object mappedFormat = MapFormatPPT.mapFormatId(lcid, formatID);
if (mappedFormat instanceof String) {
return DateTimeFormatter.ofPattern((String)mappedFormat,loc);
} else {
mappedFormatId = (Integer)mappedFormat;
}
}
Object mappedFormat = MapFormatException.mapFormatId(lcid, mappedFormatId);
if (mappedFormat instanceof String) {
return DateTimeFormatter.ofPattern((String)mappedFormat,loc);
} else {
return MapFormatBase.mapFormatId(loc, (Integer)mappedFormat);
}
}
}

+ 451
- 416
poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestTextRun.java
Fichier diff supprimé car celui-ci est trop grand
Voir le fichier


+ 1
- 1
poi/src/main/java/org/apache/poi/sl/draw/DrawMasterSheet.java Voir le fichier

// in XSLF, slidenumber and date shapes aren't marked as placeholders opposed to HSLF // in XSLF, slidenumber and date shapes aren't marked as placeholders opposed to HSLF
Placeholder ph = ((SimpleShape<?,?>)shape).getPlaceholder(); Placeholder ph = ((SimpleShape<?,?>)shape).getPlaceholder();
if (ph != null) { if (ph != null) {
return slide.getDisplayPlaceholder(ph);
return slide.getDisplayPlaceholder((SimpleShape<?, ?>)shape);
} }
} }
return slide.getFollowMasterGraphics(); return slide.getFollowMasterGraphics();

+ 36
- 34
poi/src/main/java/org/apache/poi/sl/draw/DrawTextParagraph.java Voir le fichier



package org.apache.poi.sl.draw; package org.apache.poi.sl.draw;


import static org.apache.logging.log4j.util.Unbox.box;

import java.awt.Dimension; import java.awt.Dimension;
import java.awt.Font; import java.awt.Font;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.text.AttributedCharacterIterator; import java.text.AttributedCharacterIterator;
import java.text.AttributedCharacterIterator.Attribute; import java.text.AttributedCharacterIterator.Attribute;
import java.text.AttributedString; import java.text.AttributedString;
import java.time.LocalDateTime;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Calendar;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import org.apache.poi.sl.usermodel.Insets2D; import org.apache.poi.sl.usermodel.Insets2D;
import org.apache.poi.sl.usermodel.PaintStyle; import org.apache.poi.sl.usermodel.PaintStyle;
import org.apache.poi.sl.usermodel.PlaceableShape; import org.apache.poi.sl.usermodel.PlaceableShape;
import org.apache.poi.sl.usermodel.ShapeContainer;
import org.apache.poi.sl.usermodel.Sheet;
import org.apache.poi.sl.usermodel.PlaceholderDetails;
import org.apache.poi.sl.usermodel.SimpleShape;
import org.apache.poi.sl.usermodel.Slide; import org.apache.poi.sl.usermodel.Slide;
import org.apache.poi.sl.usermodel.TextParagraph; import org.apache.poi.sl.usermodel.TextParagraph;
import org.apache.poi.sl.usermodel.TextParagraph.BulletStyle; import org.apache.poi.sl.usermodel.TextParagraph.BulletStyle;
import org.apache.poi.util.LocaleUtil; import org.apache.poi.util.LocaleUtil;
import org.apache.poi.util.Units; import org.apache.poi.util.Units;


import static org.apache.logging.log4j.util.Unbox.box;

public class DrawTextParagraph implements Drawable { public class DrawTextParagraph implements Drawable {
private static final Logger LOG = LogManager.getLogger(DrawTextParagraph.class); private static final Logger LOG = LogManager.getLogger(DrawTextParagraph.class);


} }


protected String getRenderableText(Graphics2D graphics, TextRun tr) { protected String getRenderableText(Graphics2D graphics, TextRun tr) {
if (tr.getFieldType() == FieldType.SLIDE_NUMBER) {
Slide<?,?> slide = (Slide<?,?>)graphics.getRenderingHint(Drawable.CURRENT_SLIDE);
return (slide == null) ? "" : Integer.toString(slide.getSlideNumber());
FieldType ft = tr.getFieldType();
if (ft == null) {
return getRenderableText(tr);
}
if (!tr.getRawText().isEmpty()) {
switch (ft) {
case SLIDE_NUMBER: {
Slide<?, ?> slide = (Slide<?, ?>) graphics.getRenderingHint(Drawable.CURRENT_SLIDE);
return (slide == null) ? "" : Integer.toString(slide.getSlideNumber());
}
case DATE_TIME: {
PlaceholderDetails pd = ((SimpleShape<?, ?>) this.getParagraphShape()).getPlaceholderDetails();
// refresh internal members
pd.getPlaceholder();
String uda = pd.getUserDate();
if (uda != null) {
return uda;
}
Calendar cal = LocaleUtil.getLocaleCalendar();
LocalDateTime now = LocalDateTime.ofInstant(cal.toInstant(), cal.getTimeZone().toZoneId());
return now.format(pd.getDateFormat());
}
}
} }
return getRenderableText(tr);
return "";
} }


@Internal @Internal
/** /**
* Helper method for paint style relative to bounds, e.g. gradient paint * Helper method for paint style relative to bounds, e.g. gradient paint
*/ */
@SuppressWarnings("rawtypes")
private PlaceableShape<?,?> getParagraphShape() { private PlaceableShape<?,?> getParagraphShape() {
return new PlaceableShape(){
@Override
public ShapeContainer<?,?> getParent() { return null; }
@Override
public Rectangle2D getAnchor() { return paragraph.getParentShape().getAnchor(); }
@Override
public void setAnchor(Rectangle2D anchor) {}
@Override
public double getRotation() { return 0; }
@Override
public void setRotation(double theta) {}
@Override
public void setFlipHorizontal(boolean flip) {}
@Override
public void setFlipVertical(boolean flip) {}
@Override
public boolean getFlipHorizontal() { return false; }
@Override
public boolean getFlipVertical() { return false; }
@Override
public Sheet<?,?> getSheet() { return paragraph.getParentShape().getSheet(); }
};
return paragraph.getParentShape();
} }


protected List<AttributedStringData> getAttributedString(Graphics2D graphics, StringBuilder text) { protected List<AttributedStringData> getAttributedString(Graphics2D graphics, StringBuilder text) {
} }


/** /**
* Processing the glyphs is done in two steps.
* <li>determine the font group - a text run can have different font groups. Depending on the chars,
* the correct font group needs to be used
* Processing the glyphs is done in two steps:
* <ul>
* <li>1. determine the font group - a text run can have different font groups.
* <li>2. Depending on the chars, the correct font group needs to be used
* </ul>
* *
* @see <a href="https://blogs.msdn.microsoft.com/officeinteroperability/2013/04/22/office-open-xml-themes-schemes-and-fonts/">Office Open XML Themes, Schemes, and Fonts</a> * @see <a href="https://blogs.msdn.microsoft.com/officeinteroperability/2013/04/22/office-open-xml-themes-schemes-and-fonts/">Office Open XML Themes, Schemes, and Fonts</a>
*/ */

+ 26
- 5
poi/src/main/java/org/apache/poi/sl/usermodel/PlaceholderDetails.java Voir le fichier

package org.apache.poi.sl.usermodel; package org.apache.poi.sl.usermodel;




import java.time.format.DateTimeFormatter;

/** /**
* Extended details about placholders * Extended details about placholders
* *
enum PlaceholderSize { enum PlaceholderSize {
quarter, half, full quarter, half, full
} }
Placeholder getPlaceholder(); Placeholder getPlaceholder();


/** /**
* @param placeholder The shape to use as placeholder or null if no placeholder should be set. * @param placeholder The shape to use as placeholder or null if no placeholder should be set.
*/ */
void setPlaceholder(Placeholder placeholder); void setPlaceholder(Placeholder placeholder);
boolean isVisible(); boolean isVisible();
void setVisible(boolean isVisible); void setVisible(boolean isVisible);
PlaceholderSize getSize(); PlaceholderSize getSize();
void setSize(PlaceholderSize size); void setSize(PlaceholderSize size);


/** /**
* @since POI 4.0.0 * @since POI 4.0.0
*/ */
void setText(String text); void setText(String text);


/**
* @return the stored / fixed user specified date
*
* @since POI 5.2.0
*/
default String getUserDate() {
return null;
}

/**
* @return Get the date format for the datetime placeholder
*
* @since POI 5.2.0
*/
default DateTimeFormatter getDateFormat() {
return DateTimeFormatter.ISO_LOCAL_DATE;
}
} }

+ 24
- 1
poi/src/main/java/org/apache/poi/sl/usermodel/Slide.java Voir le fichier



import java.util.List; import java.util.List;


import org.apache.poi.util.Removal;

@SuppressWarnings("unused") @SuppressWarnings("unused")
public interface Slide< public interface Slide<
S extends Shape<S,P>, S extends Shape<S,P>,
* @param placeholder the placeholder type * @param placeholder the placeholder type
* @return {@code true} if the placeholder should be displayed/rendered * @return {@code true} if the placeholder should be displayed/rendered
* @since POI 3.16-beta2 * @since POI 3.16-beta2
*
* @deprecated in POI 5.2.0 - use {@link #getDisplayPlaceholder(SimpleShape)}
*
*/
@Deprecated
@Removal(version = "6.0.0")
default boolean getDisplayPlaceholder(Placeholder placeholder) {
return false;
}


/**
* In XSLF, slidenumber and date shapes aren't marked as placeholders
* whereas in HSLF they are activated via a HeadersFooter configuration.
* This method is used to generalize that handling.
*
* @param placeholderRefShape the shape which references to the placeholder
* @return {@code true} if the placeholder should be displayed/rendered
* @since POI 5.2.0
*/ */
boolean getDisplayPlaceholder(Placeholder placeholder);
default boolean getDisplayPlaceholder(SimpleShape<?,?> placeholderRefShape) {
return false;
}


/** /**
* Sets the slide visibility * Sets the slide visibility

BIN
poi/src/main/java9/module-info.class Voir le fichier


BIN
test-data/slideshow/datetime.ppt Voir le fichier


Chargement…
Annuler
Enregistrer