Drawing diagonal line in a cell of a table in iTExt? - java

I'm creating a table in iText, but I've a problem with a cell that could be divided by a diagonal line. Someone know how can I do that?

The easiest way would be via an onGenericTag handler in a PdfPageEvent.
You give the contents of that cell a generic tag via Chunk.setGenericTag(String tag), and set up a PdfPageEvent hanlder that will draw your line when that chunk is drawn.
Something like:
public class MyPdfPageEvent extends PdfPageEventHelper {
public void onGenericTag(PdfWriter writer, Document doc, Rectangle rect, String tag) {
PdfContentByte canvas = writer.getDirectContent();
canvas.saveState();
canvas.setColorStroke(Color.BLACK); // or whatever
// You can also mess with the line's thickness, endcaps, dash style, etc.
// Lots of options to play with.
canvas.moveTo(rect.getLeft(), rect.getBottom());
canvas.lineTo(rect.getRight(), rect.getTop());
canvas.stroke();
canvas.restoreState();
}
}

Well. The answer of #Mark Storer was helpful, in this case there was a cell of a table I used "PdfPCellEvent" to inherid this methods.
Thanks Mark!

Related

iText placement of Phrase within ColumnText

So I'm dealing with a situation where I have a Phrase added to a ColumnText object.
The title in black is where iText is placing the text of the Phrase within the ColumnText. The title in pink is the desired placement.
private void addText(PdfContentByte contentByte, PdfReader threePagesReader, Project project, CoverTemplate coverTemplate)
throws DocumentException {
ColumnText columnText = new ColumnText(contentByte);
// This only affects the space between Phrases, not the space between the top of the
//ColumnText and the first Phrase
int extraParagraphSpace = 12;
columnText.setExtraParagraphSpace(extraParagraphSpace);
Phrase mainTitle = new Phrase(project.getTitle(),buildCoverFont(coverTemplate.getFontSizeLine1()));
columnText.addText(mainTitle);
... <other code that is not pertinent to this question>
//these values are calculated from values that will place this columnText onto the PDF
//template
columnText.setSimpleColumn(llx, lly, urx, ury);
columnText.go();
private Font buildCoverFont(float fontSize) {
Font font = FontFactory.getFont(FONT_ARIAL, BaseFont.WINANSI, BaseFont.EMBEDDED, fontSize, Font.NORMAL, CMYK_BLACK);
BaseFont baseFont = font.getBaseFont();
if (baseFont != null) {
baseFont.setSubset(false); // fully embedded as per requirements
}
return font;
}
Is there anything I can do to tell iText not to put any space between the top of the highest glyphs (D and Z in this case) and the top of the ColumnText box?
I tried looking at the BaseFont.getAscension() to see if there was any value available, but it ended up 0 anyway.
Please take a look at the ColumnTextAscender example:
In both cases, I have drawn a red rectangle:
rect.setBorder(Rectangle.BOX);
rect.setBorderWidth(0.5f);
rect.setBorderColor(BaseColor.RED);
PdfContentByte cb = writer.getDirectContent();
cb.rectangle(rect);
To the left, you see the text added the way you do. In this case, iText will add extra space commonly known as the leading. To the right, you see the text added the way you want to add it. In this case, we have told the ColumnText that it needs to use the Ascender value of the font:
Phrase p = new Phrase("This text is added at the top of the column.");
ColumnText ct = new ColumnText(cb);
ct.setSimpleColumn(rect);
ct.setUseAscender(true);
ct.addText(p);
ct.go();
Now the top of the text touches the border of the rectangle.

Change line spacing in JTextArea (not JTextPane)

I'm trying to find a way to change the line spacing in a JTextArea component.
A little bit of searching always seems to reveal the same answer: "Use a JTextPane instead and then call setParagraphAttributes".
But I'm wondering whether it's possible to achieve this with just a JTextArea by, for example, messing with the font.
With the deriveFont(...) method, it's possible to change the tracking and the kerning of the font, i.e. the horizontal spacing between characters, but I haven't been able to find a way to change the vertical spacing (maybe ascent, descent, leading). Am I missing something there?
As camickr pointed out, JTextArea does not provide a way to change the line height directly. It simply uses the font height provided by the corresponding FontMetrics.
But, this leaves a point of attack open using the following helper-class:
public class FontMetricsWrapper extends FontMetrics {
private final FontMetrics target;
public FontMetricsWrapper(FontMetrics target) {
super(target.getFont());
this.target = target;
}
#Override
public int bytesWidth(byte[] data, int off, int len) {
return target.bytesWidth(data, off, len);
}
#Override
public int charWidth(char ch) {
return target.charWidth(ch);
}
#Override
public int charWidth(int codePoint) {
return target.charWidth(codePoint);
}
// ... tons more #Override's, all of the same form:
//
// #Override
// public baz foo(bar, ...) {
// return target.foo(bar, ...);
// }
}
Then, it becomes possible to create the JTextArea like this:
JTextArea myTextArea = new JTextArea("Some text") {
#Override
public FontMetrics getFontMetrics(Font font) {
return new FontMetricsWrapper(super.getFontMetrics(font)) {
#Override
public int getHeight() {
return 10; // Gives line height in pixels
}
};
}
};
This is definitely not the cleanest solution and is merely meant as proof of concept. For example, one issue is that getFontMetrics(...) is called quite often, and, in the given example, creates a new instance of the wrapper class each time. So, at the very least, a HashMap that caches the created FontMetricsWrapper for each given font would be in order...
But, what I was really hoping for was a way to play with the Font or maybe the associated FontRenderContext passed into the JTextArea to modify the line height. For example, is there some way to influence font's reported ascent, descent, and leading values? Seems strange that you can change pretty much any other aspect of the font's appearance, except this one...
What's wrong with light-weight coding?
Nothing, you should use the simplest component for the job. But if the simple component doesn't support a requirement it is usually because the requirement is more complex and you need a more complex component to implement the functionality. Rarely would it be as simple at setting a property of a class.
Sometimes I'm simply interested in learning something new and figuring out what's possible.
Swing text components use a View to paint the text. It is the view's responsibility to format and position the text. So each view determines when to wrap and where to position the next line.
In the case of a JTextArea it uses either a Plainview or a WrappedPlanView. For the Plainview the painting code is:
drawLine(line, g, x, y);
y += fontHeight;
where the fontHeight is determined by using the FontMetrics.getHeight() method.
So the value is basically hard coded in the View. You could always provide a custom View for your text area, but overriding a View is generally not an easy task.

iText 5 header and footer

how I can add in my PDF page the header and the footer?
I wanna a table with 3 column in header and other table, 3 column in the footer.
My page could be A3 or A4, and landscape or portrait.
Can anyone help me? I can not found on internet good examples.
Thanks!
Tommaso
Create a class MyPageEventListener that extends PdfPageEventHelper
Add a page event listener to the PdfWriter object
In the onEndPage method of MyPageEventListener class, put the code
for header/footer
Example:
public class MyPageEventListener extends PdfPageEventHelper {
. . .
#Override
public void onEndPage(PdfWriter writer, Document document) {
//code skeleton to write page header
PdfPTable tbl = new PdfPTable(3);
tbl.addCell("1st cell");
tbl.addCell("2nd cell");
tbl.addCell("3rd cell");
float x = document.leftMargin();
float hei = getMyHeaderHeight(); //custom method that return header's height
//align bottom between page edge and page margin
float y = document.top() + hei;
//write the table
tbl.writeSelectedRows(0, -1, x, y, writer.getDirectContent());
}
}
to register the listener simply do
writer.setPageEvent(new MyPageEventListener());
The easiest way to do this is first generate the contents of your entire PDF in memory, then once all the pages have been created you need to open the in-memory PDF in the pdfStamper and iterate through all the pages adding in the header and footer objects are the correct coordinates.
If you do a quick google search of adding page numbers in itextPDF you will find a number of examples that you can quickly adapt for your needs.
The key is that it is done after you create the pdf, not before.

sorting arrows jtable column header

Does anyone know how to implement the up and down arrows of a JTable column header while sorting its rows?
I have made my own way of sorting and it is triggered by listening to mouse clicks by mouseadapter and the only things that is left is the visibility of such arrows on the header...
Is there also a way to easily implement a sortable jtable?
I finished doing all the sorting and one last thing that i can't do is show the sorting arrows..
i don't want to make a new one but i failed to find if there is an setEnableArrow or something..
any ideas about this?
You can take a look in the source code of the DefaultTableCellHeaderRenderer. In the getTableCellRendererComponent you see from where those icons are retrieved (e.g. UIManager.getIcon("Table.ascendingSortIcon")) and how this icon is set (setIcon(sortIcon);)
I suggest you don't mess up with the DefaultTableCellHeaderRenderer. The problem with this one, is that it's just that, the default. Each LaF is supposed to create a subclass of this one and do its own rendering there. My suggestion is to use a LaF that provides this functionality out of the box. I think that TinyLaf can do this but I'm not sure. You can subclass DefaultTableCellHeaderRenderer but you risk alienating the header rendering from the rest of the LaF.
So how to do it? Unicode to the rescue! Refer to the geometric shapes page and use what you like. I picked the '\u25B2' and '\u25BC' triangles. But then I had to hide the dreaded Swing icon:
UIManager.put( "Table.ascendingSortIcon", new EmptyIcon() );
UIManager.put( "Table.descendingSortIcon", new EmptyIcon() );
Be very careful with the above lines! They will replace the icons for all JTables in your application which might not be what you want. Then you should be able to see something like that:
Empty Icon can be like:
class EmptyIcon implements Icon, Serializable {
int width = 0;
int height = 0;
public void paintIcon(Component c, Graphics g, int x, int y) {}
public int getIconWidth() { return width; }
public int getIconHeight() { return height; }
}
This is the easiest way to implement sorting:
MyModel model = new MyModel();
TableRowSorter<MyModel> sorter = new TableRowSorter<MyModel> (model);
jTable1 = new javax.swing.JTable();
jTable1.setRowSorter(sorter);
jTable1.setModel(model);
What if you use JXtable instead of a Jtable?
these tables have the arrows in the header to sort them and they are easy to use...
worth trying...

Inserting Image onCloseDocument

I'm trying to insert an image in the footer of my document using iText's onCloseDocument event. I have the following code:
public void onCloseDocument(PdfWriter writer, Document document) {
PdfContentByte pdfByte = writer.getDirectContent();
try {
// logo is a non-null global variable
Image theImage = new Jpeg(logo);
pdfByte.addImage(theImage, 400.0f, 0.0f, 0.0f, 400.0f, 0.0f, 0.0f);
} catch (Exception e) { e.printStackTrace(); }
}
The code throws no exceptions, but it also fails to insert the image. This identical code is used onOpenDocument to insert the same logo. The only difference between the two methods are the coordinates in pdfByte.addImage. However, I've tried quite a few different coordinations in onCloseDocument and none of them appear anywhere in my document.
Is there any troubleshooting technique for detecting content which is displayed off-page in a PDF? If not, can anyone see the problem with my onCloseDocument method?
Edit: As a followup, it seems that onDocumentClose puts its content on page document.length() + 1 (according to its API). However, I don't know how to change the page number back to document.length() and place my logo on the last page.
The solution which worked for me (the question's author) is changing onCloseDocument to onParagraphEnd (since my document only has one paragraph).

Categories

Resources