net.sf.jasperreports.engine.util.StyledTextWriteContext Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jasperreports Show documentation
Show all versions of jasperreports Show documentation
Free Java Reporting Library
/*
* 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());
}
}
}