net.sf.jasperreports.engine.util.StyledTextWriteContext Maven / Gradle / Ivy
/*
* JasperReports - Free Java Reporting Library.
* Copyright (C) 2001 - 2023 Cloud Software Group, Inc. All rights reserved.
* http://www.jaspersoft.com
*
* Unless you have purchased a commercial license agreement from Jaspersoft,
* the following license terms apply:
*
* This program is part of JasperReports.
*
* JasperReports is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* JasperReports is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with JasperReports. If not, see .
*/
package net.sf.jasperreports.engine.util;
import java.text.AttributedCharacterIterator.Attribute;
import java.util.Map;
/**
* @author Teodor Danciu ([email protected])
*/
public class StyledTextWriteContext
{
private StyledTextListInfo[] prevListStack;
private StyledTextListItemInfo prevListItem;
private StyledTextListInfo[] listStack;
private StyledTextListItemInfo listItem;
private boolean isFirstRun = true;
private boolean runTextEndedWithNewLine = false;
private boolean prevRunTextEndedWithNewLine = false;
private boolean runTextStartsWithNewLine = false;
private int prevDepth = 0;
private int newDepth = 0;
private int commonListDepth = 0;
private boolean isProcessingCuts = false;
public StyledTextWriteContext()
{
}
public StyledTextWriteContext(boolean isProcessingCuts)
{
this.isProcessingCuts = isProcessingCuts;
}
public boolean isFirstRun()
{
return isFirstRun;
}
public StyledTextListInfo getPrevList(int index)
{
return prevListStack == null || prevListStack.length == 0 ? null : prevListStack[index];
}
public StyledTextListInfo getPrevList()
{
return prevListStack == null || prevListStack.length == 0 ? null : prevListStack[prevListStack.length - 1];
}
public StyledTextListInfo getList(int index)
{
return listStack == null || listStack.length == 0 ? null : listStack[index];
}
public StyledTextListInfo getList()
{
return listStack == null || listStack.length == 0 ? null : listStack[listStack.length - 1];
}
public StyledTextListItemInfo getListItem()
{
return listItem;
}
public boolean prevListItemEndedWithNewLine()
{
return prevRunTextEndedWithNewLine;
}
public boolean listItemStartsWithNewLine()
{
return runTextStartsWithNewLine;
}
public int getPrevDepth()
{
return prevDepth;
}
public int getDepth()
{
return newDepth;
}
public int getCommonListDepth()
{
return commonListDepth;
}
public boolean isListStart()
{
return (commonListDepth + 1 == newDepth);
}
public boolean isListEnd()
{
return (commonListDepth + 1 == prevDepth);
}
public boolean isListItemStart()
{
return
(listItem != null // there is a new li
&& listItem != StyledTextListItemInfo.NO_LIST_ITEM_FILLER // it is indeed a list item and not a filler
&& listItem != prevListItem // it is different than the previous one
&& (prevDepth <= newDepth // it is of a deeper level (this condition is probably redundant with respect to the following two)
|| (commonListDepth == newDepth
&& (!prevListStack[commonListDepth].hasParentLi() // list was between li
|| prevListStack[commonListDepth].atLiEnd())) // list was right at the end of li
|| commonListDepth < newDepth)
); // so opening it
}
public boolean isListItemEnd()
{
return
(prevListItem != null // there was a li
&& prevListItem != StyledTextListItemInfo.NO_LIST_ITEM_FILLER // it was indeed a list item and not a filler
&& prevListItem != listItem // was not the same as the new one
&& (prevDepth >= newDepth // was of deeper level (this condition is probably redundant with respect to the following two)
|| (commonListDepth == prevDepth
&& (!listStack[commonListDepth].hasParentLi() // new list is between li
|| listStack[commonListDepth].atLiStart())) // new list is right at the start of li
|| commonListDepth < prevDepth)
); // so closing it
}
public boolean isListItemChange()
{
return listItem != prevListItem;
}
public void next(Map attributes)
{
this.prevListStack = this.listStack;
this.prevListItem = this.listItem;
if (attributes == null)
{
this.listStack = null;
this.listItem = null;
}
else
{
this.listStack = (StyledTextListInfo[])attributes.get(JRTextAttribute.HTML_LIST);
this.listItem = (StyledTextListItemInfo)attributes.get(JRTextAttribute.HTML_LIST_ITEM);
}
prevDepth = prevListStack == null ? 0 : prevListStack.length;
newDepth = listStack == null ? 0 : listStack.length;
int minDepth = Math.min(prevDepth, newDepth);
commonListDepth = 0;
while (commonListDepth < minDepth)
{
if (listStack[commonListDepth] != prevListStack[commonListDepth])
{
break;
}
commonListDepth++;
}
if (isProcessingCuts)
{
if (isFirstRun)
{
if (this.listStack != null)
{
for (StyledTextListInfo list : listStack)
{
list.setCutStart(list.getStart() + list.getItemIndex());
}
}
}
if (isListItemStart() || getListItem() == StyledTextListItemInfo.NO_LIST_ITEM_FILLER)
{
StyledTextListInfo list = getList();
if (list != null) // set proper item index also for non ordered lists, why not? && list.ordered())
{
if (getListItem() == StyledTextListItemInfo.NO_LIST_ITEM_FILLER)
{
list.setItemIndex(list.getItemIndex() + 1);
}
else
{
list.setItemIndex(getListItem().getItemIndex());
}
}
}
}
this.isFirstRun = false;
}
public void next(
Map attributes,
String runText
)
{
next(attributes);
this.prevRunTextEndedWithNewLine = runTextEndedWithNewLine;
this.runTextEndedWithNewLine = runText == null ? false : runText.endsWith("\n");
this.runTextStartsWithNewLine = runText == null ? false : runText.startsWith("\n");
}
public void writeLists(StyledTextListWriter writer)
{
if (writer == null)
{
return;
}
if (isListItemEnd())
{
writer.endLi();
}
for (int i = getPrevDepth() - 1; i > getCommonListDepth(); i--)
{
StyledTextListInfo prevList = getPrevList(i);
if (prevList.ordered())
{
writer.endOl();
}
else
{
writer.endUl();
}
if (prevList.hasParentLi())
{
writer.endLi();
}
}
if (getPrevDepth() > getCommonListDepth())
{
StyledTextListInfo prevList = getPrevList(getCommonListDepth());
if (prevList.ordered())
{
writer.endOl();
}
else
{
writer.endUl();
}
if (prevList.hasParentLi() && prevList.atLiEnd())
{
writer.endLi();
}
}
if (getCommonListDepth() < getDepth())
{
StyledTextListInfo list = getList(getCommonListDepth());
if (list.hasParentLi() && list.atLiStart())
{
writer.startLi(true);
}
if (list.ordered())
{
writer.startOl(list.getType(), list.getCutStart());
}
else
{
writer.startUl();
}
}
for (int i = getCommonListDepth() + 1; i < getDepth(); i++)
{
StyledTextListInfo list = getList(i);
if (list.hasParentLi())
{
writer.startLi(true);
}
if (list.ordered())
{
writer.startOl(list.getType(), list.getCutStart());
}
else
{
writer.startUl();
}
}
if (isListItemStart())
{
writer.startLi(getListItem().noBullet());
}
}
}