How to get Paragraph absolut coordinates with iText? - java

I need to get absolute coordinates of paragraph that I already added to the document and join an image near that.
Generally my problem is below:
I have a checklist with images (checked/unchecked) before each line. I already did that but if check item takes for example 2 lines, then second line starts from the begining of the page. What I want is to start this second line from position that first line is starting. It is equal to if the second line will have a margin.
Thanks in advance!

I think your question is wrong. Allow me to explain: you have a specific requirement: you want to start a line with an image (representing a checked/unchecked check mark) that acts as a bullet. More specifically: you want the text that follows the bullet to be aligned correctly. That is a valid requirement.
However, in your question, you're asking about a specific implementation. You want to juggle with Y positions (check if a paragraph takes one or more lines) and X positions (start the second line using a specific indentation).
While it would probably be possible to achieve what you want using page events (asking a paragraph for its start and end postion), I think you are actually asking for functionality that is available out of the box: why not use a List with an image chunk as bullet?
I've written some sample code, ListWithImageAsBullet, where I use a light bulb as bullet (in your case, you'd use a checkbox image). I've added three items to the List and the second item takes more than one line. As you can see, the second line is indented correctly (you can augment the indentation using different methods available in the List class).
Please take a look at the resulting PDF. Is that what you're looking for?
If so, this is how it's done:
Image image = Image.getInstance(IMG);
image.scaleAbsolute(12, 12);
image.setScaleToFitHeight(false);
List list = new List();
list.setListSymbol(new Chunk(Image.getInstance(image), 0, 0));
list.add("Hello World");
list.add("This is a list item with a lot of text. It will certainly take more than one line. This shows that the list item is indented and that the image is used as bullet.");
list.add("This is a test");
document.add(list);
Note that I scaled the image to 12 by 12 pt, because 12pt is the default font size. Also don't forget to disable the automatic scaling of the image (otherwise, you'll end up with really tiny images as bullets).

Related

How to determine coordinates of multi-line text in PDF

I am using Apache PdfBox 2.0 in order to parse a pdf file. Having some fixed strings, I was able to create a system based on:
A fixed text, as a starting point
The next cell/text position, or null
The bottom area, to determine the height of the rectangle.
Using the starting point, I am computing the x and y (see below pic for pdf structure in PDF Box:
Using the "next" text block (which is another fixed value, for example a field or a table header), I am determining the width of the desired region, using formula:
width = second.x - first.x
or something similar. So, in a table, for example, knowing in advance the header names, it's easy to detect the columns. What I am trying to do (and so far fail to do so in an accurate way) is to determine the lines in a pdf table. This table sometimes contains missing values in some columns and also multiple lines values for some rows/columns. I have extended my "system" (first, next, bottom) to work dinamycally with table rows, and this works great when I have "normalized" tables (e.g. no whitespaces and/or at least, no multiple line values). But it's not working with real world data, because so far I could not find a way of determining the location (x, y, width, height) of a multi-line value. Is this even possible with PDF Box? Some people suggested to convert the pdf to html first and then to parse the html instead. Is this a viable option? Has anyone worked with this library? I will try to use this next.
Like I said in my previous comments, I have found a partial solution for my issue. This is based on two things:
First, I assume that one column for each table contains only distinct values which never occupy more than 1 row.
Next, since I also have some fixed texts in the document, I have determined these texts coordinates and use them as a delimiter of the area which contains the text I want to extract. For example, the "current, next, bottom" system (as I call it) can contain for example: "Column name A", "Column name B", "Fixed text C" (or second row from the same table - determined based on the unique single-row values).
It is not perfect, and problems may occur if the fixed texts may occur more than once in the document. Of course, improvements can be made by filtering the correct occurrence using the vertical coordinates and so on, but for the moment, I will close this question, as it seems that this problem has no standard answer and currently there is no open source library able to extract tabular data from pdfs.

JTextArea: how to translate row, column to offset? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Rows in JTextArea
In JTextArea, operations such as select, highlight and so on seem all to depend on offset from beginning of text. In an app that displays line-oriented text, I need to select, highlight (based on info from elsewhere, not caret) based on row and column.
Is there some functionality built-in, or in some helper class, to get offset from row,col? I realize I could maintain separate data on line-start offsets etc and calculate row,col-->offset, but surely JTextArea (or its model) already knows this in order to display the text, so I'm persuaded there must already be a way to do this.
I did see examples that use something like this one, using textarea.viewToModel(new Point(x,y));, where x and y were purportedly row,col, but so far as I can see, x, and y are pixel coordinates, not row,col... so not sure what to make of that.
Clues? Thanks!
Edited: So the question has been closed under the impression of five commenters that this is a duplicate of other questions, which it is not. I did not ask about how to convert offset to row, col, nor about how to convert screen pixel coordinates to offset, which are the subjects covered in the other articles.
In case someone else stumbles in here looking for the answer to what I actually did ask, I've now discovered that it's as follows.
JTextArea has the functionality I expected to find, but evidently overlooked on earlier browsing: getLineStartOffset(int line) which will give the offset-from-start-of-text for a particular line (row) of text. To this one can easily add the char-posn-in-line, and thus arrive at the offset of a particular character.
A textArea contains a stream of text. There's no magic method that will locate a row/column in your text model, since that can be ambiguous if your text contains variable-width characters or different font sizes. You must maintain the data necessary to map from your idea of what a particular (row,column) means with regard to your data.
That's simple example of rectangular fragment selection http://java-sl.com/tip_vertical_selection.html
You can use javax.swing.text.Utilities.getRowStart()/getRowEnd() methods. First find start row offset for the row number. Then just add col number to get the offset.

open office api text size

I am using open office API with Java UNO. I need to get size of selected text in the document content (for example embedded pictures have own size in mm but text inserted via XText.insertString(...) method doesn't have any size).
In other words: I want to get size (preferably in mm) of the box which surrounds part of text (it can be whole paragraph or selected text via some type of cursor). Is there any possibility to achieve that?
After searching, I think there is no option to achieve this at the moment. For my purposes I write small method for getting height of the paragraph in 1/100 mm.
Here is how this method works:
Get XTextViewCursor of the XTextDocumment controller for going left/right.
Go to paragraph to measure.
Loop through paragraph getting each char. For each char do: check its height (CharHeight property of the paragraph); get XLineCursor from XTextViewCursor and check if there is end of the line - if is then add (to the result) biggest height of the character in line.
This is temporary solution (still wait for something better) and has number of bugs (example line-spacing different than single; paragraph should only contain text) but maybe it will be helpful for someone.

Restrict number of lines in html JLabel

I have a JLabel that needs to display some html-formatted text. However, I want to restrict this to being 4 lines long (and if so, provide a button to see everything).
So far, I've tried setting the maximum size manually or via a layout manager. However, both of these solutions can cause part of a line to be displayed.
edit: To add a little more details, I need to force 4 lines even when respecting line wrapping correctly, resizing components, and changing font sizes. I've considered handling resize/fontsize changes by replacing the label with a new one that fits correctly.
JLabel seems to handle incomplete tags well, so I could probably do something like a binary search on the input string finding which character would cause it to go over the 4 line limit (using FontMetric to determine how many pixels 4 lines would be), and then replacing an existing label with the new one. The big downside to this approach is that I need to run the computation every time the user resizes the panel or changes fonts (and it feels like a dirty dirty hack).
Add the JLabel to a JScrollPane as set the scrollpane with a reasonable preferred size. Scrollbars will appear a necessary.
I don't know of any absolute solution to the questions since I doubt you can define what a "line" is. One line of text may be font 12 and another 24. I don't know of any way to calculate the height of each given line.
Even if you did use a ComponentListener to handle the componentResized() event I'm not sure you can come up with a reasonable algorithm to to calculate the exact width/height of of a 4 line display.
I would try running through the String of text and removing all text after the third "\n"
String shortenText(String oldtext){
String newText = "";
for(int i=0;i<3;i++){
newText += oldtext.substring(0,oldtext.indexOf("\n"));//adds one line to String
oldtext = oldtext.substring(indexOf("\n")+1);//shorten old string to prepare for next iteration
}
return newText;
}
You may also want to try the same algorithm, except strip of <p> and <br> tags as well...
If you know the values of the possible tags just switch the text from "\n" to "<br>" or any tag you need
Hey, I found a way that works. The framework I'm working with allows me to create a listener for font size changes. In this listener, I determine what the new max size of the label is (getFontMetrics(font).getHeight() * 4) and then re-set the maximum height on the label to this and then relayout everything. This even handles the word wrap case well. I'm guessing that someone could do nasty things with silly HTML input, but this covers the 99% case pretty well.

Reading from Java JTextArea

Okay, thus may seen kind of odd, but I wanted to get some suggestions from everyone here. I am a beginning Java developer (after 2 years of ASP.NET web development) and I have recently began working on my first Java project - a calculator. I realize that their are tons of calculators out there, but I thought it would be a good beginner project.
Anyway, here is what I need help with. Currently, I am using a Scrolling JTextArea for display (instead of a simple JTextField) that is approximately 5 rows tall. I want the user to be able to scroll through the list to see previous entries and such. The format of the box will be equation on one line and the program will generate the answer on the next and so on.
My real question is, how is the best way to implement this? My fist idea was to read through the JTextArea when equals is pressed, down to the last line and try to search that line for the operator (+, -, etc.) and the operands. Is this the best way to go about this? Although, this would work would work, I think it could get cumbersome and sounds very inefficient. I am open to any suggestions, even possibly replacing the JTextArea is some other component would work better.
Thanks!
There's no need to read through the JTextArea contents - use JTextArea.append() to add to the end. Here are some examples of JTextArea content manipulation:
JTextArea ta = new JTextArea("Initial Text");
// Insert some text at the beginning
int pos = 0;
ta.insert("some text", pos);
// Insert some text after the 5th character
pos = 5;
ta.insert("some text", pos);
// Append some text
ta.append("some text");
// Replace the first 3 characters with some text
int start = 0;
int end = 3;
ta.replaceRange("new text", start, end);
// Delete the first 5 characters
start = 0;
end = 5;
ta.replaceRange(null, start, end);
If you are open to different interfaces, you might want to try something like a JTextField at the top of your view, from which you can receive as input your 'new' inputted equation, and then below it with the same width a JList that would scroll to have all of the previous equations and their results. That would make parsing of the current formula much easier, and you would also have an easy time of keeping your previous formula and their results in a scrollable list, with the easy option of keeping the most recent on top.
your idea is interesting. so you would have a line such as.
2+2
then when pressing calculate would add the line
4
and so on then you could type in another equation.
it could work but as you said it wouldn't be the most efficient implementation... but that's just a tradeoff of getting the desired functionality.
If i were going to implement it the way you discribed (with a JTextArea) I'd use scanner, and scan the value string a line at a time.
if the line has +/- in it then do the calculation and add both the original line and the answer to a string.
the new string is the new value of the text field.
this method would get pretty cumbersom as you would be continually recalculating the users old entries more were added.
I guess if you continually stored the last line of the document, when you run out of lines, calculate the last stored and append the answer, then it wouldn't be so bad.
Here's what I would do:
use a JTextField to enter in the calculations, and a JList to display the old ones and their answers.
You could treat each line as a single operation. That way you could use the String array returned directly by:
String [] operations = textArea.getText().split("\n");
And then you'll know that exactly each one of them as a complete operation ( may be invalid, but that' another story )
Is this what you asked or do I totally misread you?
I think a simpler solution would actually use two components. A TextArea to hold the "history" of what's happened so far, and a textfield where the user inputs new entries.
Thanks to everyone who replied. You all gave me some ideas to think about. I think right now, I am going to go with my original idea of using a single JTextArea and try to find ways to optimize the process. If that gets too difficult (which is very possible), I will follow the majority's advice and use two separate fields. Thanks for replying everyone!

Categories

Resources