I'm designing a custom XML view with javafx.
Imagine the following XML.
<CD>
<TITLE>Empire Burlesque</TITLE>
<ARTIST>Bob Dylan</ARTIST>
<COUNTRY>USA</COUNTRY>
<COMPANY>Columbia</COMPANY>
<PRICE>10.90</PRICE>
<YEAR>1985</YEAR>
</CD>
Now I want the user to be able to edit the title, the artist etc. without him being able to change the rest of the XML.
Note that my goal is to achieve this with XML style and dont present the user with a input, dialog.
Any ideas how I can achieve this?
You could use a TextFormatter with a regex-filter to ensure the format:
This is just a small example: (You should adapt the regex to your needs)
TextArea ta = new TextArea();
ta.setText("<CD>\n <TITLE>Empire Burlesque</TITLE>\n <ARTIST>Bob Dylan</ARTIST>\n <COUNTRY>USA</COUNTRY>\n <COMPANY>Columbia</COMPANY>\n <PRICE>10.90</PRICE>\n <YEAR>1985</YEAR>\n</CD>");
UnaryOperator<Change> filter = c -> {
if(c.getControlNewText().matches("<CD>\\n <TITLE>.*</TITLE>\\n <ARTIST>.*</ARTIST>\\n <COUNTRY>.*</COUNTRY>\\n <COMPANY>.*</COMPANY>\\n <PRICE>[0-9]*\\.?[0-9]*</PRICE>\\n <YEAR>[0-9]{0,4}</YEAR>\\n</CD>")) {
return c;
}
// The new input doesn't match the regex and gets discarded
return null;
};
ta.setTextFormatter(new TextFormatter<String>(filter));
You could a layout for the xml on your own that uses Text nodes for the start/end tags and TextFields for the text content:
String input = "<CD>\n"
+ " <TITLE>Empire Burlesque</TITLE>\n"
+ " <ARTIST>Bob Dylan</ARTIST>\n"
+ " <COUNTRY>USA</COUNTRY>\n"
+ " <COMPANY>Columbia</COMPANY>\n"
+ " <PRICE>10.90</PRICE>\n"
+ " <YEAR>1985</YEAR>\n"
+ "</CD>";
XMLInputFactory inputFactory = XMLInputFactory.newInstance();
inputFactory.setProperty(XMLInputFactory.IS_COALESCING, Boolean.TRUE);
XMLStreamReader reader = inputFactory.createXMLStreamReader(new ByteArrayInputStream(input.getBytes()));
List<List<Node>> currentChildren = new ArrayList<>();
currentChildren.add(new ArrayList<>(1));
String text = null;
int depth = 0;
final Insets insets = new Insets(0, 0, 0, 20);
boolean hasChildren = false;
while (reader.hasNext()) {
switch (reader.next()) {
case XMLStreamConstants.START_ELEMENT:
depth++;
hasChildren = false;
currentChildren.add(new ArrayList<>());
break;
case XMLStreamConstants.CHARACTERS:
text = reader.getText();
break;
case XMLStreamConstants.END_ELEMENT:
String suffix = reader.getName().getLocalPart() + ">";
if (hasChildren) {
// element group
VBox vbox = new VBox(new Text("<" + suffix));
for (Node n : currentChildren.get(depth)) {
VBox.setMargin(n, insets);
}
vbox.getChildren().addAll(currentChildren.get(depth));
vbox.getChildren().add(new Text("</" + suffix));
currentChildren.get(depth - 1).add(vbox);
} else {
// text element
TextField textField = new TextField(text);
textField.setMinWidth(Region.USE_PREF_SIZE);
textField.setMaxWidth(Region.USE_PREF_SIZE);
// keep size of TextField large enough to contain all the text
ChangeListener<String> listener = new ChangeListener<String>() {
private final Text measureElement = new Text();
{
measureElement.setFont(Font.font("monospaced"));
}
#Override
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
measureElement.setText(newValue);
textField.setPrefWidth(measureElement.getLayoutBounds().getWidth() + 2);
}
};
listener.changed(null, null, text);
textField.textProperty().addListener(listener);
HBox hbox = new HBox(new Text('<' + suffix), textField, new Text("</" + suffix));
currentChildren.get(depth - 1).add(hbox);
hasChildren = true;
text = null;
}
currentChildren.remove(depth);
depth--;
break;
}
}
VBox root = (VBox) currentChildren.get(0).get(0);
root.getStyleClass().add("xml-editor");
CSS Stylesheet
.xml-editor .text-field,
.xml-editor .text-field:focused {
/* remove TextField border & background */
-fx-focus-color: transparent;
-fx-control-inner-background: transparent;
-fx-faint-focus-color: transparent;
-fx-text-box-border: transparent;
-fx-text-fill: black;
-fx-padding: 0;
-fx-font-family: 'monospaced';
}
.xml-editor Text {
-fx-font-family: 'monospaced';
}
You could achieve this by using the TextFlow component.
It works by passing objects to your TextFlow such as TextField, Text etc.
You can add custom styling to each of these objects.
Now, your XML titles could be Text objects for example and your values TextField ones.
Then, you could choose whether a TextField object you are adding to the TextFlow is editable or not. For example:
Text field = new Text("one");
TextField value = new TextField("two");
value.setPrefWidth(value.getText().length()*12); // customize if needed
value.setStyle("-fx-fill: RED;-fx-font-weight:normal;"); // adding css
value.setEditable(false); // this field cannot be edited
textFlow.getChildren().addAll(field,value);
Related
I'm reading one string in that some li tags have spans with styles so I'm trying to add styles for a particular word in the li tag (not for the whole line), but for every styles change it is going for new bullet point instead of appending to the same li,
String:
"<p><span style=\"font-weight: bold;\">Title</span></p> <ul> <li> <span style=\"font-weight: bold;\"> </span><span>Laser cutting of sheet </span><span style=\"font-weight: bold;\">metal</span><span> generates a continuous heat source which can led to high levels of thermal stress </span> </li> <li><span>Thermal Stress can deform the material at the micron level and the slightest deformation reduces the effectiveness of the sheet metal components</span></li> <br /> </ul> <p><span> </span><span style=\"font-weight: bold;\">Mass Level Production</span></p> <ul> <li><span>Laser cutting cannot produce more component more than one part at a time</span></li> <li><span>When production is required at a lower level , laser cutting may be apt but inefficient for mass level production</span></li> </ul> <p><span style=\"font-weight: bold;\">Metal etching with aluminum</span></p> <p><span style=\"font-weight: bold;\"> </span></p> <ul> <li><span>Aluminum is a reflective material that is reactive to heat in the manufacturing process and therefore, makes it less suitable for laser cutting and wire EDM processes</span></li> <li> <span>As the use of aluminum is growing in many industries, there is a requirement for a suitable manufacturing process for thin </span><span style=\"font-weight: bold;\">aluminum</span><span>components</span> </li> </ul>"
Can anyone help me, like where I'm doing the mistake?
Code:
public static void advancedUlLiConvert(XSLFTextShape textShape, String str) {
System.out.println("Recived String: "+str);
Document doc = null;
try {
doc = Jsoup.parse(str);
Element element = doc.body();
Elements lstElements = element.children();
System.out.println("bodyChildEle : " +lstElements);
for (Element ele: lstElements) {
if (ele.tagName() == "p") {
System.out.println("para" + ele);
String para = ele.children().toString();
System.out.println("String para" + para);
//if any <p> tags are there then I'm calling this method to take care of that which is working fine,
addAllStyledText(textShape,para, false);
}
//I'm facing problems in these below part
if (ele.tagName() == "ul") {
Elements lstLi = ele.children();
System.out.println("lstsi" + lstLi);
for (Element li: lstLi) {
Elements spans = li.children();
XSLFTextParagraph paragraph = textShape.addNewTextParagraph();
paragraph.setBullet(true);
XSLFTextRun textRun = paragraph.addNewTextRun();
System.out.println("allspans: " + spans);
for (Element span: spans) {
System.out.println("loopspan" + span);
if (!(span.hasText())) {
span.remove();
System.out.println("Removed Element: "+ span);
} else if (span.hasAttr("style")) {
System.out.println("Styled Span: " + span);
String strSpan = span.toString();
boolean isBold = false;
boolean isItalic = false;
boolean isUnderline = false;
boolean isLineThrough = false;
if (strSpan.contains(": bold;"))
isBold = true;
if (strSpan.contains(": italic;"))
isItalic = true;
if (strSpan.contains(": underline;"))
isUnderline = true;
if (strSpan.contains(": line-through;"))
isLineThrough = true;
String text = span.text();
textRun = textShape.appendText(text+" ", false);
if (isBold) {
textRun.setBold(true);
//textRun.setFontColor(rgb);
}
if (isItalic) {
textRun.setItalic(true);
}
if (isUnderline) {
textRun.setUnderlined(true);
}
if (isLineThrough) {
textRun.setStrikethrough(true);
}
//textRun.setText(text);
} else {
System.out.println("Span without Style: " + span);
String text = span.text();
//if I make this as false than whole code braking not sure why
textRun = textShape.appendText(text + " ", true);
//textRun.setText(text);
//paragraph.setBullet(false);
//paragraph.setBullet(false);
//paragraph.addNewTextRun().setText(text);
}
XSLFTextRun dummyTextRun = textShape.appendText("", false);
dummyTextRun.setBold(false);
dummyTextRun.setItalic(false);
dummyTextRun.setUnderlined(false);
dummyTextRun.setStrikethrough(false);
}
paragraph.setBullet(false);
}
}
}
} catch (Exception e) {
log.error("Exception in advancedUlLiConvert: " , e);
}
}
Code Output:
My expectation :
To program a HTML to XSLFTextParagraph converter, which considers all the ugly possibilities of that HTML tag-soup, would lead to program a whole library. HTML is a mess, nothing else. No real rules, all free interpretable by browsers.
JSoup is a helper but not the complete solution. I have adopted my attempt of How to set define different styles for the same paragraph to XSLF. As told there it uses NodeTraversor and NodeVisitor of JSoup. I have extended this to consider inline-CSS using style attributes in SPAN elements. Also I have extended it to consider LI elements in UL elements as bulleted paragraphs.
Complete example converting your given HTML-String:
import java.io.FileOutputStream;
import org.apache.poi.xslf.usermodel.*;
import org.apache.poi.sl.usermodel.*;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Node;
import org.jsoup.nodes.TextNode;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.jsoup.select.NodeVisitor;
import org.jsoup.select.NodeTraversor;
public class HTMLtoPPTX {
private XMLSlideShow slideShow;
public HTMLtoPPTX(String html, String pptxPath) throws Exception {
this.slideShow = new XMLSlideShow();
XSLFSlide slide = slideShow.createSlide();
XSLFTextShape textShape = slide.createAutoShape();
java.awt.Rectangle rect = new java.awt.Rectangle(100, 100, 500, 400);
textShape.setAnchor(rect.getBounds2D());
textShape.setShapeType(ShapeType.RECT);
XSLFTextParagraph paragraph = null;
Document htmlDocument = Jsoup.parse(html);
Elements htmlElements = htmlDocument.select("p:not(li *), ul li:not(li *)");
for(Element htmlElement : htmlElements) {
System.out.println(htmlElement);
paragraph = textShape.addNewTextParagraph();
createParagraphFromHTML(paragraph, htmlElement);
}
FileOutputStream out = new FileOutputStream(pptxPath);
slideShow.write(out);
out.close();
slideShow.close();
}
void createParagraphFromHTML(XSLFTextParagraph paragraph, Element htmlElement) {
ParagraphNodeVisitor nodeVisitor = new ParagraphNodeVisitor(paragraph);
NodeTraversor.traverse(nodeVisitor, htmlElement);
}
private class ParagraphNodeVisitor implements NodeVisitor {
String nodeName;
boolean isItalic;
boolean isBold;
boolean isUnderlined;
double fontSize;
java.awt.Color fontColor;
XSLFTextParagraph paragraph;
XSLFTextRun run;
boolean spanStyleSetBold;
boolean spanStyleSetItalic;
boolean spanStyleSetUnderlined;
boolean spanStyleSetFontColor;
boolean spanStyleSetFontSize;
ParagraphNodeVisitor(XSLFTextParagraph paragraph) {
this.paragraph = paragraph;
this.run = paragraph.addNewTextRun(); this.run.setText("");
this.nodeName = "";
this.isItalic = false;
this.isBold = false;
this.isUnderlined = false;
this.fontSize = 11d;
this.fontColor = java.awt.Color.BLACK;
this.spanStyleSetBold = false;
this.spanStyleSetItalic = false;
this.spanStyleSetUnderlined = false;
this.spanStyleSetFontColor = false;
this.spanStyleSetFontSize = false;
}
#Override
public void head(Node node, int depth) {
nodeName = node.nodeName();
System.out.println("Start "+nodeName+": " + node);
if ("#text".equals(nodeName)) {
run.setText(((TextNode)node).text());
} else if ("i".equals(nodeName)) {
isItalic = true;
} else if ("b".equals(nodeName)) {
isBold = true;
} else if ("u".equals(nodeName)) {
isUnderlined = true;
} else if ("br".equals(nodeName)) {
run = run.getParagraph().addLineBreak();
} else if ("font".equals(nodeName)) {
String rgbS = (!"".equals(node.attr("color")))?node.attr("color"):"#000000";
fontColor = new java.awt.Color(
Integer.valueOf(rgbS.substring(1, 3), 16),
Integer.valueOf(rgbS.substring(3, 5), 16),
Integer.valueOf(rgbS.substring(5, 7), 16)
);
fontSize = (!"".equals(node.attr("size")))?Double.parseDouble(node.attr("size")):11d;
} else if ("li".equals(nodeName)) {
paragraph.setBullet(true);
} else if ("span".equals(nodeName)) {
String style = node.attr("style");
if (style.matches(".*\\bfont-weight:\\s*bold\\s*;.*")) {
isBold = true;
spanStyleSetBold = true;
}
if (style.matches(".*\\bfont-style:\\s*italic\\s*;.*")) {
isItalic = true;
spanStyleSetItalic = true;
}
if (style.matches(".*\\btext-decoration:\\s*underline\\s*;.*")) {
isUnderlined = true;
spanStyleSetUnderlined = true;
}
//if (style.matches(".*\\bcolor:\\s*(#[0-9a-fA-F]+)\\s*;.*")) {
// ToDo
//}
//if (style.matches(".*\\bfont-size:\\s*(#[0-9]+)\\s*;.*")) {
// ToDo
//}
}
run.setItalic(isItalic);
run.setBold(isBold);
if (isUnderlined) run.setUnderlined(true); else run.setUnderlined(false);
run.setFontColor(fontColor); run.setFontSize(fontSize);
}
#Override
public void tail(Node node, int depth) {
nodeName = node.nodeName();
System.out.println("End "+nodeName);
if ("#text".equals(nodeName)) {
run = paragraph.addNewTextRun(); run.setText(""); //after setting the text in the run a new run is needed
} else if ("i".equals(nodeName)) {
isItalic = false;
} else if ("b".equals(nodeName)) {
isBold = false;
} else if ("u".equals(nodeName)) {
isUnderlined = false;
} else if ("br".equals(nodeName)) {
run = paragraph.addNewTextRun(); run.setText(""); //after setting a break a new run is needed
} else if ("font".equals(nodeName)) {
fontColor = java.awt.Color.BLACK;
fontSize = 11d;
} else if ("li".equals(nodeName)) {
// ToDo
} else if ("span".equals(nodeName)) {
if (spanStyleSetItalic) isItalic = false;
if (spanStyleSetBold) isBold = false;
if (spanStyleSetUnderlined) isUnderlined = false;
//if (spanStyleSetFontColor) fontColor = java.awt.Color.BLACK; //ToDo
//if (spanStyleSetFontSize) fontSize = 11d; //ToDo
run = paragraph.addNewTextRun(); run.setText(""); //after a span a new run is needed
}
run.setItalic(isItalic);
run.setBold(isBold);
if (isUnderlined) run.setUnderlined(true); else run.setUnderlined(false);
run.setFontColor(fontColor); run.setFontSize(fontSize);
}
}
public static void main(String[] args) throws Exception {
String html =
"<p><font size='32' color='#0000FF'><b>First paragraph.</font></b><br/>Just like a heading</p>"
+"<p>This is my text <i>which now is in italic <b>but also in bold</b> depending on its <u>importance</u></i>.<br/>Now a <b><i><u>new</u></i></b> line starts <i>within <b>the same</b> paragraph</i>.</p>"
+"<p><b>Last <u>paragraph <i>comes</u> here</b> finally</i>.</p>"
+"<p>But yet <u><i><b>another</i></u></b> paragraph having <i><font size='22' color='#FF0000'>special <u>font</u> settings</font></i>. Now default font again.</p>"
+"<p />"
;
//html +=
html =
"<p><span style=\"font-weight: bold; font-style: italic; text-decoration: underline; \">Title</span></p>"
+"<ul> <li> <span style=\"font-weight: bold;\"> </span><span>Laser cutting of sheet </span><span style=\"font-weight: bold;\">metal</span><span> generates a continuous heat source which can led to high levels of thermal stress </span> </li> <li><span>Thermal Stress can deform the material at the micron level and the slightest deformation reduces the effectiveness of the sheet metal components</span></li> <br /> </ul>"
+"<p><span> </span><span style=\"font-weight:bold;text-decoration:underline;\">Mass Level Production</span></p>"
+"<ul> <li><span>Laser cutting cannot produce more component more than one part at a time</span></li> <li><span>When production is required at a lower level , laser cutting may be apt but inefficient for mass level production</span></li> </ul>"
+"<p><span style=\"font-weight: bold;\">Metal etching with aluminum</span></p>"
+"<p><span style=\"font-weight: bold;\"> </span></p>"
+"<ul> <li><span>Aluminum is a reflective material that is reactive to heat in the manufacturing process and therefore, makes it less suitable for laser cutting and wire EDM processes</span></li> <li> <span>As the use of aluminum is growing in many industries, there is a requirement for a suitable manufacturing process for thin </span><span style=\"font-weight: bold;\">aluminum</span><span>components</span> </li> </ul>"
;
HTMLtoPPTX htmlToPPTX = new HTMLtoPPTX(html, "./CreatePowerPointTextFromHTML.pptx");
}
}
Again: Disclaimer: This is a working draft showing the principle. Neither it is fully ready nor it is code ready for use in productive environments.
I am using itextpdf 7 (7.2.0) to create a pdf file. However even though the TOC part is rendered very well, in the content part the text overflows. Here is my code that generates the pdf:
public class Main {
public static void main(String[] args) throws IOException {
PdfWriter writer = new PdfWriter("fiftyfourthPdf.pdf");
PdfDocument pdf = new PdfDocument(writer);
Document document = new Document(pdf, PageSize.A4,false);
//document.setMargins(30,10,36,10);
// Create a PdfFont
PdfFont font = PdfFontFactory.createFont(StandardFonts.TIMES_ROMAN,"Cp1254");
document
.setTextAlignment(TextAlignment.JUSTIFIED)
.setFont(font)
.setFontSize(11);
PdfOutline outline = null;
java.util.List<AbstractMap.SimpleEntry<String, AbstractMap.SimpleEntry<String, Integer>>> toc = new ArrayList<>();
for(int i=0;i<5000;i++){
String line = "This is paragraph " + String.valueOf(i+1)+ " ";
line = line.concat(line).concat(line).concat(line).concat(line).concat(line);
Paragraph p = new Paragraph(line);
p.setKeepTogether(true);
document.add(p.setFont(font).setFontSize(10).setHorizontalAlignment(HorizontalAlignment.CENTER).setTextAlignment(TextAlignment.LEFT));
//PROCESS FOR TOC
String name = "para " + String.valueOf(i+1);
outline = createOutline(outline,pdf,line ,name );
AbstractMap.SimpleEntry<String, Integer> titlePage = new AbstractMap.SimpleEntry(line, pdf.getNumberOfPages());
p
.setFont(font)
.setFontSize(12)
//.setKeepWithNext(true)
.setDestination(name)
// Add the current page number to the table of contents list
.setNextRenderer(new UpdatePageRenderer(p));
toc.add(new AbstractMap.SimpleEntry(name, titlePage));
}
int contentPageNumber = pdf.getNumberOfPages();
for (int i = 1; i <= contentPageNumber; i++) {
// Write aligned text to the specified by parameters point
document.showTextAligned(new Paragraph(String.format("Sayfa %s / %s", i, contentPageNumber)).setFontSize(10),
559, 26, i, TextAlignment.RIGHT, VerticalAlignment.MIDDLE, 0);
}
//BEGINNING OF TOC
document.add(new AreaBreak());
Paragraph p = new Paragraph("Table of Contents")
.setFont(font)
.setDestination("toc");
document.add(p);
java.util.List<TabStop> tabStops = new ArrayList<>();
tabStops.add(new TabStop(580, TabAlignment.RIGHT, new DottedLine()));
for (AbstractMap.SimpleEntry<String, AbstractMap.SimpleEntry<String, Integer>> entry : toc) {
AbstractMap.SimpleEntry<String, Integer> text = entry.getValue();
p = new Paragraph()
.addTabStops(tabStops)
.add(text.getKey())
.add(new Tab())
.add(String.valueOf(text.getValue()))
.setAction(PdfAction.createGoTo(entry.getKey()));
document.add(p);
}
// Move the table of contents to the first page
int tocPageNumber = pdf.getNumberOfPages();
for (int i = 1; i <= tocPageNumber; i++) {
// Write aligned text to the specified by parameters point
document.showTextAligned(new Paragraph("\n footer text\n second line\nthird line").setFontColor(ColorConstants.RED).setFontSize(8),
300, 26, i, TextAlignment.CENTER, VerticalAlignment.MIDDLE, 0);
}
document.flush();
for(int z = 0; z< (tocPageNumber - contentPageNumber ); z++){
pdf.movePage(tocPageNumber,1);
pdf.getPage(1).setPageLabel(PageLabelNumberingStyle.UPPERCASE_LETTERS,
null, 1);
}
//pdf.movePage(tocPageNumber, 1);
// Add page labels
/*pdf.getPage(1).setPageLabel(PageLabelNumberingStyle.UPPERCASE_LETTERS,
null, 1);*/
pdf.getPage(tocPageNumber - contentPageNumber + 1).setPageLabel(PageLabelNumberingStyle.DECIMAL_ARABIC_NUMERALS,
null, 1);
document.close();
}
private static PdfOutline createOutline(PdfOutline outline, PdfDocument pdf, String title, String name) {
if (outline == null) {
outline = pdf.getOutlines(false);
outline = outline.addOutline(title);
outline.addDestination(PdfDestination.makeDestination(new PdfString(name)));
} else {
PdfOutline kid = outline.addOutline(title);
kid.addDestination(PdfDestination.makeDestination(new PdfString(name)));
}
return outline;
}
private static class UpdatePageRenderer extends ParagraphRenderer {
protected AbstractMap.SimpleEntry<String, Integer> entry;
public UpdatePageRenderer(Paragraph modelElement, AbstractMap.SimpleEntry<String, Integer> entry) {
super(modelElement);
this.entry = entry;
}
public UpdatePageRenderer(Paragraph modelElement) {
super(modelElement);
}
#Override
public LayoutResult layout(LayoutContext layoutContext) {
LayoutResult result = super.layout(layoutContext);
//entry.setValue(layoutContext.getArea().getPageNumber());
if (result.getStatus() != LayoutResult.FULL) {
if (null != result.getOverflowRenderer()) {
result.getOverflowRenderer().setProperty(
Property.LEADING,
result.getOverflowRenderer().getModelElement().getDefaultProperty(Property.LEADING));
} else {
// if overflow renderer is null, that could mean that the whole renderer will overflow
setProperty(
Property.LEADING,
result.getOverflowRenderer().getModelElement().getDefaultProperty(Property.LEADING));
}
}
return result;
}
#Override
// If not overriden, the default renderer will be used for the overflown part of the corresponding paragraph
public IRenderer getNextRenderer() {
return new UpdatePageRenderer((Paragraph) this.getModelElement());
}
}
}
Here are the screen shots of TOC part and content part :
TOC :
Content :
What am I missing? Thank you all for your help.
UPDATE
When I add the line below it renders with no overflow but the page margins of TOC and content part differ (the TOC margin is way more than the content margin). See the picture attached please :
document.setMargins(30,60,36,20);
Right Margin difference between TOC and content:
UPDATE 2 :
When I comment the line
document.setMargins(30,60,36,20);
and set the font size on line :
document.add(p.setFont(font).setFontSize(10).setHorizontalAlignment(HorizontalAlignment.CENTER).setTextAlignment(TextAlignment.LEFT));
to 12 then it renders fine. What difference should possibly the font size cause for the page content and margins? Are not there standard page margins and page setups? Am I unknowingly (I am newbie to itextpdf) messing some standard implementations?
TL; DR: either remove setFontSize in
p
.setFont(font)
.setFontSize(12)
//.setKeepWithNext(true)
.setDestination(name)
or change setFontSize(10) -> setFontSize(12) in
document.add(p.setFont(font).setFontSize(10).setHorizontalAlignment(HorizontalAlignment.CENTER).setTextAlignment(TextAlignment.LEFT));
Explanation: You are setting the Document to not immediately flush elements added to that document with the following line:
Document document = new Document(pdf, PageSize.A4,false);
Then you add an paragraph element with font size equal to 10 to the document with the following line:
document.add(p.setFont(font).setFontSize(10).setHorizontalAlignment(HorizontalAlignment.CENTER).setTextAlignment(TextAlignment.LEFT));
What happens is that the element is being laid out (split in lines etc), but now drawn on the page. Then you do .setFontSize(12) and this new font size is applied for draw only, so iText calculated that X characters would fit into one line assuming the font size is 10 while in reality the font size is 12 and obviously fewer characters can fit into one line.
There is no sense in setting the font size two times to different values - just pick one value you want to see in the resultant document and set it once.
I want to create a new style for my docx file by Apache-poi and I want to set "IRnazanin" as fontFamily for this style (IRnazanin is a kind of persian fonts). I wrote this code from this link and this one, but every time that I run it, Arial is set for paragraphs with this style (when I open docx file that is created by apache-poi, paragraphs with this style have "Arial (Body CS)" font from Theme font not IRNazanin). what should I do to fix it? And also fontsize is not set.
XWPFDocument docx = new XWPFDocument(OPCPackage.open("8.docx"));
XWPFStyles styles = docx.getStyles();
String heading1 = "My Heading 1";
String heading4 = "My Heading 4";
addCustomHeadingStyle(docx, styles, heading1, 1, 36, "4288BC");
addCustomHeadingStyle(docx, styles, heading4, 4, 20, "000000");
XWPFParagraph paragraph = docx.createParagraph();
paragraph.setStyle(heading4);
XWPFRun run = paragraph.createRun();
run.setText("سلااااام!");
List<XWPFParagraph> xwpfparagraphs = docx.getParagraphs();
System.out.println();
for (int i = 0; i < xwpfparagraphs.size(); i++) {
if (xwpfparagraphs.get(i).getText().equals("اول")) {
xwpfparagraphs.get(i).setStyle(heading1);
System.out.println("!##$%^&*()(*&^%$##!");
}
System.out.println("paragraph style id " + (i + 1) + ":" + xwpfparagraphs.get(i).getStyleID());
if (xwpfparagraphs.get(i).getStyleID() != null) {
String styleid = xwpfparagraphs.get(i).getStyleID();
XWPFStyle style = styles.getStyle(styleid);
if (style != null) {
System.out.println(xwpfparagraphs.get(i).getText());
System.out.println("Style name:" + style.getName());
if (style.getName().startsWith("heading")) {
//this is a heading
System.out.println("###############");
}
}
}
}
docx.write(docxOut);
private static void addCustomHeadingStyle(XWPFDocument docxDocument, XWPFStyles styles, String strStyleId, int headingLevel, int pointSize, String hexColor) {
CTStyle ctStyle = CTStyle.Factory.newInstance();
ctStyle.setStyleId(strStyleId);
CTString styleName = CTString.Factory.newInstance();
styleName.setVal(strStyleId);
ctStyle.setName(styleName);
CTDecimalNumber indentNumber = CTDecimalNumber.Factory.newInstance();
indentNumber.setVal(BigInteger.valueOf(headingLevel));
// lower number > style is more prominent in the formats bar
ctStyle.setUiPriority(indentNumber);
CTOnOff onoffnull = CTOnOff.Factory.newInstance();
ctStyle.setUnhideWhenUsed(onoffnull);
// style shows up in the formats bar
ctStyle.setQFormat(onoffnull);
// style defines a heading of the given level
CTPPr ppr = CTPPr.Factory.newInstance();
ppr.setOutlineLvl(indentNumber);
ctStyle.setPPr(ppr);
XWPFStyle style = new XWPFStyle(ctStyle);
CTHpsMeasure size = CTHpsMeasure.Factory.newInstance();
size.setVal(new BigInteger(String.valueOf(pointSize)));
CTHpsMeasure size2 = CTHpsMeasure.Factory.newInstance();
size2.setVal(new BigInteger("24"));
CTFonts fonts = CTFonts.Factory.newInstance();
fonts.setAscii("IRnazanin");
fonts.setHAnsi("IRnazanin");
CTRPr rpr = CTRPr.Factory.newInstance();
rpr.setRFonts(fonts);
rpr.setSz(size);
rpr.setSzCs(size2);
CTColor color = CTColor.Factory.newInstance();
color.setVal(hexToBytes(hexColor));
rpr.setColor(color);
style.getCTStyle().setRPr(rpr);
// is a null op if already defined
style.setType(STStyleType.PARAGRAPH);
styles.addStyle(style);
}
public static byte[] hexToBytes(String hexString) {
HexBinaryAdapter adapter = new HexBinaryAdapter();
byte[] bytes = adapter.unmarshal(hexString);
return bytes;
}
I get this code from this link and this one.
I found answer:
I replace this code and it works:
CTFonts fonts = CTFonts.Factory.newInstance();
fonts.setAscii("IRnazanin");
fonts.setHAnsi("IRnazanin");
fonts.setCs("IRnazanin");
rpr.setRFonts(fonts);
It's thought that the solution has been defined already. I'd like to think so but unfortunately the results are the same trying yet a 3rd solution produced no change to the text color...
..
I'm trying to change the color of a certain word in a JTextPane (to red) to
show it's status. There are a number of examples and I've tried several but the end result is either the text remains unchanged or the entire text's color changes.
I will place a snippet of code here because the class is rather large
..
textPane = new JTextPane();
textPane.setFont(new Font("Arial", Font.PLAIN, 12));
..
String productName = "PC";
String vendorName = "DELL";
String statusOfProd = "OFF";
String theObject = "Product " + productName + " Vendor " + vendorName;
String taData = theObject + "\n";
textPane.setText(taData);
if (statusOfProd.equals("OFF")){
addColor2Pane(productName, Color.RED);
}
..
private void addColor2Pane(String value2Change, Color color2Use) {
String theData = textPane.getText();
int v2cIndex = theData.indexOf(value2Change);
int v2cLen = value2Change.length();
try {
textPane.getHighlighter().addHighlight(v2cIndex, v2cIndex + v2cLen,
new DefaultHighlighter.DefaultHighlightPainter(color2Use));
}
catch (BadLocationException e) {
e.printStackTrace();
}
}
..
// Attributes
protected JTextPane textPane;
public static String taData;
The result of the above method has no effect. If I change the "addColor2Pane"
method to below the result renders all text in the pane RED which is not what I'm trying to achieve.
..
private void addColor2Pane(String value2Change, Color color2Use) {
StyleContext sc = StyleContext.getDefaultSytleContext();
AttributeSet aSet = sc.addAttribute(sc.getEmptySet(),
StyleConstants.Foreground,
color2Use);
aSet = sc.addAttribute(aSet,
StyleConstants.FontFamily,
"Lucida Console");
aSet = sc.addAttribute(aSet,
StyleConstants.Alignment,
StyleConstants.ALIGN_LEFT);
int v2cInd = theData.indexOf(value2Change);
int v2cLen = value2Change.length();
textPane.setCaretPosition(v2cInd);
textPane.setCharacterAttributes(aSet, true);
textPane.replaceSection(value2Change);
}
The desired result is ONLY have the color of the productName set to RED. Suggestions?
I develop some project, it works for tagging a words when i drag the words and click special button.
I want to make tags surrounding a word (begin & end tags with red color) (please refer exam picture, this)
but when it tagged at begin & end of text, it take null-spaces (like picture 2nd).
when I drag that spaces, there's no real space(white space or " " or "\nbsp" - no, never), that's just null space!
I can't select that space!
Pic. Link here
here's my code below:
attribute:
static final Color TAG_COLOR = new Color(255, 50, 50);
static final Color PLAIN_TXT_COLOR = new Color(0, 0, 0);
public static SimpleAttributeSet plainAttr = new SimpleAttributeSet();
public static SimpleAttributeSet tagAttr = new SimpleAttributeSet();
StyleConstants.setAlignment(plainAttr, StyleConstants.ALIGN_JUSTIFIED);
StyleConstants.setForeground(plainAttr, PLAIN_TXT_COLOR);
StyleConstants.setFontSize(plainAttr, 11);
StyleConstants.setBold(plainAttr, false);
StyleConstants.setAlignment(tagAttr, StyleConstants.ALIGN_JUSTIFIED);
StyleConstants.setForeground(tagAttr, TAG_COLOR);
StyleConstants.setFontSize(tagAttr, 11);
StyleConstants.setBold(tagAttr, true);
tagging function:
public static void tag_functiont() {
String taggedName = "tagMark";
int start_sel = mainEditText.getSelectionStart();
int end_sel = mainEditText.getSelectionEnd();
String selected = mainEditText.getSelectedText();
StyledDocument doc = mainEditText.getStyledDocument();
if(selected == null || selected.isEmpty()) return;
try {
String bTag = "__B:"+taggedName+"__";
String eTag = "__E:"+ taggedName +"__";
doc.insertString(start_sel, bTag, tagAttr);
doc.insertString(start_sel+bTag.length()+selected.length(), eTag, tagAttr);
} catch (Exception e) {
e.printStackTrace();
}
}
I also worked all possibility of attributes options.
(some kinds of fonts, all kinds of arrangement;center, right, left, justified )
could someone gimme a piece of advice???
Solved
I added " textPane.setContentType("html/text"); in main source, so foolish.
it triggered <p> & <div> tags.. so the paragraph are gone bad.