Skip to main content

JTextPane

81 replies [Last post]
freesoft_2000
Offline
Joined: 2005-09-06
Points: 0

Hi everyone,

I have a question about doing something. I have a jtextpane that you can type text and all but i need to create something like microsoft's word 2000 in where i can view the entire print layout of the jtextpane as a print layout but also be able to continue typing my text on that particular print layout.

It is something like word 2000 in which you can click to view in print layout. It is something like a print preview but i will still be able to type the text on the print preview.

The thing is i really am not sure on how to go about doing this. Do i need to create a custom jcomponent or simply create a renderer for the jtextpane(not sure if this is possible). Basically i am really open to ideas on how i can achieve this.

Links to sample codes would be great if possible

Thank You

Yours Sincerely

Richard West

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
freesoft_2001
Offline
Joined: 2006-03-11
Points: 0

Hi everyone,

Stanislav or is anyone else there?
Or has this thread just no longer being respond to
Anyone at all

Richard West

stanislavl
Offline
Joined: 2003-06-17
Points: 0

>I didn't know you were writing your own glyph painter as well. Where are you going to list it once you have finished?
I'm not writing it. I wouls write it. I just glanced on the GlyphPainter1 code.

I have written a custom GlyphPainter but I have no permissions to share the code. And the painter isn't what you actually need.

As for scaling images I think it's ok. Not a bug. You can try to scale the image by some another image editor tool and see whether the effect is the same. (I guess it will be the same). Also you cn try to play with rendering hints of your graphics instance to achieve more smooth scaling.

regards,
Stas

stanislavl
Offline
Joined: 2003-06-17
Points: 0

What about own GlyphPainter?

Are you writing it?

regards,
Stas

freesoft_2001
Offline
Joined: 2006-03-11
Points: 0

Hi everyone,

> What about own GlyphPainter?
>
> Are you writing it?

Haven't started it yet but it looks quite tough
Still trying to do research on it first

Hoping to hear from you

Yours Sincerely

Richard West

stanislavl
Offline
Joined: 2003-06-17
Points: 0

>Haven't started it yet but it looks quite tough
>Still trying to do research on it first
it isn't too difficult. I would write it in a few days.

You can take the existing code of GlyphPainter1 and just modify it. I glanced on the code. The only problem I see is Segment class using because of SegmentCache private class. but actually you need char[] array from the segment so ususal String can be used just from document.gettext(offset, len) method.

regards,
Stas

freesoft_2001
Offline
Joined: 2006-03-11
Points: 0

Hi everyone,

>I would write it in a few days.

I didn't know you were writing your own glyph painter as well. Where are you going to list it once you have finished?

Anyways i noticed another little problem.
You see if i saved a JTable as an image and later when i insert it into the scaled JTextPane when the scale is at 100% all looks fine but the image seems to become distorted like some grid lines missing if i start to scale the JTextPane by using your scaling code.

Now when i put the scaling of the JTextPane back to 100% everything is fine again and the image is not distorted

Why does this happen? Is there a way in which i can fix it? Or this something that is normal and nothing to worry about.

Hoping to hear from you

Yours Sincerely

Richard West

freesoft_2001
Offline
Joined: 2006-03-11
Points: 0

Hi everyone,

Sorry i wanted to add this.

Do you know of any open-source or free or some link on the internet for table views that can be used to insert tables into the Styled document of a JTextPane?

Hoping to hear from you

Yours Sincerely

Richard West

stanislavl
Offline
Joined: 2003-06-17
Points: 0

>Do you know of any open-source or free or some link on the internet for table views that can be used to insert tables into the Styled document of a JTextPane?

See src of HTMLEditorKit from sun.

regards,
Stanislav

paulmpr
Offline
Joined: 2003-08-19
Points: 0

Stas;

I'm not sure if you're still viewing this thread, but I have a basic question regarding inserting components into JTextPane.

Is there anyway to control where a component is displayed in JTextPane ( like an Icon ) other than where it's postion in the document model is located? To change that position 'on the fly', like a dnd operation, other than repositioning it in the document model?

And is there any possibility under ParagraphView to wrap text around an icon, instead of JTextPane's default method which at least visually breaks lines and inserts space depending on the size of the image?

Paul

freesoft_2000
Offline
Joined: 2005-09-06
Points: 0

Hi everyone,

stas you said this

> The method calculates where caret should be placed
> when you click in the JEditorPane.

Isn't that the purpose of the modelToView method as well.
Correct me if i am wrong.

On another issue which has nothing to do with scaling
let's say if i have three pages in my paginated
JTextPane and the cursor is on page 2 how do i get
the current page number the cursor is on. A rough
explanation would help

Yours Sincerely

Richard West

Anonymous

Tehre are two methods
1. modelToView - you have some position in the document and should show caret in appropriate page.

2. viewToModel - you click somewhere in the view and the view should determine what is caret position for the x and y. After that modelToView is called for obtained pos and caret is shown appopriately.

Second question.
The word cursor is ambiguous caret or mouse cursor?
Suppose you have mouse cursor and y coordinate. Then you have to page number=y/pageHeight+1

If you have caret just call modelToView to get caret rect and use y the same way as above.

regards,
Stas

freesoft_2000
Offline
Joined: 2005-09-06
Points: 0

Hi everyone,

> Second question.
> The word cursor is ambiguous caret or mouse cursor?

What i meant is that if the JTextPane is in a JScrollPane
and as i move the verticle scrollbar up and down is there a way in which i can get the current page number of the page currently in view in the JScrollpane.

Is there a way in which i can achieve this?

Richard West

Anonymous

Use scroll.getViewport().getViewRect().y

regards,
Stas

freesoft_2001
Offline
Joined: 2006-03-11
Points: 0

Hi everyone,

Stas i have one more question on this topic.

You see if you have three pages in your pagination how do you get the contents for each of the three pages and store them into a document array.

The real part that i am confused about is actually getting the contents of the three individual pages.

Hoping to hear from you

Richard West

ps. Do you have difficulty logging in. I can't seem to log into my previous freesoft_2000 username. Don't know why. Are you having the same troble as well

stanislavl
Offline
Joined: 2003-06-17
Points: 0

Actually document doesn't store the information at all. All pagination is done on views level. In fact views represent document's content in some custom form.

To get content of page you in fact need two offsets: start offset on page and end offset on page.

All the offets can be got by viewToModel() methods. You just have to specify proper coordinates (x=0 , y=page start Y ) for start offset and (x=page Width, y=page end Y) for end offset.

Could you tell me why do you need the info?

regards,
Stas

p.s. I have no problem to login.

freesoft_2001
Offline
Joined: 2006-03-11
Points: 0

Hi everyone,

> Could you tell me why do you need the info?

I intend to serialize each page of the document individually.

I have one more question but its rather on printing but bear with me for a while.

You see i trying to print a JTextPane by using the infamous DocumentRenderer class at this site

[url]http://www.fawcette.com/javapro/2002_12/online/print_kgauthier_12_10_02/[/url]

The thing is that everything prints well except embedded JComponents which i feel is an error due to the
below if statement(see the first if statement in the below class with my comments) in the below class.

[code]
protected boolean printView(Graphics2D graphics2D, Shape allocation, View view)
{
//This function paints the page if it exists

boolean pageExists = false;
Rectangle clipRectangle = graphics2D.getClipBounds();
Shape childAllocation;
View childView;

//This more likely where i think the error is
//but can't really confirm it

if((view.getViewCount() > 0))
{

for(int i = 0;i {

childAllocation = view.getChildAllocation(i,allocation);

if(childAllocation != null)
{

childView = view.getView(i);

if(printView(graphics2D,childAllocation,childView))
{
pageExists = true;
}

}

}

}

else
{
//The below if statement checks if there are pages currently to paint

if(allocation.getBounds().getMaxY() >= clipRectangle.getY())
{
pageExists = true;

if((allocation.getBounds().getHeight() > clipRectangle.getHeight()) &&
(allocation.intersects(clipRectangle)))
{
view.paint(graphics2D,allocation);
}

else
{

if(allocation.getBounds().getY() >= clipRectangle.getY())
{

if(allocation.getBounds().getMaxY() <= clipRectangle.getMaxY() - 15)
{
view.paint(graphics2D,allocation);
}

else
{

if(allocation.getBounds().getY() < pageEndY)
{
pageEndY = allocation.getBounds().getY();
}

}

}

}

}

}

return pageExists;
}
[/code]

This is the document structure i get when i try to get a
view dump

[code]
avax.swing.plaf.basic.BasicTextUI$RootView@1bbdd48section[0, 4] 12366398
PageableEditorKit$SectionView@5a3923section[0, 4] 12366398
PageableEditorKit$PageableParagraphView@15d616eparagraph[0, 2] 27766975
javax.swing.text.ParagraphView$Row@650892paragraph[0, 2] 27766975
javax.swing.text.ComponentView@115d06ccomponent[0, 1] 19309212
javax.swing.text.LabelView@17dc1cbcontent[1, 2] 20846071
PageableEditorKit$PageableParagraphView@11410e5paragraph[2, 3] 6371135
javax.swing.text.ParagraphView$Row@7244caparagraph[2, 3] 6371135
javax.swing.text.LabelView@23756content[2, 3] 25104891
PageableEditorKit$PageableParagraphView@175ade6paragraph[3, 4] 15462504
javax.swing.text.ParagraphView$Row@1f44ec7paragraph[3, 4] 15462504
javax.swing.text.LabelView@602b6bcontent[3, 4] 29530019
section[0, 4] 12366398
paragraph[0, 2] 27766975
component[0, 1] 19309212
content[1, 2] 20846071
paragraph[2, 3] 6371135
content[2, 3] 25104891
paragraph[3, 4] 15462504
content[3, 4] 29530019
ent[0, 1] 19321823
javax.swing.text.LabelView@2016b0content[1, 2] 11642082
section[0, 2] 12366398
paragraph[0, 2] 27766975
component[0, 1] 19321823
content[1, 2] 11642082
[/code]

Thus is an in teresting little method that i used to get the dump

[code]
public void dump()
{
View root =TextPane1.getUI().getRootView(TextPane1);
dumpView(root, 0);
dumpDoc(TextPane1.getDocument().getRootElements()[0],0);
}

private void dumpView(View root, int level)
{
for (int i = 0; i < level*2; i++)
System.out.print(' ');
System.out.print(root);
Element elem = root.getElement();
System.out.println(elem.getName() + "[" + elem.getStartOffset() + ", " + elem.getEndOffset() + "] " + elem.hashCode());
if (root.getViewCount() != 0)
for (int j = 0; j < root.getViewCount(); j++)
dumpView(root.getView(j), level+1);
}

private void dumpDoc(Element elem, int level)
{
for (int i = 0; i < level*2; i++)
System.out.print(' ');
System.out.println(elem.getName() + "[" + elem.getStartOffset() + ", " + elem.getEndOffset() + "] " + elem.hashCode());
if (!elem.isLeaf() && elem.getElementCount() != 0)
for (int j = 0; j < elem.getElementCount(); j++)
dumpDoc(elem.getElement(j), level+1);
}
[/code]

The thing is i do see the component in the document structure in the dump but still not JComponent when i print its not there. By the way i am using your version of the styled editor kit wwith pagination

Do let me know if you need the entire Document renderer code as sometimes the server is down

Sorry for asking you this question as i know its asking alot from you but you seem the only one capable of answering complex questions like these

I apologize if i seem to be haunting you with questions.

Looking forward from hearing from you

Yours Sincerely

Richard West

ps. Is there an administrator on this site??
If there is do you know his id so i can
pm him about me not being able to log in

stanislavl
Offline
Joined: 2003-06-17
Points: 0

Why do you need the page based serializing? for printing?

The problem with printing of embedded components is well known. Actually the problem is following:
[code]
public void paint(Graphics g, Shape a) {
if (c != null) {
Rectangle alloc = (a instanceof Rectangle) ?
(Rectangle) a : a.getBounds();
c.setBounds(alloc.x, alloc.y, alloc.width, alloc.height);
}
}
[/code]
paint() method of ComponentView doesn't paint the component but just set bounds of component. SO you have to get all the components added to container and call their paint() method if they are visible on currently printed page.

regards,
Stas

freesoft_2001
Offline
Joined: 2006-03-11
Points: 0

Hi everyone,

>
> The problem with printing of embedded components is
> well known. Actually the problem is following:
> [code]
> public void paint(Graphics g, Shape a) {
> if (c != null) {
> Rectangle alloc = (a instanceof Rectangle) ?
> (Rectangle) a : a.getBounds();
> c.setBounds(alloc.x, alloc.y, alloc.width,
> idth, alloc.height);
> }
> }
> [/code]
> paint() method of ComponentView doesn't paint the
> component but just set bounds of component. SO you
> have to get all the components added to container and
> call their paint() method if they are visible on
> currently printed page.
>
> regards,
> Stas

I still a bit hazy about your explanation.

Is this what you mean

[code]
class ComponentView extends BoxView
{

public ComponentView(Element elem)
{
super(elem);
}

public void paint(Graphics g, Shape a)
{
if (c != null)
{
Rectangle alloc = (a instanceof Rectangle) ?(Rectangle) a : a.getBounds();
c.setBounds(alloc.x, alloc.y, alloc.width, alloc.height);
}

}
[/code]

My first question is what is c??

My other question is how do i know what component to paint when i do not know what the component is??

But let's assume if the JComponent is a JEditorPane,
then how do i find where the component is. I mean after all i could have 10 or 20 embedded Jcomponents, does it mean i have to paint 10 to 20 times.

I think i have confused myself.

Maybe a small example would help if its of no inconvinience

Hoping to hear from you

Yours Sincerely

Richard West

stanislavl
Offline
Joined: 2003-06-17
Points: 0

ComponentView represent component inserted in a document. So when content of paragraph is layed out (by ParagraphView) a new ComponentView instance is created for each embedded component to render it. But it doesn't paint the component but specify some bounds - coordinates where the component must be located in the JEditorPane (appropriate place in paragraph's row).

Thus c is parent component represented by the view. For example submit button (JButton in fact) in HTML representation.

>My other question is how do i know what component to >paint when i do not know what the component is??

You must paint _all_ components with specific bounds. You know there is a page bounds in JEditorPane for each page.
x=0
y=pageNumber*pageheight
width=pageWidth
height=pageHeight

You have to get all components added to JEditorPane.

getComponentCount();
getComponent(int index); methods

For each component you have to check whether i is inside rendered page by checking bounds intersection with page's shape.

If it is you have to paint the component as well as editorPane.paint();

Steps to print as I can see them.
The print() method of printable passed pageIndex attribute. We use the index to translate content and create clip for passed graphics and then call editorPane.paint(g); to paint desired fragment (for appropriate page).

then iterate through the all components added to JeditorPane and check their bounds. for each of them translate coordinates to appropriate point and call
ampeddedComponent.paint(g)

regards,
Stas

regards,
Stas

freesoft_2001
Offline
Joined: 2006-03-11
Points: 0

Hi everyone,

Sorry stas i have another question,
you see i have managed to add tables in a rtf document successfully but here is the problem.

When i add your scaling code to it, i get an exception and nothing happens but when i remove your scaling code it works fine and the table are added.

The table views that i used are from tom sanders at the below link

[url]http://forum.java.sun.com/thread.jspa?forumID=57&threadID=473685[/url]

When i use the paginated editorkit with the table views all is good and the tables are added perfectly but only when i add the parts for scaling in the editorkit, the tables are not added and an exception is thrown but if i leave out the scalling part in the editorkit the tables are added and there is no problem.

The problem is that i don't really know what the exception mean and maybe you could shed some light on it

Here is the exception

[code]
java.lang.IndexOutOfBoundsException: levels.length = 5 start: 4 limit: 13
at sun.awt.font.BidiUtils.getLevels(Unknown Source)
at javax.swing.text.AbstractDocument.calculateBidiLevels(Unknown Source)
at javax.swing.text.AbstractDocument.updateBidi(Unknown Source)
at javax.swing.text.AbstractDocument.insertUpdate(Unknown Source)
at javax.swing.text.DefaultStyledDocument.insertUpdate(Unknown Source)
at javax.swing.text.AbstractDocument.handleInsertString(Unknown Source)
at javax.swing.text.AbstractDocument.insertString(Unknown Source)
at javax.swing.text.AbstractDocument.replace(Unknown Source)
at javax.swing.JTextPane.replaceSelection(Unknown Source)
at javax.swing.JTextPane.replaceSelection(Unknown Source)
at javax.swing.text.StyledEditorKit$StyledInsertBreakAction.actionPerformed(Unknown Source)
at javax.swing.SwingUtilities.notifyAction(Unknown Source)
at javax.swing.JComponent.processKeyBinding(Unknown Source)
at javax.swing.JComponent.processKeyBindings(Unknown Source)
at javax.swing.JComponent.processKeyEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.KeyboardFocusManager.redispatchEvent(Unknown Source)
at java.awt.DefaultKeyboardFocusManager.dispatchKeyEvent(Unknown Source)
at java.awt.DefaultKeyboardFocusManager.preDispatchKeyEvent(Unknown Source)
at java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(Unknown Source)
at java.awt.DefaultKeyboardFocusManager.dispatchEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Window.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
[/code]

What do you think is causing this problem?
is there a way in which this problem can be fixed?

Is there some thing i have to tweak viewToModel or modelToView? If yes what are they

Hoping to hear from you

Yours Sincerely

Richard West

stanislavl
Offline
Joined: 2003-06-17
Points: 0

I haven't met such a bugs before. According to stack trace the problem is in bidirectional levels calculations. I guess why that happens. When you added code for scaling you switched on bidi support (by using GlyphPainter2) so your tables need to calculate some bidi info.

Seems like you should specify correct info when table's elements are added in document structure.

Hope this helps.

regards,
Stas

freesoft_2001
Offline
Joined: 2006-03-11
Points: 0

Hi everyone,

>When you added code for scaling you switched on bidi >support (by using GlyphPainter2)

Yes you are absolutely right. The problem seem to come from this line
[code]
document.putProperty("i18n", Boolean.TRUE);
[/code]

but when i do the below the problem dissappears
[code]
document.putProperty("i18n", Boolean.FALSE);
[/code]

>so your tables need to
>calculate some bidi info.

How does one actually calculate the bidi like in my situation?

I have never come across this type of problem before
and i am ver unsure on how to proceed further withg this problem.

> Hope this helps.

It really helped alot and really shed a lot of light on this topic for me.

Hoping to hear from you

Yours Sincerely

Richard West

stanislavl
Offline
Joined: 2003-06-17
Points: 0

>How does one actually calculate the bidi like in my situation?

Unfortunately I don't know what really happens in you case. I have worked with bidirectional texts and multilanguage support but I've never met such bugs. Try to figure out the bidi info in your document and how it's created and processed.

See getBidiRootElement() method of AbstractDocument and check bidi elements structure.

regards,
Stas

freesoft_2001
Offline
Joined: 2006-03-11
Points: 0

Hi everyone,

Stas is there any way that i can avoid glyphpainter2??
glyphpainter2 seems to becausing alot of problems

Is there any other glyphpainters or ways that i could do that would give me the same effect of glyphpainter2 but avoid using it directly??

Hoping to hear from you

Richard West

stanislavl
Offline
Joined: 2003-06-17
Points: 0

Actually the GlyphPainter2 is required only to provide float measurements of texts (to provide correct caret navigation in scaled views).

Thus all you need is to write own GlyphPainter. The simplest way it to take code of GlyphPainter1 and modify some code.

The problem is the method
public float getSpan(GlyphView v, int p0, int p1,
TabExpander e, float x) {

int width = Utilities.getTabbedTextWidth(text, metrics, (int) x, e, p0);
this line provides rounded values only.

There might be some other places though. That's the first one.

regards,
Stas

freesoft_2001
Offline
Joined: 2006-03-11
Points: 0

Hi everyone,

Stanislavl, i have a question about your scaling code.

You see i am using a JTextPane with your scaling code but there is a problem. You see when i embed a JComponent in th JTextPane and use your scaling code the scaling works fine for all the formating and everthing else but it seems that the JComponents embedded in the JTextPane are not scaled.

Why does this happen and is there a way in which i can fix this problem so that the embedded JComponents in the JTextPane are also scaled with everything else.

Hoping to hear from you

Yours Sincerely

Richard West

stanislavl
Offline
Joined: 2003-06-17
Points: 0

Actually components scaling is much more difficult. The JEditorPane scaling code provide only scale of drawing (text and images). Components scaling requies also scaling of all mouse events.

I did some researching about the problem. You can find my suggestions there
http://forum.java.sun.com/thread.jspa?forumID=57&threadID=631652

regards,
Stas

freesoft_2001
Offline
Joined: 2006-03-11
Points: 0

Hi everyone,

> http://forum.java.sun.com/thread.jspa?forumID=57&threa
> dID=631652

The link above seems to be the scaling of JComponents in JPanel. For me the embedded JComponent is a JTextPane.

In other words i have a JTextPane embedded in another JTextPane.

I don't get how your code in the above link relates to this.

Does it mean that i have to get each invidual JTextPane that i have embedded in the original JTextPane and scale them and then reinsert them back or is there another way of doing it? Is there something i have to do in the editorkit as well?

I really hope you can clarify this for me

Hoping to hear from you

Yours Sincerely

Richard West

stanislavl
Offline
Joined: 2003-06-17
Points: 0

How do you add the interna JEditorPane? Do you create it? What about iterating through all the subcomponents and set them appropriate scale?

Sorry seems I don't understand your problem properly.

Could you write down a small compilable example of this?

regards,
Stas

freesoft_2001
Offline
Joined: 2006-03-11
Points: 0

Hi everyone,

> How do you add the interna JEditorPane? Do you create
> it?

For example this is what i do

[code]
TextPane k = new JTextPane();
TextPane L = new JTextPane();
L.setBackground(Color.blue);
k.insertComponent(L);
[/code]

Now i use the above JTextPane k with your scaled editorkit
combined with your pagination code but the JTextPane L is simply using the java standard RTF Editorkit

So basically i inserted L into k. Now when i scaled the JTextPane all is scaled except the embeded JTextPane L

My qusetion is simply what do i have to add to your existing scaling code so that the embedded JTextPane L is also scaled together with all the text and images in JTextPane k?

Hoping to hear from you

Yours Sincerely

Richard West

stanislavl
Offline
Joined: 2003-06-17
Points: 0

The simplest way I see is go through all the subcomponents of k and set their scale appropriately.

[code]
int n=k.getComponentCount();
for (int i=0; i //ComponentView creates a container where the real component is added
//so k.getComponent(i) returns the container creaed by ComponentView
//its first child is you component.
if (((JComponent)k.getComponent(i)).getComponent(0) instanceof JTextPane) {
JTextPane internalTextpane=(JTextPane)((JComponent)k.getComponent(i)).getComponent(0);

internalTextpane.setScale()
}
}

[/code]

regards,
Stas

freesoft_2001
Offline
Joined: 2006-03-11
Points: 0

Hi everyone,

> The simplest way I see is go through all the
> subcomponents of k and set their scale
> appropriately.

Sorry but going back to the scaling of embedded JComponents, i seemed to have run into some trouble

You see i decided to use your ZoomedPanel code at the below thread
http://forum.java.sun.com/thread.jspa?forumID=57&threadID=631652

Now this is what i did to insert the embedded JTextpane into the Original JTextPane called TextPane1

[code]
ZoomedPanel ZoomedPanel2 = new ZoomedPanel();
JTextPane L = new JTextPane();
L.setBackground(Color.blue);
ZoomedPanel2.setLayout(new BorderLayout());
ZoomedPanel2.add(L, "Center");
TextPane1.insertComponent(ZoomedPanel2);
[/code]

Now when it come time to scale this is what i did
to iterate all embedded components in the JTextPane

[code]
int j = 0;
int i = 0;

j = TextPane1.getComponentCount();

for(i=0;i {
ZoomedPanel ZoomedPanel1 = new ZoomedPanel();

// The below line i get an exception thrown
ZoomedPanel1 = (ZoomedPanel)TextPane1.getComponent(i);

ZoomedPanel1.scale = (float)0.5;
ZoomedPanel1.invalidate();
ZoomedPanel1.validate();
ZoomedPanel1.repaint();
}
[/code]

Now this is the exception thrown in the second code shown

[code]
xception in thread "AWT-EventQueue-0" java.lang.ClassCastException: javax.swing.text.ComponentView$Invalidator
[/code]

From what i know from the second code i did cast correctly but then why did i get the above exception?

Am i doing something wrongly or am i missing something?

Hoping to hear from you

Yours Sincerely

Richard West

stanislavl
Offline
Joined: 2003-06-17
Points: 0

I already wrote the answer in comment. Seems you didn't read it.
//ComponentView creates a container where the real component is added so k.getComponent(i) returns the container creaed by ComponentView its first child is you component.

regards,
Stas

freesoft_2001
Offline
Joined: 2006-03-11
Points: 0

Hi everyone,

> I already wrote the answer in comment. Seems you
> didn't read it.

Actually i saw it, this was what you meant right

[code]
int j = 0;
int i = 0;

j = TextPane1.getComponentCount();

for(i=0;i {
ZoomedPanel ZoomedPanel1 = new ZoomedPanel();

// The below line i get an exception thrown
ZoomedPanel1 = (ZoomedPanel)((JComponent)TextPane1.getComponent(i)).getComponent(0);

ZoomedPanel1.scale = (float)Scale;
ZoomedPanel1.invalidate();
ZoomedPanel1.validate();
ZoomedPanel1.repaint();
[/code]

The thing is i still get the same exception as below

[code]
Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: javax.swing.text.ComponentView$Invalidator
[/code]

Any idea why this happens as i am really have no idea why
because i seem to do ths casting correctly yet i still get the above exception.

Am i missing something?

Hoping to hear from you

Yours Sincerely

Richard West

stanislavl
Offline
Joined: 2003-06-17
Points: 0

You can try to get all the subtree of the component added to your JTextPane. Just use the same getComponentCount(), getComponent(int index), and getClassgetName() to obtain which classes are in the subtree. One of the subcomponents should be your panel.

regards,
Stas

freesoft_2001
Offline
Joined: 2006-03-11
Points: 0

Hi everyone,

Sorry but it seems another problem has popped up.

It seems that now the embedded ZoomedPanel
can be scaled but after scaling but the problem is that it now shifts outside the drawn pages(if i am using your paginated editorkit)and acts as its not part of the JTextPane.

Do you knopw why it behaves like that and is there a way in which i can fix this problem of shifting?

Hoping to hear from you

Yours Sincerely

Richard West

stanislavl
Offline
Joined: 2003-06-17
Points: 0

Never tied to combine boh the codes. The only idea i can guess is double scaling of graphics instance.

It's scaled in main JTextPane and the scaled once again in the second one.

Hope this helps.

regards,
Stas

freesoft_2001
Offline
Joined: 2006-03-11
Points: 0

Hi everyone,

> Never tied to combine boh the codes. The only idea i
> can guess is double scaling of graphics instance.

I checked it and nope its not being scaled twice.

Is there a way that i can remove an embedded JComponent from the JTextPane, rescale it(i know this part already),
and reinsert it at the same location where i got it from?

A little sample would really help if its of no inconvinience to you

Hoping to hear from you

Yours Sincerely

Richard West

stanislavl
Offline
Joined: 2003-06-17
Points: 0

>Is there a way that i can remove an embedded JComponent from the JTextPane, rescale it(i know this part already),
and reinsert it at the same location where i got it from?

Why do you need to remove component to rescale? If you found it embedded just scle it there.

>A little sample would really help if its of no inconvinience to you
Unfortunately I have no time to write any examples. I have to do my own tasks. I post some code if i have already written piece of code.

You can post your code (a small compilable example) and I'll try to fix bugs (if it doesn't need too much time). At least I will provide some advises about suspicious places.

regards,
Stas

freesoft_2001
Offline
Joined: 2006-03-11
Points: 0

Hi everyone,

> Why do you need to remove component to rescale? If
> you found it embedded just scle it there.

I wanted to do this because i feel this is only the best wa that i could do it without getting any undesired side effects.

You see if i use your paginated styled editorkit together with your zoomed panel class the embedded JTextPane shifts and nothing can be typed directly below the embedded JTextPane(according to its size) and the embedded JTextPane shifts from its original place.

Now if i use the default styled editorkit the JTextPane does not shift but the typing below the JtextPane problem still Occurs

> You can post your code (a small compilable example)
> and I'll try to fix bugs (if it doesn't need too much
> time).

I am posting a little compilable example where you can using your zomom panel class and the default styled editor kit.

You can also use you paginated editor kit to see the shifting problem if you want to

Here is the compilable example

[code]
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.awt.geom.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
import javax.swing.plaf.basic.*;
import javax.swing.text.rtf.*;

public class Pagination implements ActionListener
{

JFrame fr = new JFrame ("Frame");
JButton Button1 = new JButton("Insert Comp");
JButton Button2 = new JButton("Scale Comp 50%");
JButton Button3 = new JButton("Scale Comp 100%");

JTextPane TextPane1 = new JTextPane();

SimpleAttributeSet sas = new SimpleAttributeSet();

StyleContext sc = new StyleContext();

MutableAttributeSet mas;

DefaultStyledDocument dse = new DefaultStyledDocument(sc);

JScrollPane ScrollPane1 = new JScrollPane(TextPane1, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);

StyledEditorKit StyledEditorKit1 = new StyledEditorKit();

Dimension Size1 = new Dimension();

public void initialize ()
{
Container pane = fr.getContentPane();
pane.setLayout(new FlowLayout());
fr.setSize(250,300);
fr.setLocation(300,300);
fr.setBackground(Color.lightGray);

TextPane1.setEditorKit(StyledEditorKit1);

TextPane1.setDocument(dse);
Size1.width = 500;
Size1.height = 300;
ScrollPane1.setPreferredSize(Size1);
pane.add(ScrollPane1);
pane.add(Button1);
pane.add(Button2);
pane.add(Button3);
fr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

Button1.addActionListener(this);
Button2.addActionListener(this);
Button3.addActionListener(this);

fr.pack();
fr.setVisible(true);
}

public void actionPerformed(ActionEvent event)
{
JComponent b = (JComponent)event.getSource();

if(b == Button1)
{
ZoomedPanel ZoomedPanel1 = new ZoomedPanel();
JTextPane TextPane2 = new JTextPane();

ZoomedPanel1.setLayout(new BorderLayout());
ZoomedPanel1.add(TextPane2, "Center");

TextPane2.setBackground(Color.blue);
TextPane1.insertComponent(ZoomedPanel1);

TextPane1.grabFocus();
}

else if(b == Button2)
{
ZoomedPanel ZoomedPanel2 = new ZoomedPanel();

Toolkit.getDefaultToolkit().getSystemEventQueue().push(ZoomedPanel2.new MyEventQueue());

int j = 0;
int i = 0;

j = TextPane1.getComponentCount();

for(i=0;i {
ZoomedPanel2 = (ZoomedPanel)((Container)TextPane1.getComponent(i)).getComponent(0);
ZoomedPanel2.scale = (float)0.5;

ZoomedPanel2.validate();
ZoomedPanel2.repaint();
}

TextPane1.revalidate();
TextPane1.repaint();
fr.validate();
fr.repaint();

TextPane1.grabFocus();
}

else if(b == Button3)
{
ZoomedPanel ZoomedPanel3 = new ZoomedPanel();

Toolkit.getDefaultToolkit().getSystemEventQueue().push(ZoomedPanel3.new MyEventQueue());

int j = 0;
int i = 0;

j = TextPane1.getComponentCount();

for(i=0;i {
ZoomedPanel3 = (ZoomedPanel)((Container)TextPane1.getComponent(i)).getComponent(0);
ZoomedPanel3.scale = (float)1;

ZoomedPanel3.validate();
ZoomedPanel3.repaint();
}

TextPane1.revalidate();
TextPane1.repaint();
fr.validate();
fr.repaint();

TextPane1.grabFocus();
}

}
public static void main(String args[])
{
Pagination a = new Pagination();
a.initialize();
}
}

class ZoomedPanel extends JPanel
{
float scale = 1;

public ZoomedPanel()
{

}

public void paint(Graphics g)
{
Graphics2D g2d=(Graphics2D)g;
AffineTransform oldTr=g2d.getTransform();
g2d.scale(scale,scale);
super.paint(g);
g2d.setTransform(oldTr);
}

protected void processMouseEvent1(MouseEvent e)
{
int x=(int)(e.getX() * scale);
int y=(int)(e.getY() * scale);
MouseEvent ze = new MouseEvent(e.getComponent(), e.getID(), e.getWhen(), e.getModifiers(), x, y, e.getClickCount(), e.isPopupTrigger());
super.processMouseEvent(ze);
}

public Graphics getGraphics()
{
Graphics g=super.getGraphics();
Graphics2D g2d=(Graphics2D)g;
g2d.scale(scale,scale);
return g;
}

public class MyEventQueue extends EventQueue
{

public MyEventQueue()
{

}

protected void dispatchEvent(AWTEvent event)
{

AWTEvent event2=event;

if(event instanceof MouseEvent)
{

if(event.getSource() instanceof Component && event instanceof MouseEvent)
{
MouseEvent me=(MouseEvent)event2;
Component c=(Component)event.getSource();
Component cursorComponent=SwingUtilities.getDeepestComponentAt(c, me.getX(), me.getY());
ZoomedPanel zContainer=getZoomedPanel(cursorComponent);

if(zContainer!=null)
{
float scale=zContainer.scale;
int x=me.getX();
Point p=SwingUtilities.convertPoint(zContainer,0,0,(Component)event.getSource());
int cX=me.getX()-p.x;
x=x-cX+(int)(cX/scale);

int y=me.getY();
int cY=me.getY()-p.y;
y=y-cY+(int)(cY/scale);
MouseEvent ze = new MouseEvent(me.getComponent(), me.getID(), me.getWhen(), me.getModifiers(),
x, y, me.getClickCount(), me.isPopupTrigger());

event2=ze;

}

}

}

super.dispatchEvent(event2);

}

}

public static ZoomedPanel getZoomedPanel(Component c)
{
if (c ==null)
{
return null;
}

else if (c instanceof ZoomedPanel)
{
return (ZoomedPanel)c;
}

else
{
return getZoomedPanel(c.getParent());
}

}

}
[/code]

Hoping to hear from you

Yours sincerely

Richard West

stanislavl
Offline
Joined: 2003-06-17
Points: 0

I runt the test.

To fix problem try to override ComponentView. Methods getXXXSpan();
[code]
public float getPreferredSpan(int axis) {
if ((axis != X_AXIS) && (axis != Y_AXIS)) {
throw new IllegalArgumentException("Invalid axis: " + axis);
}
if (c != null) {
Dimension size = c.getPreferredSize();
if (axis == View.X_AXIS) {
return size.width;
} else {
return size.height;
}
}
return 0;
}
[/code]

The sizes of component must be adapted according to scale.

But could you tell me do you have only JTextPane embedded? I mean No buttons, comboboxes and similar components?

If yes you don't need the zoomed panel at all. You can iterate through all the added JTextPane and set ScaledEditorKit to all of them so you will be able to use the same scaling code as for main JTExtPane. I mean sets zoomFactor to the embeded JtextPanes' EditorKits.

Also could you describe what you try to achieve? Why do you need the embedded components? I mean what does the end user need?

regards,
Stas

freesoft_2001
Offline
Joined: 2006-03-11
Points: 0

Hi everyone,

> But could you tell me do you have only JTextPane
> embedded? I mean No buttons, comboboxes and similar
> components?

No, the only Jcomponents that will be embedded will be JTextPanes and no other components

> If yes you don't need the zoomed panel at all. You
> can iterate through all the added JTextPane and set
> ScaledEditorKit to all of them so you will be able
> to use the same scaling code as for main JTextPane.

The thing for your scaled editorkits is that it only works for rtf contents but the contents of the embedded JTextPanes will be html

> Also could you describe what you try to achieve? Why
> do you need the embedded components? I mean what does
> the end user need?

I am trying to insert html content into a rtf JTextPane by adding a JTextPane that uses the htmleditorkit into another JTextPane that uses your scaled editorkit

What the user needs is prectically html content in rtd content JTextPane and this is the only way i know of curently.

Hoping to hear from you

Yours Sincerely

Richard West

stanislavl
Offline
Joined: 2003-06-17
Points: 0

>I am trying to insert html content into a rtf JTextPane by adding a JTextPane that uses the htmleditorkit into another JTextPane that uses your scaled editorkit

So my previous advice is for you. You should extend ComponentView and override getXXXSpan() methods to change preferred size according to specified zoom factor.

regards,
Stas

freesoft_2001
Offline
Joined: 2006-03-11
Points: 0

Hi everyone,

> So my previous advice is for you. You should extend
> ComponentView and override getXXXSpan() methods to
> change preferred size according to specified zoom
> factor.

I tried doing that but it seems that things seem to get even worse. Before this i can insert and see the JTextPane embedded in the the original JTextPane but now it seems that after i extended the ComponentView i can see the JTextPane embedded in the original JTextPane.

This is what i did

[code]
class ComponentView extends View
{
Element elem1;

public ComponentView(Element elem)
{
super(elem);
elem1 = elem;
}

public float getMaximumSpan(int axis)
{
float f = super.getMaximumSpan(axis);
f *= getZoomFactor();
return f;
}

public float getMinimumSpan(int axis)
{
return getPreferredSpan(axis);
}

public float getPreferredSpan(int axis)
{
return new SectionView(elem1, View.Y_AXIS).getPreferredSpan(axis);
}

public Shape modelToView(int pos, Shape a, Position.Bias b)throws BadLocationException
{
double zoomFactor = getZoomFactor();

Rectangle alloc;

alloc = a.getBounds();
Shape s = new SectionView(elem1, View.Y_AXIS).modelToView(pos, alloc, b);
alloc = s.getBounds();
alloc.x*= zoomFactor;
alloc.y*= zoomFactor;
alloc.width*= zoomFactor;
alloc.height*= zoomFactor;

return alloc;
}

public int viewToModel(float x, float y, Shape a, Position.Bias[] bias)
{
//return new ComponentView(elem1).viewToModel(x, y, a, bias);

double zoomFactor = getZoomFactor();

Rectangle alloc = a.getBounds();

x/= zoomFactor;
y/= zoomFactor;
alloc.x/= zoomFactor;
alloc.y/= zoomFactor;
alloc.width/= zoomFactor;
alloc.height/= zoomFactor;

return new SectionView(elem1, View.Y_AXIS).viewToModel(x, y, alloc, bias);
}

public void paint(Graphics g, Shape a)
{
double zoomFactor = getZoomFactor();

Graphics2D g2d = (Graphics2D)g;
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
RenderingHints.VALUE_FRACTIONALMETRICS_ON);

AffineTransform old = g2d.getTransform();
g2d.scale(zoomFactor, zoomFactor);

g2d.setTransform(old);
}

public double getZoomFactor()
{
Double scale = (Double)getDocument().getProperty("ZOOM_FACTOR");

if(scale != null)
{
return scale.doubleValue();
}

else
{
return 1.0;
}

}

}
[/code]

Please note that the SectionView class is the same SectionView class in your paginated styled editor kit.

I know i am doing something wrong but i just can't seem to put my finger on it.

What is it that i am doing wrongly?

Hoping to hear from you

Yours Sincerely

Richard West

stanislavl
Offline
Joined: 2003-06-17
Points: 0

I don't understand the logic of the method
public float getPreferredSpan(int axis)
{
return new SectionView(elem1, View.Y_AXIS).getPreferredSpan(axis);
}

What are you trying to get? Why do you create a new instance of root view inside the embedded view? Where is the zoom factor correction?

regards,
Stas

freesoft_2001
Offline
Joined: 2006-03-11
Points: 0

Hi everyone,

> I don't understand the logic of the method
> public float getPreferredSpan(int axis)
> {
> return new SectionView(elem1,
> View.Y_AXIS).getPreferredSpan(axis);
> }

Sorry about that, i was experimenting with something anyways the above code should be like this

[code]
public float getPreferredSpan(int axis)
{
float f = super.getPreferredSpan(axis);
f *= getZoomFactor();
return f;
[/code]

The thing is why does it become worse.

I know i am doing something wrong but i don't know where the error is in the ComponentView class

Hoping to hear from you

Yours Sincerely

Richard West

stanislavl
Offline
Joined: 2003-06-17
Points: 0

You have similar code in other methods
>return new SectionView(elem1,View.Y_AXIS).getPreferredSpan(axis);

Why do you override the modelToView and viewToModel methods?

>The thing is why does it become worse.
What do you see? Worse? I don't quite understand the worse.

Is the size correct? bigger than required?

Do you need fixed size of the embedded JEditorPane's? Why do you need to insert html inside rtf docuemnt?

I don't understand what you are trying to achieve that's the main problem.

BTW: I posted a couple of articles here
http://innovative-java.com/articles/articles.html
There are some about pagination, printing of paginated content and headers/footers.

regards,
Stas

freesoft_2001
Offline
Joined: 2006-03-11
Points: 0

Hi everyone,

> You have similar code in other methods
> >return new
> SectionView(elem1,View.Y_AXIS).getPreferredSpan(axis);

There are only two which one is in the modelToView and the viewToModel methods

The thing is if i do this in the overided modelToView
method
[code]
Shape s = modelToView(pos, alloc, b);
[/code]

i will get a compilation error sayting that i cannot call the modelToView directly so that's why i used the one from the SectionView.

> Why do you override the modelToView and viewToModel
> methods?

If i don't overide the methods i get a compilation error
saying that i must overide them

> >The thing is why does it become worse.
> What do you see? Worse? I don't quite understand the
> worse.

Nothing happens at all, When i try to insert the embedded JTextPane it does not appear at all.

> Do you need fixed size of the embedded JEditorPane's?

No. You see in your scaling code for the JEditorPane all text and images are scaled except embedded JComponents.
What i am trying to do is to add embedded JComponent scaling functionality so that not only will the text and images scale as well as embedded JComponents(although my concern is only with JTextPanes' using the HTMLEditorKit)
will be scaled.

> Why do you need to insert html inside rtf docuemnt?

I also trying to integrate a feature in which my document can handle both html and rtf content, like for example adding hyperlinks into a styled document.

The thing is i really do not know why the embedded JComponents are still not scaling. I know i am doing something wrong but i am still unable to find the fault although i do know that fault lies mainly in the ComponentView class that listed in the earlier post

Hoping to hear from you

Yours Sincerely

Richard West

ps. Your articles at innovative Java are really great and
fantastic

stanislavl
Offline
Joined: 2003-06-17
Points: 0

>If i don't overide the methods i get a compilation error
saying that i must overide them

I tried to write down an extension and don't have any compilation errors.
[code]
class MyComponentView extends ComponentView {
public MyComponentView(Element elem) {
super(elem);
}
public float getPreferredSpan(int axis) {
float res=super.getPreferredSpan(axis);
return res*0.5f;
}
public float getMinimumSpan(int axis) {
float res=super.getMinimumSpan(axis);
return res*0.5f;
}
public float getMaximumSpan(int axis) {
float res=super.getMaximumSpan(axis);
return res*0.5f;
}
}
[/code]

What kind of error do you get? COuld you post it here?

Also what size should have the unscaled (100% zoom) embedded JEditorPane? Is it fixed somehow?

regards,
Stas

freesoft_2001
Offline
Joined: 2006-03-11
Points: 0

Hi everyone,

> I tried to write down an extension and don't have any
> compilation errors.

It seems that my error was due to this line
[code]
class ComponentView extends View
[/code]

I should have extended ComponentView instead. It was a silly mistake on my part

> Also what size should have the unscaled (100% zoom)
> embedded JEditorPane?

I did not set any size for the embedded JTextPane, i simply used the default

This is how i inserted th embedded JTextPane
where TextPane1 is the original JTextPane

[code]
JTextPane L = new JTextPane();
L.setBackground(Color.blue);
TextPane1.insertComponent(L);
[/code]

Is it fixed somehow?

Yes, The thing is that i do not want it to be fixed.

For example when i embeded the JTextPane into a JTextPane using your scaled editorkit at 100% everything is okay but when i scale it to 50% everthing is scaled except the embedded JTextPane and i still can't figure out why.

I tried redoing the MyComponentView a bit but still the embedded JComponent will not scale

Here is the MyComponentView code
[code]
class MyComponentView extends ComponentView
{
public MyComponentView(Element elem)
{
super(elem);
}

public float getPreferredSpan(int axis)
{
float f = super.getPreferredSpan(axis);
f *= getZoomFactor();
return f;
}

public float getMinimumSpan(int axis)
{
float f = super.getMinimumSpan(axis);
f *= getZoomFactor();
return f;
}

public float getMaximumSpan(int axis)
{
float f = super.getMaximumSpan(axis);
f *= getZoomFactor();
return f;
}

public void paint(Graphics g, Shape a)
{
double zoomFactor = getZoomFactor();

Graphics2D g2d = (Graphics2D)g;
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
RenderingHints.VALUE_FRACTIONALMETRICS_ON);

AffineTransform old = g2d.getTransform();
g2d.scale(zoomFactor, zoomFactor);

g2d.setTransform(old);
}

public double getZoomFactor()
{
Double scale = (Double)getDocument().getProperty("ZOOM_FACTOR");

if(scale != null)
{
return scale.doubleValue();
}

else
{
return 1.0;
}

}

}
[/code]

I don't get any error or exceptions but the embedded JTextPane still does not scale when i use the above listed MyComponentView class.

I know i am doing something wrong but i am not sure where the mistake lies.

Hoping to hear from you

Yours Sincerely

Richard West