com.adobe.xfa.layout.BoxModelContent Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aem-sdk-api Show documentation
Show all versions of aem-sdk-api Show documentation
The Adobe Experience Manager SDK
/*
* ADOBE CONFIDENTIAL
*
* Copyright 2007 Adobe Systems Incorporated All Rights Reserved.
*
* NOTICE: All information contained herein is, and remains the property of
* Adobe Systems Incorporated and its suppliers, if any. The intellectual and
* technical concepts contained herein are proprietary to Adobe Systems
* Incorporated and its suppliers and may be covered by U.S. and Foreign
* Patents, patents in process, and are protected by trade secret or copyright
* law. Dissemination of this information or reproduction of this material
* is strictly forbidden unless prior written permission is obtained from
* Adobe Systems Incorporated.
*/
package com.adobe.xfa.layout;
//import com.adobe.xfa.Bool;
import com.adobe.xfa.Element;
import com.adobe.xfa.EnumAttr;
//import com.adobe.xfa.EnumValue;
import com.adobe.xfa.AppModel;
import com.adobe.xfa.Int;
import com.adobe.xfa.Measurement;
import com.adobe.xfa.STRS;
import com.adobe.xfa.XFA;
import com.adobe.xfa.content.Content;
//import com.adobe.xfa.content.DateTimeValue;
//import com.adobe.xfa.content.DateValue;
//import com.adobe.xfa.content.DecimalValue;
import com.adobe.xfa.content.ExDataValue;
//import com.adobe.xfa.content.FloatValue;
//import com.adobe.xfa.content.IntegerValue;
//import com.adobe.xfa.content.TextValue;
//import com.adobe.xfa.content.TimeValue;
import com.adobe.xfa.template.TemplateResolver;
import com.adobe.xfa.template.containers.Draw;
import com.adobe.xfa.template.containers.Field;
import com.adobe.xfa.template.formatting.Picture;
import com.adobe.xfa.template.ui.UI;
import com.adobe.xfa.text.TextAttr;
import com.adobe.xfa.text.TextDisplay;
import com.adobe.xfa.text.TextMeasurement;
import com.adobe.xfa.text.TextPosn;
import com.adobe.xfa.text.TextPosnBase;
import com.adobe.xfa.text.TextRange;
import com.adobe.xfa.text.TextRegion;
import com.adobe.xfa.ut.CoordPair;
import com.adobe.xfa.ut.ExFull;
import com.adobe.xfa.ut.FindBugsSuppress;
import com.adobe.xfa.ut.LcLocale;
import com.adobe.xfa.ut.LcNum;
import com.adobe.xfa.ut.Margins;
import com.adobe.xfa.ut.ObjectHolder;
import com.adobe.xfa.ut.Rect;
import com.adobe.xfa.ut.ResId;
import com.adobe.xfa.ut.PictureFmt;
import com.adobe.xfa.ut.IntegerHolder;
import com.adobe.xfa.ut.StringUtils;
import com.adobe.xfa.ut.UnitSpan;
import java.util.List;
/**
* This class provides the implementation for box model formatting
* of a nodes with textual content and caption regions
*
* @exclude from published api.
*/
class BoxModelContent extends BoxModelCaptionable {
// protected AXTEDisplay m_oContentDisplay;
protected Rect m_oContentDisplayExtent = Rect.ZERO;
protected boolean m_bSplitContent;
protected TextPosn m_oStartContentPosn = new TextPosn();
protected TextPosn m_oEndContentPosn = new TextPosn();
protected TextAttr m_oAmbientTextAttr = new TextAttr();
//Is there embedded content within this box model
protected boolean m_bEmbeddedContent;
// Flag to indicate whether we need to keep the text stream from being destroyed in re-initialization
protected boolean m_bKeepContentTextStream;
// Force to grow W/H
protected boolean m_bForcedGrowableW;
protected boolean m_bForcedGrowableH;
public BoxModelContent(LayoutEnv oEnv, boolean bAllowRenderProxy) {
super(oEnv, bAllowRenderProxy);
m_bEmbeddedContent = false;
m_bSplitContent = false ;
m_bKeepContentTextStream = false;
m_bForcedGrowableW = false;
m_bForcedGrowableH = false;
}
public void clear() {
//
//Empty the box model
//
// Javaport: not yet available. TODO
// m_oContentDisplay.setNull();
m_bKeepContentTextStream = false;
m_bSplitContent = false;
super.clear();
// Javaport: not yet available. TODO
// assert (m_oContentDisplay == null);
// assert (m_oCaptionDisplay == null);
}
public void initialize(Element oNode) {
//Strategy
//Initialize the box model for a text based object (field/draw)
//1)Read initial box model settings from node, including
//-x,y,anchor
//-margins
//-border
//-caption info
//-initialize content (textual in this case)
//2)Then format the box model into subregions (content/caption) given these settings.
// This will automatically account for min/max ranges
//3)Rotate the box model, as appropriate.
//4)Record the visual extent of the box model
assert (oNode != null);
assert (oNode instanceof Field || oNode instanceof Draw);
if (! isBoxModelCompatible(oNode))
return;
checkProxyStatus(oNode);
//Read ne w/h, determine growability and if applicable the ne min/max ranges
if (! isProxy())
initWidthHeight(oNode, true);
//Read anchorPoint
initAnchorPoint(oNode);
//Read ne, content and caption margins
initMargins(oNode);
//Read border margins, content border margins
initBorder(oNode);
if (! isProxy()) {
//Create stream, apply attributes. Do not set w/h of stream. Do not create display.
//For caption, determine if caption present (w/wo text), reserved space if any.
initCaption(oNode);
//Create stream, apply attributes. Do not set w/h of stream. Do not create display.
initContent(oNode);
//Format internals based on the info so far
format(oNode);
} else {
//Create stream, apply attributes.
initContent(oNode);
if (oNode instanceof Field) {
// if this is a field, we still have to render content, so make sure the
// display is created.
createDisplay(m_oContentExtent.width(),
m_oContentExtent.width(),
m_oContentExtent.height(),
m_oContentExtent.height());
}
}
//Once formatted, perform any rotation
initRotatedContentTopLeft();
respectRotation(oNode);
//Finally, determine the visual extent.
initVisualExtent(oNode);
}
public void reinitialize(Element oNode) {
if ((! m_bKeepContentTextStream && ! m_bKeepCaptionTextStream)) {
super.reinitialize(oNode);
return;
}
else {
//Don't do clean up here. We want to keep caption and content text stream alive here.
assert (oNode != null);
initialize(oNode);
}
}
public boolean hasContent() {
return true; //By definition, always
}
public String getContentByType(String sType,
List colorTable,
List fontTable) {
assert (null != getContent());
if (null != getContent())
return getStringByType(getContent(), m_oAmbientTextAttr, sType, m_oStartContentPosn, m_oEndContentPosn, colorTable, fontTable);
else
return "";
}
public boolean enumerateContent(LayoutHandler pHandler,
CoordPair oLocalOrigin,
boolean bWrap,
boolean bTruncate /* = false */,
Rect oInvalidatedRect /* = Rect.ZERO */) {
CoordPair oNewOrigin = oLocalOrigin;
Rect oInvalid = oInvalidatedRect;
if (oInvalid.width().equals(UnitSpan.ZERO) && oInvalid.height().equals(UnitSpan.ZERO))
oInvalid = Rect.ZERO;
if (m_bSplitContent) {
oInvalid = m_oContentDisplayExtent;
oNewOrigin = new CoordPair(oNewOrigin.x(), oNewOrigin.y().subtract(m_oContentDisplayExtent.top()));
}
boolean bSplitContentFits = true;
if (m_oContentDisplayExtent.width().gt(getContentExtent().width())) {
oInvalid = oInvalid.width(getContentExtent().width(), false);
bSplitContentFits = false;
}
if (m_oContentDisplayExtent.height().gt(getContentExtent().height())) {
oInvalid = oInvalid.height(getContentExtent().height(), false);
bSplitContentFits = false;
}
boolean bFits = m_oGfxLayoutEnv.renderText(pHandler,
getContentDisplay(),
oNewOrigin,
bWrap,
bTruncate,
m_oRotationAngle,
oInvalid);
if (m_bSplitContent)
return bSplitContentFits;
return bFits;
}
public void resizeToNominal(UnitSpan oW, UnitSpan oH, Element oNode) {
//Strategy
//We're resizing the box model, ie as if we grabbed the
//corner selection handle. We are not respecting min/max settings, we are overriding them
//Watson 1183952/1419109: nominal w/h is always considered to conform to the x,y axis. In other words
//left-right is always the width, top-bottom direction is always height, even when objects are rotated.
//So if the nominal width is being modified, make sure we take into account any rotation.
if (m_bWasRotated && (m_oRotationAngle.degrees() == 90 || m_oRotationAngle.degrees() == 270)) {
//90 or 270 degree rotation means we flip and set nominal height because when we reformat it becomes the width.
setGrowableH(oW, oW);
setGrowableW(oH, oH);
}
else {
setGrowableW(oW, oW);
setGrowableH(oH, oH);
}
format(oNode);
//Once formatted, perform any rotation
initRotatedContentTopLeft();
respectRotation(oNode);
//Finally, determine the visual extent.
initVisualExtent(oNode);
}
public void resizeToNominalWidth(UnitSpan oW, Element oNode) {
//Strategy
//What are we trying to do here? Like resizeToNominal(w,h,)
//the box model is being resized, ie as if we've grabbed a sizing
//handle. So should we respect min/max? What if object is not even growable?
//For now we resize regardless of anything else.
assert (UnitSpan.ZERO.lte(oW));
//Watson 1183952: nominal w/h is always considered to conform to the x,y axis. In other words
//left-right is always the width, top-bottom direction is always height, even when objects are rotated.
//So if the nominal width is being modified, make sure we take into account any rotation.
if (m_bWasRotated) {
//90 or 270 degree rotation means we flip and set nominal height because when we reformat it becomes the width.
if (m_oRotationAngle.degrees() == 90 || m_oRotationAngle.degrees() == 270) {
setGrowableH(oW, oW);
}
else
setGrowableW(oW, oW); //turns off growableness, see comments above
}
else
setGrowableW(oW, oW); //turns off growableness, see comments above
//reformat
format(oNode);
//Once formatted, perform any rotation
initRotatedContentTopLeft();
respectRotation(oNode);
//Finally, determine the visual extent.
initVisualExtent(oNode);
}
public void resizeToContent(UnitSpan oW, UnitSpan oH, Element oNode) {
//Should not be called for this object
assert (false);
}
public boolean splitImpl(UnitSpan oVSplit,
BoxModelLayout pNewBM,
Element oNode) {
//Note : Changes to this function in terms of where the split point lands should also be reflected in ::calculateSplitPoint()
//If this was rotated splitting is not possible
if (m_bWasRotated)
return false;
boolean bSplit = false;
// Does split pt cut of the box model?
if (oVSplit.gt(UnitSpan.ZERO) && oVSplit.lt(getHeight())) {
//Does split pt cut the content and not top/bottom margins or top/bottom caption?
if (oVSplit.gte(m_oContentExtent.top()) && oVSplit.lte(m_oContentExtent.bottom())) {
if (! m_bSplitContent) {
m_oContentDisplayExtent = m_oContentDisplayExtent.width(getContentExtent().width(), false);
m_oContentDisplayExtent = m_oContentDisplayExtent.height(getContentExtent().height(), false);
if (m_bHasCaption) {
m_oCaptionDisplayExtent = m_oCaptionDisplayExtent.width(getCaptionExtent().width(), false);
m_oCaptionDisplayExtent = m_oCaptionDisplayExtent.height(getCaptionExtent().height(), false);
}
}
assert (null != getContentDisplay());
assert (null != getCaptionDisplay() || ! m_bHasCaption);
UnitSpan oContentDisplayOffset = m_oContentDisplayExtent.top();
assert (UnitSpan.ZERO.lte((oVSplit.subtract(m_oContentExtent.top()).add(oContentDisplayOffset))));
TextPosn oPrevEndContentPosn = m_oEndContentPosn;
boolean bEndsInNewLine = false;
UnitSpan oContentSplit = UnitSpan.ZERO;
// Javaport: not available. TODO
// oContentSplit = getContentDisplay().split(oVSplit.subtract(m_oContentExtent.top()).add(oContentDisplayOffset), m_oEndContentPosn, bEndsInNewLine);
UnitSpan oContentDisplayBottom = m_oContentDisplayExtent.bottom();
// watson 1096277
// If the split point to close to the bottom of the contentExtent (there
// should be a bottom margin otherwise we wondn't be this far in this method)
// we will split one line above. The reason is because we don't want to end up
// with a box model that doesn't have any content (or too little content e.i
// not even big enough to see a full line).
Rect oLineRect = Rect.ZERO;
// Javaport: not available. TODO
// m_oEndContentPosn.caretPos(oLineRect, true);
if (oLineRect.height().gt((oContentDisplayBottom.subtract(oContentSplit)))) {
// try the split again... this time one line up.
// Javaport: not available. TODO
// oContentSplit = getContentDisplay().split(oVSplit.subtract(m_oContentExtent.top()).add(oContentDisplayOffset.subtract(oLineRect.height())), m_oEndContentPosn, bEndsInNewLine);
assert (oContentSplit.lt(oContentDisplayBottom));
}
// if we try to split to close to the beginning of the contentExtext... don't
// cut a boxModel when one of the piece won't have any content or very little
// content (i.e less than one line)
// Javaport: not available. TODO
// m_oEndContentPosn.caretPos(oLineRect, true);
if (oLineRect.height().gt(oContentSplit.subtract(m_oContentDisplayExtent.top()))) {
// reset the member variables that we changed
if (! m_bSplitContent) {
m_oContentDisplayExtent = Rect.ZERO;
if (m_bHasCaption)
m_oCaptionDisplayExtent = Rect.ZERO;
}
m_oEndContentPosn = oPrevEndContentPosn;
return false;
}
Rect oOldNE = getNominalExtent();
//Does split pt cut the content display?
if (oContentSplit.gte(oContentDisplayOffset) && oContentSplit.lte(oContentDisplayBottom)) {
Rect oNewContentDisplayExtent = m_oContentDisplayExtent;
oNewContentDisplayExtent = oNewContentDisplayExtent.topBottom(oContentSplit, oContentDisplayBottom);
m_oContentDisplayExtent = m_oContentDisplayExtent.topBottom(oContentDisplayOffset, oContentSplit);
//Create 2nd box model
pNewBM = new BoxModelContent(m_oGfxLayoutEnv, false);
BoxModelContent pBMContent = (BoxModelContent) pNewBM;
pBMContent.m_bSplitContent = true;
pBMContent.m_oStartContentPosn = m_oEndContentPosn;
pBMContent.m_oEndContentPosn = oPrevEndContentPosn;
if (bEndsInNewLine)
m_oEndContentPosn.prevUserPosn(); // don't include trailing newline in first half
m_bSplitContent = true;
// If Caption is left or right . split caption
// If Caption is top . no caption on 2nd box model (nothing needs to be set)
// If Caption is bottom . no caption on the 1st box model (caption on the 2nd box model)
// If no Caption . nothing needs to be done
Rect oNewCaptionDisplayExtent = m_oCaptionDisplayExtent;
if (m_bHasCaption) {
assert (m_eCaptionPlacement != EnumAttr.PLACEMENT_INLINE);
if (m_eCaptionPlacement == EnumAttr.PLACEMENT_LEFT ||
m_eCaptionPlacement == EnumAttr.PLACEMENT_RIGHT ||
m_eCaptionPlacement == EnumAttr.PLACEMENT_BOTTOM) {
pBMContent.m_bHasCaption = true;
pBMContent.m_bReserveCaptionSpace = m_bReserveCaptionSpace;
pBMContent.m_eCaptionPresence = m_eCaptionPresence;
pBMContent.m_eCaptionPlacement = m_eCaptionPlacement;
pBMContent.m_oReserveCaptionSpace = m_oReserveCaptionSpace;
if (m_eCaptionPlacement == EnumAttr.PLACEMENT_BOTTOM) {
m_bHasCaption = false;
}
else {
UnitSpan oCaptionDisplayOffset = m_oCaptionDisplayExtent.top();
assert (UnitSpan.ZERO.lte(oVSplit.subtract(m_oCaptionExtent.top()).add(oCaptionDisplayOffset)));
TextPosn oPrevEndCaptionPosn = new TextPosn(m_oEndCaptionPosn);
bEndsInNewLine = false;
UnitSpan oCaptionSplit = UnitSpan.ZERO;
// Javaport: not available. TODO
// oCaptionSplit = getCaptionDisplay().split(oVSplit.subtract(m_oCaptionExtent.top()).add(oCaptionDisplayOffset), m_oEndCaptionPosn, bEndsInNewLine);
UnitSpan oCaptionDisplayBottom = m_oCaptionDisplayExtent.bottom();
oNewCaptionDisplayExtent = oNewCaptionDisplayExtent.topBottom(oCaptionSplit, oCaptionDisplayBottom);
m_oCaptionDisplayExtent = m_oCaptionDisplayExtent.topBottom(oCaptionDisplayOffset, oCaptionSplit);
pBMContent.m_bSplitCaption = true;
pBMContent.m_oStartCaptionPosn = m_oEndCaptionPosn;
pBMContent.m_oEndCaptionPosn = oPrevEndCaptionPosn;
if (bEndsInNewLine)
m_oEndCaptionPosn.prevUserPosn(); // don't include trailing newline in first half
m_bSplitCaption = true;
}
}
}
pBMContent.initializeSplit(oNode, /*m_oContentDisplay, */ oNewContentDisplayExtent, /* m_oCaptionDisplay, */ oNewCaptionDisplayExtent);
pBMContent.disableTopMargin();
pBMContent.disableContentTopMargin();
if (m_bSplitCaption) {
pBMContent.disableCaptionTopMargin();
disableCaptionBottomMargin();
}
//This box model was split. It is no longer growable
//nor does it have it's original a min/max
//Shrink wrap this box model around content
disableBottomMargin();
disableContentBottomMargin();
boolean bWasHGrowable = hasGrowableH();
setGrowableH(UnitSpan.ZERO, new UnitSpan(UnitSpan.INCHES_72K, -1));
format(oNode);
// get the new height
UnitSpan oNewNEHeight = getHeight();
// reset to non-growable if it wasn't to begin with
if (! bWasHGrowable)
setGrowableH(oNewNEHeight, oNewNEHeight);
//growable or not we don't want to take more space that we were
//allocated... so this second box model must not be bigger than the delta
//between the original height and the new height.
//Shrink 2nd box model piece by the difference in nominal height
UnitSpan oNEDelta = oOldNE.height().subtract(oNewNEHeight);
pNewBM.resizeToNominal(oOldNE.width(), oNEDelta, oNode);
// make sure that this new box model knows that it
// is part of a growable field
if (bWasHGrowable)
pBMContent.setGrowableH(UnitSpan.ZERO, new UnitSpan(UnitSpan.INCHES_72K, -1));
//watson 1820449 - carry over the forced growable setting
pBMContent.setForcedGrowableH(hasForcedGrowableH());
pBMContent.setForcedGrowableW(hasForcedGrowableW());
bSplit = true;
}
}
}
return bSplit;
}
public boolean hasSplit() {
return m_bSplitContent || m_bSplitCaption;
}
public boolean isFontSubstituted() {
boolean bIsFontSubstituted = false;
TextDisplay pDisp = getCaptionDisplay();
if (pDisp != null)
bIsFontSubstituted = pDisp.hasFontSubstitution();
if (! bIsFontSubstituted) {
pDisp = getContentDisplay();
if (pDisp != null)
bIsFontSubstituted = pDisp.hasFontSubstitution();
}
return bIsFontSubstituted;
}
public boolean hasGrowableW() {
return super.hasGrowableW() || m_bForcedGrowableW;
}
public boolean hasGrowableH() {
return super.hasGrowableH() || m_bForcedGrowableH;
}
public void setForcedGrowableW(boolean bForcedGrowableW /* = true */) {
m_bForcedGrowableW = bForcedGrowableW;
}
public void setForcedGrowableH(boolean bForcedGrowableH /* = true */) {
m_bForcedGrowableH = bForcedGrowableH;
}
public boolean hasForcedGrowableW() {
return m_bForcedGrowableW;
}
public boolean hasForcedGrowableH() {
return m_bForcedGrowableH;
}
/**
* Return the text range associated with the content of this box model.
* @param oStartPosn the start position within the text stream.
* @param oEndPosn the end position within the text stream.
* @return true if the box model has been split, false otherwise.
*/
// JavaPort: Todo: oStartPosn and oEndPosn are passed by reference in C++, but by value here.
public boolean getContentRange(ObjectHolder oStartPosn, ObjectHolder oEndPosn) {
oStartPosn.value = m_oStartContentPosn;
oEndPosn.value = m_oEndContentPosn;
return hasSplit();
}
/**
* Retrieve the max chars attribute of the text node.
*/
public boolean getComb(Element oNode, Element oCurrentUI, IntegerHolder nNumCells) {
if (oNode == null)
return false;
boolean bIsComb = false;
nNumCells.value = 0;
Element oCombNode = oCurrentUI.peekElement(XFA.COMBTAG, false, 0);
if (oCombNode != null) {
bIsComb = true;
Int oCells = (Int) oCombNode.getAttribute(XFA.NUMBEROFCELLSTAG);
nNumCells.value = oCells.getValue();
if (nNumCells.value < 1) {
nNumCells.value = 1; // minimum of 1 cell for combs
Element oValueNode = oNode.peekElement(XFA.VALUETAG, false, 0);
if (oValueNode != null) {
Element oTextNode = oValueNode.peekElement(XFA.TEXTTAG, false, 0);
if (oTextNode != null) {
Int oMaxChars = (Int) oTextNode.getAttribute(XFA.MAXCHARSTAG);
if (oMaxChars != null) {
nNumCells.value = oMaxChars.getValue();
if (nNumCells.value < 1) nNumCells.value = 1;
}
}
}
}
}
return bIsComb;
}
public boolean getKeepContentTextStreamFlag() {
return m_bKeepContentTextStream;
}
public void setKeepContentTextStreamFlag(boolean bKeepTextStream) {
m_bKeepContentTextStream = bKeepTextStream;
}
//interface for box model text editing
/**
* Text editing interface
* Update box model based on current stream state(s)
*/
public void update(Element oNode) {
//
//Resize to the current content
//
assert (! m_bWasRotated);
//
//If! growable, it never changes
//
if (! m_bGrowableW && ! m_bGrowableH
&& ! m_bForcedGrowableW && ! m_bForcedGrowableH)
return;
//
//Dont' support editing of rotated objects at this time
//
if (m_bWasRotated)
return;
//
//format internal subregions
//
format(oNode);
initVisualExtent(oNode);
}
public TextDisplay getContentDisplay() {
// Javaport: not yet available. TODO
// if (m_oContentDisplay != null)
// return m_oContentDisplay.getDisplay();
throw new ExFull(ResId.UNSUPPORTED_OPERATION, "BoxModelContent#getContentDisplay");
}
public TextRegion getContent() {
// Javaport: not yet available. TODO
// if (m_oContentDisplay != null)
// return m_oContentDisplay.getRegion();
return null;
}
public TextRange getContentRangeAttrs() {
// Javaport: not yet available. TODO
// assert (m_oContentDisplay != null);
// return m_oContentDisplay.getRangeAttr();
return null;
}
//interface used for splitting
//returns acceptable split point <= suggested split point.
public UnitSpan calculateSplitPoint(UnitSpan oSuggestedVSplit) {
//Strategy
//Given a suggested split point from top of nominal extent, calculate an acceptable
//split point that is less than or equal to oSuggestSplit where this object can actually be split.
//Does split point event cut through the box model?
if (oSuggestedVSplit.gt(UnitSpan.ZERO) && oSuggestedVSplit.lte(getHeight())) {
//Does split pt cut through top margin or top caption?
if (oSuggestedVSplit.lt(m_oContentExtent.top())) {
return UnitSpan.ZERO;
}
//Does split pt cut through bottom margin or bottom caption?
if (oSuggestedVSplit.gt(m_oContentExtent.bottom())) {
return m_oContentExtent.bottom();
}
//Otherwise defer to the text display to identify a good split position
if (null != getContentDisplay()) {
//Of course need to take into account our display offset into the stream (aka any previous split piece(s))
//UnitSpan oSuggestedTextContentSplitPt = m_oContentDisplayExtent.top().add(oSuggestedVSplit).subtract(m_oContentExtent.top());
UnitSpan oTextContentSplitPt = UnitSpan.ZERO;
// Javaport: not available. TODO
// oTextContentSplitPt = getContentDisplay().split(oSuggestedTextContentSplitPt);
// watson 1096277 (and thus also fixes 1222364)
// If the split point to close to the bottom of the contentExtent (there
// should be a bottom margin otherwise we wondn't be this far in this method)
// we will split one line above. The reason is because we don't want to end up
// with a box model that doesn't have any content (or too little content e.i
// not even big enough to see a full line).
if (! m_bSplitContent) {
m_oContentDisplayExtent = m_oContentDisplayExtent.width(getContentExtent().width(), false);
m_oContentDisplayExtent = m_oContentDisplayExtent.height(getContentExtent().height(), false);
}
Rect oLineRect = Rect.ZERO;
// Javaport: not available. TODO
// m_oEndContentPosn.caretPos(oLineRect, true);
if (oLineRect.height().gt((m_oContentDisplayExtent.bottom().subtract(oTextContentSplitPt)))) {
// try the split again... this time one line up.
throw new ExFull(ResId.UNSUPPORTED_OPERATION, "BoxModelContent#calculateSplitPoint");
// Javaport: not available. TODO
// oTextContentSplitPt = getContentDisplay().split(oTextContentSplitPt.subtract(oLineRect.height()));
}
//If it's in the first line, then give up. There is no split point.
// Javaport: not available. TODO
// m_oStartContentPosn.caretPos(oLineRect, true);
if (oLineRect.bottom().gt(m_oContentDisplayExtent.top().add(oTextContentSplitPt)))
return UnitSpan.ZERO;
if (UnitSpan.ZERO.gt(oTextContentSplitPt))
return UnitSpan.ZERO;
return oTextContentSplitPt.add(m_oContentExtent.top()).subtract(m_oContentDisplayExtent.top());
}
}
return UnitSpan.ZERO;
}
//internal formatting functions
// JavaPort: TODO. oNode is never referenced?
@FindBugsSuppress(pattern="DLS_DEAD_LOCAL_STORE") // oConStreamMinH - false positive
protected void format(Element oNode) {
//Format the box model into subtract regions based on current settings.
//Here we go (try to keep up)
UnitSpan oCapSpaceW = UnitSpan.ZERO;
UnitSpan oCapSpaceH = UnitSpan.ZERO;
UnitSpan oCapStreamMinH = UnitSpan.ZERO;
UnitSpan oCapStreamMaxH = UnitSpan.ZERO;
UnitSpan oCapStreamMinW = UnitSpan.ZERO;
UnitSpan oCapStreamMaxW = UnitSpan.ZERO;
UnitSpan oConStreamMinH = UnitSpan.ZERO;
UnitSpan oConStreamMaxH = UnitSpan.ZERO;
UnitSpan oConStreamMinW = UnitSpan.ZERO;
UnitSpan oConStreamMaxW = UnitSpan.ZERO;
//sizes of box model subtract regions. Not necessarily the same as stream sizes
UnitSpan oCaptionExtentW = UnitSpan.ZERO;
UnitSpan oCaptionExtentH = UnitSpan.ZERO;
UnitSpan oContentExtentW = UnitSpan.ZERO;
UnitSpan oContentExtentH = UnitSpan.ZERO;
//Margins
Margins oCapMargins = getCaptionExtentMargins();
Margins oConMargins = getContentExtentMargins();
Margins oNEMargins = getNominalExtentMargins();
UnitSpan oCapLeftRightMargins = oCapMargins.marginLeft().add(oCapMargins.marginRight());
UnitSpan oCapTopBottomMargins = oCapMargins.marginTop().add(oCapMargins.marginBottom());
UnitSpan oConLeftRightMargins = oConMargins.marginLeft().add(oConMargins.marginRight());
UnitSpan oConTopBottomMargins = oConMargins.marginTop().add(oConMargins.marginBottom());
UnitSpan oNELeftRightMargins = oNEMargins.marginLeft().add(oNEMargins.marginRight());
UnitSpan oNETopBottomMargins = oNEMargins.marginTop().add(oNEMargins.marginBottom());
if (m_bHasCaption) { //should be true if caption space of any kind, even if no text
assert (EnumAttr.PLACEMENT_INLINE != m_eCaptionPlacement);
if (EnumAttr.PLACEMENT_LEFT == m_eCaptionPlacement ||
EnumAttr.PLACEMENT_RIGHT == m_eCaptionPlacement) {
oCapStreamMinH = m_oMinH.subtract(oNETopBottomMargins).subtract(oCapTopBottomMargins);
if (m_bGrowableH && m_bInfiniteMaxH)
oCapStreamMaxH = new UnitSpan(UnitSpan.INCHES_72K, -1);
else
oCapStreamMaxH = m_oMaxH.subtract(oNETopBottomMargins).subtract(oCapTopBottomMargins);
if (m_bReserveCaptionSpace) {
oCapStreamMinW = m_oReserveCaptionSpace.subtract(oCapLeftRightMargins);
oCapStreamMaxW = oCapStreamMinW;
}
else {
oCapStreamMinW = m_oMinW.subtract(oNELeftRightMargins).subtract(oCapLeftRightMargins);
if (m_bGrowableW && m_bInfiniteMaxW)
oCapStreamMaxW = new UnitSpan(UnitSpan.INCHES_72K, -1);
else
oCapStreamMaxW = m_oMaxW.subtract(oNELeftRightMargins).subtract(oCapLeftRightMargins);
}
}
else if (EnumAttr.PLACEMENT_TOP == m_eCaptionPlacement ||
EnumAttr.PLACEMENT_BOTTOM == m_eCaptionPlacement) {
oCapStreamMinW = m_oMinW.subtract(oNELeftRightMargins).subtract(oCapLeftRightMargins);
if (m_bGrowableW && m_bInfiniteMaxW)
oCapStreamMaxW = new UnitSpan(UnitSpan.INCHES_72K, -1);
else
oCapStreamMaxW = m_oMaxW.subtract(oNELeftRightMargins).subtract(oCapLeftRightMargins);
if (m_bReserveCaptionSpace) {
oCapStreamMinH = m_oReserveCaptionSpace.subtract(oCapTopBottomMargins);
oCapStreamMaxH = oCapStreamMinH;
}
else {
oCapStreamMinH = m_oMinH.subtract(oNETopBottomMargins.subtract(oCapTopBottomMargins));
if (m_bGrowableH && m_bInfiniteMaxH)
oCapStreamMaxH = new UnitSpan(UnitSpan.INCHES_72K, -1);
else
oCapStreamMaxH = m_oMaxH.subtract(oNETopBottomMargins).subtract(oCapTopBottomMargins);
}
}
if (oCapStreamMinW.lt(UnitSpan.ZERO))
oCapStreamMinW = UnitSpan.ZERO;
if (oCapStreamMinH.lt(UnitSpan.ZERO))
oCapStreamMinH = UnitSpan.ZERO;
//Set caption stream sizes, then create display. This is more efficient
//because the display would do formatting more than once.
if (! m_bSplitCaption) {
// Javaport: TODO
// getCaption().setMinWidth(oCapStreamMinW);
// getCaption().setMaxWidth(oCapStreamMaxW);
// getCaption().setMinHeight(oCapStreamMinH);
// getCaption().setMaxHeight(oCapStreamMaxH);
}
// if (null == getCaptionDisplay())
// m_oCaptionDisplay.createDisplay(null, m_oGfxLayoutEnv);
//
//Unless a reserved value is specified for caption, it will automaticaly take
//all the room it needs
//Calculate caption extent w/h.
//
if (EnumAttr.PLACEMENT_LEFT == m_eCaptionPlacement ||
EnumAttr.PLACEMENT_RIGHT == m_eCaptionPlacement) {
// Javaport: TODO
// Rect rcRuntimeExtent;
// if (m_bSplitCaption)
// rcRuntimeExtent = m_oCaptionDisplayExtent;
// else
// rcRuntimeExtent = getCaptionDisplay().runtimeExtent();
//
// oCaptionExtentW = rcRuntimeExtent.width();
// oCaptionExtentH = rcRuntimeExtent.height();
//
if (m_bReserveCaptionSpace) {
assert (oCapStreamMinW.equals(oCapStreamMaxW));
oCaptionExtentW = oCapStreamMaxW;
}
//Clamp captions heights to any fixed height
if (! m_bGrowableH) {
oCaptionExtentH = oCapStreamMaxH;
}
oCapSpaceW = oCaptionExtentW.add(oCapLeftRightMargins);
oCapSpaceH = UnitSpan.ZERO;
}
else if (EnumAttr.PLACEMENT_TOP == m_eCaptionPlacement ||
EnumAttr.PLACEMENT_BOTTOM == m_eCaptionPlacement) {
// Javaport: TODO
// Rect rcRuntimeExtent;
// if (m_bSplitCaption)
// rcRuntimeExtent = m_oCaptionDisplayExtent;
// else
// rcRuntimeExtent = getCaptionDisplay().runtimeExtent();
// oCaptionExtentW = rcRuntimeExtent.width();
// oCaptionExtentH = rcRuntimeExtent.height();
if (m_bReserveCaptionSpace) {
assert (oCapStreamMinH.equals(oCapStreamMaxH));
oCaptionExtentH = oCapStreamMaxH;
}
else {
// Javaport: TODO. For now, just throw if sized-to-fit.
throw new ExFull(ResId.UNSUPPORTED_OPERATION, "BoxModelContent#format");
}
//Clamp captions width to any fixed width
if (! m_bGrowableW) {
oCaptionExtentW = oCapStreamMaxW;
}
oCapSpaceH = oCaptionExtentH.add(oCapTopBottomMargins);
oCapSpaceW = UnitSpan.ZERO;
}
}//endif caption
//Figure out what range of room is left for content
oConStreamMinW = m_oMinW.subtract(oNELeftRightMargins).subtract(oConLeftRightMargins).subtract(oCapSpaceW);
oConStreamMaxW = m_oMaxW.subtract(oNELeftRightMargins).subtract(oConLeftRightMargins).subtract(oCapSpaceW);
oConStreamMinH = m_oMinH.subtract(oNETopBottomMargins).subtract(oConTopBottomMargins).subtract(oCapSpaceH);
oConStreamMaxH = m_oMaxH.subtract(oNETopBottomMargins).subtract(oConTopBottomMargins).subtract(oCapSpaceH);
//Protect against bad ranges
if (oConStreamMinW.lt(UnitSpan.ZERO))
oConStreamMinW = UnitSpan.ZERO;
if (oConStreamMinH.lt(UnitSpan.ZERO))
oConStreamMinH = UnitSpan.ZERO;
if ((m_bGrowableW && m_bInfiniteMaxW) || m_bForcedGrowableW)
oConStreamMaxW = new UnitSpan(UnitSpan.INCHES_72K, -1);
else {
if (oConStreamMaxW.lt(UnitSpan.ZERO))
oConStreamMaxW = UnitSpan.ZERO;
}
if ((m_bGrowableH && m_bInfiniteMaxH) || m_bForcedGrowableH)
oConStreamMaxH = new UnitSpan(UnitSpan.INCHES_72K, -1);
else {
if (oConStreamMaxH.lt(UnitSpan.ZERO))
oConStreamMaxH = UnitSpan.ZERO;
}
createDisplay(oConStreamMinW, oConStreamMaxW, oConStreamMinH, oConStreamMaxH);
//Now determine content extent. This is based on whether growable or not, ie difference
//between runtime width vs fixed width
if (m_bGrowableW || m_bForcedGrowableW) {
Rect oRuntimeExtent;
if (m_bSplitContent)
oRuntimeExtent = m_oContentDisplayExtent;
else
oRuntimeExtent = getContentDisplay().runtimeExtent();
oContentExtentW = oRuntimeExtent.right();
if (oContentExtentW.lt(oConStreamMinW))
oContentExtentW = oConStreamMinW;
else if (! m_bForcedGrowableW && oContentExtentW.gt(oConStreamMaxW) && ! m_bInfiniteMaxW) // If we force to grow, don't set theraint
oContentExtentW = oConStreamMaxW;
assert (! oContentExtentW.gt(oConStreamMaxW) || m_bInfiniteMaxW || m_bForcedGrowableW);
}
else {
assert (oConStreamMinW.equals(oConStreamMaxW));
oContentExtentW = oConStreamMaxW;
}
if (m_bGrowableH || m_bForcedGrowableH) {
Rect oRuntimeExtent;
if (m_bSplitContent)
oRuntimeExtent = m_oContentDisplayExtent;
else
oRuntimeExtent = getContentDisplay().runtimeExtent();
oContentExtentH = oRuntimeExtent.height();
if (oContentExtentH.lt(oConStreamMinH))
oContentExtentH = oConStreamMinH;
else if (! m_bForcedGrowableH && oContentExtentH.gt(oConStreamMaxH) && ! m_bInfiniteMaxH) // If we force to grow, don't set theraint
oContentExtentH = oConStreamMaxH;
assert (! oContentExtentH.gt(oConStreamMaxH) || m_bInfiniteMaxH || m_bForcedGrowableH);
}
else {
assert (oConStreamMinH.equals(oConStreamMaxH));
oContentExtentH = oConStreamMaxH;
}
//All that's left is to set m_oNE, m_oContentExtent and m_oCaptionExtent
if (m_bHasCaption) {
if (EnumAttr.PLACEMENT_LEFT == m_eCaptionPlacement) {
//The determinant height is content+con margins.
m_oNE = m_oNE.width(oNELeftRightMargins.add(oCapLeftRightMargins).add(oCaptionExtentW).add(oConLeftRightMargins).add(oContentExtentW), false);
if (oContentExtentH.add(oConTopBottomMargins).gt(oCaptionExtentH.add(oCapTopBottomMargins))) {
m_oNE = m_oNE.height(oNETopBottomMargins.add(oContentExtentH).add(oConTopBottomMargins), false);
oCaptionExtentH = oContentExtentH.add(oConTopBottomMargins).subtract(oCapTopBottomMargins);
}
else {
//If this is a split piece of content and the content is smaller, it takes precedence.
//So shrink the caption to match. Otherwise we get case where field
//grows to accomodate caption, which is likely empty space anyway.
//If not split then the caption does indeed take precedence
if (m_bSplitCaption) {
m_oNE = m_oNE.height(oNETopBottomMargins.add(oContentExtentH).add(oConTopBottomMargins), false);
oCaptionExtentH = m_oNE.height().subtract(oCapTopBottomMargins).add(oNETopBottomMargins);
m_oCaptionDisplayExtent = m_oCaptionDisplayExtent.height(oCaptionExtentH, false);
}
else {
m_oNE = m_oNE.height(oNETopBottomMargins.add(oCaptionExtentH).add(oCapTopBottomMargins), false);
oContentExtentH = oCaptionExtentH.add(oCapTopBottomMargins).subtract(oConTopBottomMargins);
}
}
m_oCaptionExtent = m_oCaptionExtent.leftWidth(oNEMargins.marginLeft().add(oCapMargins.marginLeft()),
oCaptionExtentW);
m_oCaptionExtent = m_oCaptionExtent.topHeight(oNEMargins.marginTop().add(oCapMargins.marginTop()),
oCaptionExtentH);
m_oContentExtent = m_oContentExtent.leftWidth(oNEMargins.marginLeft().add(oCapLeftRightMargins).add(oCaptionExtentW).add(oConMargins.marginLeft()),
oContentExtentW);
m_oContentExtent = m_oContentExtent.topHeight(oNEMargins.marginTop().add(oConMargins.marginTop()),
oContentExtentH);
}
else if (EnumAttr.PLACEMENT_RIGHT == m_eCaptionPlacement) {
//The determinant height is content+con margins.
m_oNE = m_oNE.width(oNELeftRightMargins.add(oCapLeftRightMargins).add(oCaptionExtentW).add(oConLeftRightMargins).add(oContentExtentW), false);
if (oContentExtentH.add(oConTopBottomMargins).gt(oCaptionExtentH.add(oCapTopBottomMargins))) {
m_oNE = m_oNE.height(oNETopBottomMargins.add(oContentExtentH).add(oConTopBottomMargins), false);
oCaptionExtentH = oContentExtentH.add(oConTopBottomMargins).subtract(oCapTopBottomMargins);
}
else {
//If this is a split piece of content and the content is smaller, it takes precedence.
//So shrink the caption to match. Otherwise we get case where field
//grows to accomodate caption, which is likely empty space anyway.
//If not split then the caption does indeed take precedence
if (m_bSplitCaption) {
m_oNE = m_oNE.height(oNETopBottomMargins.add(oContentExtentH).add(oConTopBottomMargins), false);
oCaptionExtentH = m_oNE.height().subtract(oCapTopBottomMargins.add(oNETopBottomMargins));
m_oCaptionDisplayExtent = m_oCaptionDisplayExtent.height(oCaptionExtentH, false);
}
else {
m_oNE = m_oNE.height(oNETopBottomMargins.add(oCaptionExtentH).add(oCapTopBottomMargins), false);
oContentExtentH = oCaptionExtentH.add(oCapTopBottomMargins).subtract(oConTopBottomMargins);
}
}
m_oCaptionExtent = m_oCaptionExtent.leftWidth(oNEMargins.marginLeft().add(oConLeftRightMargins).add(oContentExtentW).add(oCapMargins.marginLeft()),
oCaptionExtentW);
m_oCaptionExtent = m_oCaptionExtent.topHeight(oNEMargins.marginTop().add(oCapMargins.marginTop()),
oCaptionExtentH);
m_oContentExtent = m_oContentExtent.leftWidth(oNEMargins.marginLeft().add(oConMargins.marginLeft()),
oContentExtentW);
m_oContentExtent = m_oContentExtent.topHeight(oNEMargins.marginTop().add(oConMargins.marginTop()),
oContentExtentH);
}
else if (EnumAttr.PLACEMENT_TOP == m_eCaptionPlacement) {
//What's the determinant width? content+con margins or caption+cap margins?
//Expand the smaller to fit.
m_oNE = m_oNE.height(oNETopBottomMargins.add(oCapTopBottomMargins).add(oCaptionExtentH).add(oConTopBottomMargins).add(oContentExtentH), false);
if (oContentExtentW.add(oConLeftRightMargins).gt(oCaptionExtentW.add(oCapLeftRightMargins))) {
m_oNE = m_oNE.width(oNELeftRightMargins.add(oContentExtentW).add(oConLeftRightMargins), false);
oCaptionExtentW = oContentExtentW.add(oConLeftRightMargins).subtract(oCapLeftRightMargins);
}
else {
m_oNE = m_oNE.width(oNELeftRightMargins.add(oCaptionExtentW).add(oCapLeftRightMargins), false);
oContentExtentW = oCaptionExtentW.add(oCapLeftRightMargins).subtract(oConLeftRightMargins);
}
m_oCaptionExtent = m_oCaptionExtent.leftWidth(oNEMargins.marginLeft().add(oCapMargins.marginLeft()),
oCaptionExtentW);
m_oCaptionExtent = m_oCaptionExtent.topHeight(oNEMargins.marginTop().add(oCapMargins.marginTop()),
oCaptionExtentH);
m_oContentExtent = m_oContentExtent.leftWidth(oNEMargins.marginLeft().add(oConMargins.marginLeft()),
oContentExtentW);
m_oContentExtent = m_oContentExtent.topHeight(oNEMargins.marginTop().add(oCapTopBottomMargins).add(oCaptionExtentH).add(oConMargins.marginTop()),
oContentExtentH);
}
else if (EnumAttr.PLACEMENT_BOTTOM == m_eCaptionPlacement) {
//What's the determinant width? content+con margins or caption+cap margins?
//Expand the smaller to fit.
m_oNE = m_oNE.height(oNETopBottomMargins.add(oCapTopBottomMargins).add(oCaptionExtentH).add(oConTopBottomMargins).add(oContentExtentH), false);
if (oContentExtentW.add(oConLeftRightMargins).gt(oCaptionExtentW.add(oCapLeftRightMargins))) {
m_oNE = m_oNE.width(oNELeftRightMargins.add(oContentExtentW).add(oConLeftRightMargins), false);
oCaptionExtentW = oContentExtentW.add(oConLeftRightMargins).subtract(oCapLeftRightMargins);
}
else {
m_oNE = m_oNE.width(oNELeftRightMargins.add(oCaptionExtentW).add(oCapLeftRightMargins), false);
oContentExtentW = oCaptionExtentW.add(oCapLeftRightMargins).subtract(oConLeftRightMargins);
}
m_oCaptionExtent = m_oCaptionExtent.leftWidth(oNEMargins.marginLeft().add(oCapMargins.marginLeft()),
oCaptionExtentW);
m_oCaptionExtent = m_oCaptionExtent.topHeight(oNEMargins.marginTop().add(oConTopBottomMargins).add(oContentExtentH).add(oCapMargins.marginTop()),
oCaptionExtentH);
m_oContentExtent = m_oContentExtent.leftWidth(oNEMargins.marginLeft().add(oConMargins.marginLeft()),
oContentExtentW);
m_oContentExtent = m_oContentExtent.topHeight(oNEMargins.marginTop().add(oConMargins.marginTop()),
oContentExtentH);
}
else
assert (false); //inline, m_bHasCaption should be false
if (! m_bSplitCaption) {
// Javaport: TODO
// getCaption().setJustifyExtents(m_oCaptionExtent.width(), m_oCaptionExtent.height());
}
if (! m_bSplitContent) {
// Javaport: TODO
// getContent().setJustifyExtents(m_oContentExtent.width(), m_oContentExtent.height());
}
}
else {
m_oCaptionExtent = Rect.ZERO;
m_oContentExtent = m_oContentExtent.leftWidth(oNEMargins.marginLeft().add(oConMargins.marginLeft()), //left
oContentExtentW);//width
m_oContentExtent = m_oContentExtent.topHeight(oNEMargins.marginTop().add(oConMargins.marginTop()), //top
oContentExtentH);
if (! m_bSplitContent) {
// Javaport: TODO
// getContent().setJustifyExtents(m_oContentExtent.width(), m_oContentExtent.height());
}
m_oNE = m_oNE.height(oNETopBottomMargins.add(oConTopBottomMargins).add(oContentExtentH), false);
m_oNE = m_oNE.width(oNELeftRightMargins.add(oContentExtentW).add(oConLeftRightMargins), false);
}
//Yes, we've already calculated the nominal extent w/h.
//But we did so by adding individual subtract region widths/height and their will inevitably be
//round off errors. For non-growable objects at least, we'll avoid these errors by just
//setting outright nominal extent values
if (! m_bGrowableW && ! m_bForcedGrowableW) {
assert (m_oMaxW.equals(m_oMinW));
m_oNE = m_oNE.width(m_oMaxW, false);
}
if (! m_bGrowableH && ! m_bForcedGrowableH) {
assert (m_oMaxH.equals(m_oMinH));
m_oNE = m_oNE.height(m_oMaxH, false);
}
}
protected void initContent(Element oNode) {
//Strategy
//Create the content stream, set text and other font
//attributes. Do not create a text display at this time - it
//will be done during formatting.
assert (oNode instanceof Draw || oNode instanceof Field);
// If we're a draw element and rendered from text runs, then we
// will get our content from the stored text run definitions.
if (isProxy() && oNode instanceof Draw)
return;
Element oValue = oNode.peekElement(XFA.VALUETAG, true, 0);
Content oContent = (Content) oValue.getOneOfChild(true, true);
UI oUI = (UI) oNode.peekElement(XFA.UITAG, true, 0);
Element oCurrentUI = oUI.getUIElement(false);
boolean bRichContent = false;
//boolean bIsExData = false;
boolean bIsField = (oNode instanceof Field);
//boolean bMultiLine = ! bIsField; // We'll assume not multiline for all fields, unless otherwise stated.
//String sTextContent = null;
//boolean bIsComb = false;
//int nNumCells = 0;
boolean bPasswordEdit = false;
char uPasswordChar = 0;
// Get the locale setting for the field/draw if specified.
String sLang = oNode.getInstalledLocale();
boolean bIsLocaleSpecified = !StringUtils.isEmpty(sLang);
int oCurrentUITag = oCurrentUI.getClassTag();
// if (oCurrentUITag == XFA.TEXTEDITTAG && bIsField) {
// bMultiLine = Bool.getValue((EnumValue) oCurrentUI.getAttribute(XFA.MULTILINETAG));
//
// // See if we're dealing with a comb field
// if (! bMultiLine)
// bIsComb = getComb(oNode, oCurrentUI, nNumCells);
// }
// if ((oCurrentUITag == XFA.DATETIMEEDITTAG || oCurrentUITag == XFA.NUMERICEDITTAG) && bIsField) {
// // See if we're dealing with a comb field
// bIsComb = getComb(oNode, oCurrentUI, nNumCells);
// }
// if (oCurrentUITag == XFA.CHOICELISTTAG && bIsField)
// bMultiLine = false;
if (oCurrentUITag == XFA.PASSWORDEDITTAG && bIsField) {
bPasswordEdit = true;
String oPasswordChar = oCurrentUI.peekAttribute(XFA.PASSWORDCHARTAG).toString();
if (oPasswordChar != null) {
String sPasswordChar = oPasswordChar;
if (!StringUtils.isEmpty(sPasswordChar)) {
uPasswordChar = sPasswordChar.charAt(0);
}
}
if (uPasswordChar == 0x0000)
uPasswordChar = 0x002A; // '*'
}
if (oContent instanceof ExDataValue) {
//bIsExData = true;
//Is this rich text?
String sContentType = oContent.getAttribute(XFA.CONTENTTYPETAG).toString();
bRichContent = (STRS.TEXTHTML.equals(sContentType));
}
// If it's not an field we get the text in a different way.
// Why? Because fields can contain picture clauses.
// if (! bIsField) {
// if (oContent instanceof TextValue) {
// sTextContent = ((TextValue) oContent).getValue();
// }
// else if (oContent instanceof DecimalValue) {
// double dTemp = ((DecimalValue) oContent).getValue();
// sTextContent = Double.toString(dTemp);
// }
// else if (oContent instanceof IntegerValue) {
// int nTemp = ((IntegerValue) oContent).getValue();
// sTextContent = Integer.toString(nTemp);
// }
// else if (oContent instanceof FloatValue) {
// double dTemp = ((FloatValue) oContent).getValue();
// sTextContent = Double.toString(dTemp);
// }
// else if (oContent instanceof DateValue) {
// sTextContent = ((DateValue) oContent).getValue();
// }
// else if (oContent instanceof DateTimeValue) {
// sTextContent = ((DateTimeValue) oContent).getValue();
// }
// else if (oContent instanceof TimeValue) {
// sTextContent = ((TimeValue) oContent).getValue();
// }
// else if (oContent instanceof ExDataValue) {
// AppModel appModel = oContent.getAppModel();
//
// // watson bug 1795969 old forms need to use the legacy XHTML processing
// boolean bLegacy = appModel.getLegacySetting(AppModel.XFA_LEGACY_V27_XHTMLVERSIONPROCESSING);
//
// // If we are here then the content type was not
// // text/html, but text/plain, so we will get the
// // value here. If it's RichText, it will be handled
// // later in this method.
// if (bIsExData && ! bRichContent) {
// sTextContent = ((ExDataValue) oContent).getValue(false, false, bLegacy);
// }
// }
// }
// else {
// if (bIsExData) {
// AppModel appModel = oContent.getAppModel();
//
// // watson bug 1795969 old forms need to use the legacy XHTML processing
// boolean bLegacy = appModel.getLegacySetting(AppModel.XFA_LEGACY_V27_XHTMLVERSIONPROCESSING);
//
// sTextContent = ((ExDataValue) oContent).getValue(false, false, bLegacy);
// }
// else {
// // Get the picture formatted text
// sTextContent = ((Field) oNode).getFormattedValue();
// }
// }
// Init text engine members:
// Assign a default width and height to textblock.
// This may change once any growable-ness calculates the
// exact content area the text is to occupy.
if (! m_bKeepContentTextStream) { // Do full initialization
// Javaport: not yet available. TODO
// m_oContentDisplay = AXTEDisplay(new TextRegion(), m_oGfxLayoutEnv);
// getContent().setText(sTextContent);
// getContent().allowOverflow(! bMultiLine);
//
// // For a comb field let the text region know how many cells there are
// if (bIsComb)
// getContent().combCells(nNumCells);
// getContentRangeAttrs().associate(getContent());
//
// //For performance reasons, collect text attributes so they can be set all at once.
// //Record them in a member variable so that we can return the correct xhtml string value if asked
// m_oAmbientTextAttr.default();
m_oAmbientTextAttr.transparent(true);
m_oAmbientTextAttr.fontService(m_oGfxLayoutEnv.fontService());
//Initialize alignment. Be aware that justifyAll is not compatible with horiz-growableness.
//One indicates 'grow to the content extent' and the other says 'extend the content along the
//entire extent'.
Element oPara = oNode.peekElement(XFA.PARATAG, true, 0);
int eVAlign = oPara.getEnum(XFA.VALIGNTAG);
setVertAlign(eVAlign, m_oAmbientTextAttr);
int eHAlign = oPara.getEnum(XFA.HALIGNTAG);
if (EnumAttr.HALIGN_JUSTIFY_ALL == eHAlign && hasGrowableW())
eHAlign = EnumAttr.HALIGN_JUSTIFY;
setHorizAlign(eHAlign, m_oAmbientTextAttr);
if (EnumAttr.HALIGN_RADIX == eHAlign) {
// Check for Radix Offset
UnitSpan oRO = new Measurement(oPara.getAttribute(XFA.RADIXOFFSETTAG)).getUnitSpan();
m_oAmbientTextAttr.radixOffset(new TextMeasurement(oRO));
}
// Set the locale on the text attr if one was specified.
if (bIsLocaleSpecified) {
m_oAmbientTextAttr.locale(sLang);
}
// Initialize the font.
setFont(oNode.peekElement(XFA.FONTTAG, true, 0), oPara, true, m_oAmbientTextAttr, sLang);
if (bIsField) {
Element oFormat = oNode.peekElement(XFA.FORMATTAG, false, 0);
Picture oPicture = null;
if (oFormat != null)
oPicture = (Picture) oFormat.peekElement(XFA.PICTURETAG, false, 0);
String sPicture = "";
if (oPicture != null)
sPicture = oPicture.getValue();
if (!StringUtils.isEmpty(sPicture)) {
StringBuilder sCat = new StringBuilder();
StringBuilder sLoc = new StringBuilder();
StringBuilder sSub = new StringBuilder();
if (PictureFmt.isSubPicture(sPicture, 0, sCat, sLoc, sSub)
&& sCat.toString().equals("num")
|| PictureFmt.isNumericPicture(sPicture)) {
if (StringUtils.isEmpty(sSub))
sSub.append(sPicture);
if (StringUtils.isEmpty(sLoc))
sLoc.append(sLang);
LcLocale oLocale = new LcLocale(sLoc.toString());
m_oAmbientTextAttr.locale(oLocale.getIsoName());
String sRawTextContent = ((Field) oNode).getRawValue();
LcNum oNum = new LcNum(sRawTextContent, sLoc.toString());
IntegerHolder oRadixPos = new IntegerHolder();
String sRes = oNum.format(sSub.toString(), oRadixPos);
if (!StringUtils.isEmpty(sRes))
m_oAmbientTextAttr.radixPos(oRadixPos.value);
}
}
//initialize the tab default and tab stops
setTabs (oPara.getAttribute(XFA.TABSDEFAULTTAG),
oPara.getAttribute(XFA.TABSTOPSTAG),
m_oAmbientTextAttr);
}
if (bPasswordEdit) {
m_oAmbientTextAttr.invisible(true);
m_oAmbientTextAttr.invisChar(uPasswordChar);
}
//Apply the text attributes
// Javaport: not yet available. TODO
// getContentRangeAttrs().attribute(m_oAmbientTextAttr);
if (bRichContent) {
AppModel appModel = oContent.getAppModel();
// watson bug 1795969 old forms need to use the legacy XHTML processing
boolean bLegacy = appModel.getLegacySetting(AppModel.XFA_LEGACY_V27_XHTMLVERSIONPROCESSING);
String sRichText = ((ExDataValue) oContent).getValue(true, false, bLegacy);
// Supply an ambient attribute so that we can process the
// xhtml fragment better. This fixes an immediate problem
// where we need to tell text services what the ambient font is.
// Also, pass a text resolver for any embedded field references within
// the xhtml markup
if (!StringUtils.isEmpty(sRichText)) {
// Javaport: TODO
// assert (null != m_oGfxLayoutEnv.getTextResolver());
if (null != m_oGfxLayoutEnv.getTextResolver()) {
// set the context for the SOMExpression so that
// we may be able to resolve un-qualified names
// Javaport: not yet available. TODO
// LayoutTextResolver pResolver = (LayoutTextResolver) m_oGfxLayoutEnv.getTextResolver();
// assert (null != pResolver);
// pResolver.setContext(oNode);
//
// TextAttr pAmbientAttr = m_oAmbientTextAttr;
// pResolver.hasEmbeddedContent(false);
//
// MarkupXHTMLIn oMarkup = new MarkupXHTMLIn(sRichText, null, pAmbientAttr, pResolver);
// getContentRangeAttrs().markup(oMarkup);
//
// m_bEmbeddedContent = pResolver.hasEmbeddedContent();
// pResolver.hasEmbeddedContent(false);
}
}
}
// If caption is inline then be sure to insert it at start
// of content stream. This must be done *after* resolving
// any rich markup font changes in the content stream.
if (hasInlineCaption() && null != getCaption()) {
TextPosnBase oPosn = new TextPosnBase(getContent());
oPosn.first();
// Javaport: TODO
// getContent().posnInsert(oPosn, getCaption());
}
TextPosnBase oPosn = new TextPosnBase(getContent());
m_oStartContentPosn = new TextPosn(oPosn);
m_oEndContentPosn = new TextPosn(oPosn);
m_oStartContentPosn.first();
m_oEndContentPosn.last();
}
}
public boolean hasEmbeddedContent() {
return m_bEmbeddedContent;
}
protected void createDisplay(UnitSpan minW,
UnitSpan maxW,
UnitSpan minH,
UnitSpan maxH) {
//Set the content ranges. Because these values were calculated with the nominal extent
//min/max in mind the we know that the resulting content region will not result in a box
//model that violates it's nominal range.
//Create the content display after setting ranges - it's more efficient because
//then the line formatting is only performed once.
if (! m_bSplitContent) {
// Javaport: TODO
// getContent().setMinWidth(minW);
// getContent().setMaxWidth(maxW);
// getContent().setMinHeight(minH);
// getContent().setMaxHeight(maxH);
}
// if (null == getContentDisplay())
// m_oContentDisplay.createDisplay(null, m_oGfxLayoutEnv);
}
//Private initialization used during splitting
private void initializeSplit(Element oNode,
// AXTEDisplay oContent,
Rect oContentRect,
// AXTEDisplay oCaption,
Rect oCaptionRect) {
//Strategy
//Initialize the box model for a text based object (field/draw) given
//the initial stream of content and caption but still using box model
//settings of xfa node.
//1)Read initial box model settings from node, including
//-x,y,anchor
//-margins
//-border
//-initialize caption (stream already created with the original BM)
//-initialize content (stream already created with the original BM)
//2)Then format the box model into subregions (content/caption) given these settings.
// This will automatically account for min/max ranges
//3)Record the visual extent of the box model
//Do not support rotation or min/max at this time
assert (oNode != null);
assert (isBoxModelCompatible(oNode));
//Initialize a box model from a
if (! isBoxModelCompatible(oNode))
return;
//Read ne w/h, determine growability and if applicable the ne min/max ranges
initWidthHeight(oNode, true);
//Read anchor
initAnchorPoint(oNode);
//Read ne, content and caption margins
initMargins(oNode);
//Read border margins, content border margins
initBorder(oNode);
//Set the caption stream and rect
initSplitCaption(oNode, /* oCaption, */ oCaptionRect);
//Set the content stream and rect
initSplitContent(oNode, /* oContent, */ oContentRect);
//Format internals based on the info so far
format(oNode);
//Finally, determine the visual extent.
initVisualExtent(oNode);
}
private void initSplitContent(Element oNode,
// AXTEDisplay oContent,
Rect oRect /* = Rect.ZERO */) {
if (! m_bHasCaption)
return;
// Javaport: not yet available. TODO
// m_oCaptionDisplay = oCaption;
m_oCaptionDisplayExtent = oRect;
assert (null != getCaption());
assert (null != getCaptionDisplay());
}
private void initSplitCaption(Element oNode,
// AXTEDisplay oCaption,
Rect oRect /* = Rect.ZERO */) {
// Javaport: not yet available. TODO
// m_oContentDisplay = oContent;
m_oContentDisplayExtent = oRect;
assert (null != getContent());
assert (null != getContentDisplay());
}
/**
* Return true if this box model contains text that overflows it's allotted space
* and false otherwise.
* @return false if this object contains no text.
* @see #BoxModelLayout.hasOverflowingContentText()
* @exclude from published api.
*/
public boolean hasOverflowingContentText() {
// Javaport: not yet available. TODO
/*
if ((m_oContentDisplay != null) && null != m_oContentDisplay.getDisplay()) {
Rect rcContentRuntime = m_oContentDisplay.getDisplay().runtimeExtent();
Rect rcContentAllotted = getContentExtent();
if (m_bWasRotated && (m_oRotationAngle.degrees() == 90 || m_oRotationAngle.degrees() == 270)) {
//Flip it - compare alloted-content width vs runtime h etc
return rcContentAllotted.height() < rcContentRuntime.width() || rcContentAllotted.width() < rcContentRuntime.height();
}
return rcContentAllotted.width() < rcContentRuntime.width() || rcContentAllotted.height() < rcContentRuntime.height();
}
*/
return false;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy