Problem with viewToModel()

S

Sascha Konrad

Hello,

I have a JTextPane where I want to determine the position of the mouse.
So if there is a mouse moved event, I will do

int hoverPosition = jCurrentSentencePane.viewToModel(e.getPoint());

to determine the position (as the position of the letter) in the text
pane over which the mouse hovers. Now I have the problem that this
method returns bogus values if the mouse is somewhere in the text pane,
but not on the text. E.g., when I slowly approch the text somewhere
from the top, it tells me 0 as the hoverPosition, from the bottom it
tells me 35 (the length of my text). I was expecting to receive -1 or
so when I am not over the text, not the beginning or end of my text.
Does anybody have any suggestions?

Thanks.
 
C

Christian Kaufhold

Sascha Konrad said:
I have a JTextPane where I want to determine the position of the mouse.
So if there is a mouse moved event, I will do

int hoverPosition = jCurrentSentencePane.viewToModel(e.getPoint());

to determine the position (as the position of the letter) in the text
pane over which the mouse hovers. Now I have the problem that this
method returns bogus values if the mouse is somewhere in the text pane,
but not on the text. E.g., when I slowly approch the text somewhere

It is (where?) expected to make a closest guess. This may not always
be implemented in an optimal way.
from the top, it tells me 0 as the hoverPosition, from the bottom it
tells me 35 (the length of my text). I was expecting to receive -1 or
so when I am not over the text, not the beginning or end of my text.
Does anybody have any suggestions?

Use modelToView() on the result and check whether the point is near there.
Actually, use getUI().viewToModel() to also get aware of the bias.



Christian
 
S

Sascha

Hi Christian,

Thanks for your replay.

I found out that when I call jCurrentSentencePane.setMargin(0,0,0,0),
everything works as expected. Now, I was wondering if I can find out
the rectangle of the displated text in the JCurrentTextPane. If that is
possible, then I can just ignore the mouse being on the margin. But I
have not found out how to do that. I can call the JTextArea to get the
size of the margin, but I don't know how to obtain the heigth and width
of the text. (I.e., the right and lower boundary of the displayed
text). Any ideas?

Thanks
 
C

Christian Kaufhold

Sascha said:
Thanks for your replay.

Please quote some context.

I found out that when I call jCurrentSentencePane.setMargin(0,0,0,0),
everything works as expected. Now, I was wondering if I can find out
the rectangle of the displated text in the JCurrentTextPane. If that is
possible, then I can just ignore the mouse being on the margin. But I
have not found out how to do that. I can call the JTextArea to get the
size of the margin, but I don't know how to obtain the heigth and width
of the text. (I.e., the right and lower boundary of the displayed
text). Any ideas?


Untested!:


JTextComponent t = ...;

Insets n = t.getInsets();

Rectangle r = new Rectangle(n.left, n.top, t.getWidth() - n.left - n.right, t.getHeight() - n.top - n.bottom);

View v = t.getUI().getRootView(t);

Shape textShape = v.modelToView(v.getStartOffset(), Position.Bias.Forward, v.getEndOffset(), Position.Bias.Backward, r);



Christian
 
S

Sascha

Christian, thanks for your efforts, but your solution still does not
work, you still get the width and heigth of the whole text pane.

But you pointed me in the right direction and I think I got it now. You
need to look at each row of each paragrah individually (i only have one
paragrah), determining the width and heigth of this row. Then you
create a new rectangle based on the width of the current row and the
heigth of this row and all previous rows.

Here is the code, in case anybody is interested. It works fine for me
and sets the boolean variable hit to true if the mouse is positioned
over text:

boolean hit=false;

Insets n = jCurrentSentencePane.getInsets();
Rectangle r=new Rectangle(n.left,n.top,0,0);

View sectionView =
jCurrentSentencePane.getUI().getRootView(jCurrentSentencePane).getView(0);

int paragraphCount = sectionView.getViewCount();

for (int paragraphIndex = 0; paragraphIndex < paragraphCount;
paragraphIndex++) {
View paragraphView = sectionView.getView(paragraphIndex);
if (paragraphView instanceof ParagraphView) {
ParagraphView newparagraphView = (ParagraphView) paragraphView;
int rowCount=newparagraphView.getViewCount();
//oldHeigth contains the height of the previous row and is used to
update the y position
int oldHeight=0;
for (int rowIndex = 0; rowIndex < rowCount; rowIndex++) {
View rowView= newparagraphView.getView(rowIndex);

r.width=(int) rowView.getPreferredSpan(View.X_AXIS);
r.y=r.y+oldHeight;
r.height=(int) (rowView.getPreferredSpan(View.Y_AXIS));

if(r.contains(e.getX(),e.getY()))
{
//The point was in the rectangle, i.e. mouse is over text
hit=true;
break;
}

oldHeight=(int) rowView.getPreferredSpan(View.Y_AXIS);
}
}
}

It's mighty complicated though, I would be happy to see a simpler
solution.

-- Sascha
 
C

Christian Kaufhold

Sascha said:
Christian, thanks for your efforts, but your solution still does not
work, you still get the width and heigth of the whole text pane.

Again, please quote some context.


AFAICS, the reason my code does not work is a broken (?) optimization in
CompositeView.

Use getEndOffset() - 1 instead of getEndOffset(), then it is not used,
and it does not matter.



Christian
 
S

Sascha

Wow, thanks Christian, it works now, you're the Swing master. I guess I
haven't really understoof this whole concept of views and models.
Thanks again for your help.

-- Sascha
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,014
Latest member
BiancaFix3

Latest Threads

Top