From pavel.porvatov at oracle.com Tue Jul 3 15:31:07 2012 From: pavel.porvatov at oracle.com (Pavel Porvatov) Date: Tue, 03 Jul 2012 19:31:07 +0400 Subject: Extension method for AbstractDocument.Content? In-Reply-To: References: <4FE31DFA.1010000@oracle.com> <4FEDA22B.3050803@oracle.com> Message-ID: <4FF3103B.3030003@oracle.com> Hi Paulo, > > > On Fri, Jun 29, 2012 at 1:40 PM, Pavel Porvatov > > wrote: > > Hi Paulo, >> Hi Pavel. >> >> On Thu, Jun 21, 2012 at 2:13 PM, Pavel Porvatov >> > wrote: >> >> Hi Paulo, >> >> Hi. I've noticed that DefaultStyledDocument has a >> slowness issue when inserting text. Even if you subclass >> it and expose the faster method: >> protected void insert(int offset, ElementSpec[] data) >> >> the body of the method still uses a stringbuilder to >> append all char[] inside of the data before actually >> inserting into the content. >> >> This is because the only method for insertion in the >> default content interface is: >> public UndoableEdit insertString(int where, String str) >> >> Now if there are going to be extension methods in java 8, >> it would be nice to have a >> public UndoableEdit insert(int where, int index, int >> length, char[] str) default { >> return insert(where, new String(index, length, str); >> } >> >> In which class do you suggest to add the new method? >> >> It would need to be part of AbstractDocument.Content with the new >> extension method feature in order to be able to be part of the >> public interface of Content and be useable generally without casts. > Unfortunately we can't do that because of backward compatibility. > > > Why not? (this for java 8 with extension methods). I admit i hadn't > thought it through for**javax.swing.text.GapContent > Since it's not final, using instanceof for the same effect in > DefaultStyledDocument.insert(int offset, ElementSpec[] data) > in the would be be a bad idea since the Content can be replaced. > > However, with a extension method that only calls the string version in > the Content interface, and overriding that method in GapContent to > copy the char[]'s directly, and using that new Content method in > DefaultStyledDocument.insert(int offset, ElementSpec[] data) > would have the same effect. We cannot modify public API (in your case it's AbstractDocument.Content) because there are lot of implementations and all of them will be not compilable. Regards, Pavel -------------- next part -------------- An HTML attachment was scrubbed... URL: From i30817 at gmail.com Wed Jul 4 10:19:13 2012 From: i30817 at gmail.com (Paulo Levi) Date: Wed, 4 Jul 2012 11:19:13 +0100 Subject: Extension method for AbstractDocument.Content? In-Reply-To: <4FF3103B.3030003@oracle.com> References: <4FE31DFA.1010000@oracle.com> <4FEDA22B.3050803@oracle.com> <4FF3103B.3030003@oracle.com> Message-ID: Isn't that what extension methods are supposed to address? -------------- next part -------------- An HTML attachment was scrubbed... URL: From alexandr.scherbatiy at oracle.com Tue Jul 10 12:11:54 2012 From: alexandr.scherbatiy at oracle.com (Alexander Scherbatiy) Date: Tue, 10 Jul 2012 16:11:54 +0400 Subject: Extension method for AbstractDocument.Content? In-Reply-To: References: Message-ID: <4FFC1C0A.9080708@oracle.com> Hi Paulo, On 6/21/2012 8:56 AM, Paulo Levi wrote: > Hi. I've noticed that DefaultStyledDocument has a slowness issue when > inserting text. Even if you subclass it and expose the faster method: > protected void insert(int offset, ElementSpec[] data) Before fixing the performance issue it usually needs to have some performance statistics, like: - What is the difference between time execution or memory usage for code with the fix and without the fix for text with different length - Text with which length is commonly used in this method - How often this method is used in real cases - Is the most performance degradation is localized in this method or may be where are other narrow places which have performance issues during a text manipulation Thanks, Alexandr. > > the body of the method still uses a stringbuilder to append all char[] > inside of the data before actually inserting into the content. > > This is because the only method for insertion in the default content > interface is: > public UndoableEdit insertString(int where, String str) > > Now if there are going to be extension methods in java 8, it would be > nice to have a > public UndoableEdit insert(int where, int index, int length, char[] > str) default { > return insert(where, new String(index, length, str); > } > > with a adequate specialization in GapContent (that obviously doesn't > call the string version), and that that new method is used in the > protected void insert(int offset, ElementSpec[] data) > method (and where it makes sense) From pavel.porvatov at oracle.com Tue Jul 10 15:34:47 2012 From: pavel.porvatov at oracle.com (Pavel Porvatov) Date: Tue, 10 Jul 2012 19:34:47 +0400 Subject: Extension method for AbstractDocument.Content? In-Reply-To: <4FFC1C0A.9080708@oracle.com> References: <4FFC1C0A.9080708@oracle.com> Message-ID: <4FFC4B97.4000700@oracle.com> Hi, > > Hi Paulo, > > On 6/21/2012 8:56 AM, Paulo Levi wrote: >> Hi. I've noticed that DefaultStyledDocument has a slowness issue when >> inserting text. Even if you subclass it and expose the faster method: >> protected void insert(int offset, ElementSpec[] data) > > Before fixing the performance issue it usually needs to have some > performance statistics, like: > - What is the difference between time execution or memory usage > for code with the fix and without the fix for text with different length > - Text with which length is commonly used in this method > - How often this method is used in real cases > - Is the most performance degradation is localized in this method > or may be where are other narrow places which have performance issues > during a text manipulation I agree with Alexander. Adding a new method in public API must be really reasonable. Otherwise we will get monstrous classes... Regards, Pavel > > Thanks, > Alexandr. > > > >> >> the body of the method still uses a stringbuilder to append all >> char[] inside of the data before actually inserting into the content. >> >> This is because the only method for insertion in the default content >> interface is: >> public UndoableEdit insertString(int where, String str) >> >> Now if there are going to be extension methods in java 8, it would be >> nice to have a >> public UndoableEdit insert(int where, int index, int length, char[] >> str) default { >> return insert(where, new String(index, length, str); >> } >> >> with a adequate specialization in GapContent (that obviously doesn't >> call the string version), and that that new method is used in the >> protected void insert(int offset, ElementSpec[] data) >> method (and where it makes sense) > > From i30817 at gmail.com Wed Jul 11 12:04:22 2012 From: i30817 at gmail.com (Paulo Levi) Date: Wed, 11 Jul 2012 13:04:22 +0100 Subject: Extension method for AbstractDocument.Content? In-Reply-To: <4FFC4B97.4000700@oracle.com> References: <4FFC1C0A.9080708@oracle.com> <4FFC4B97.4000700@oracle.com> Message-ID: I can do a simple test What i do is extend DefaultStyledDocument so i can override the method using reflection. Here is the code: @Override public void insert(int offset, ElementSpec[] data) throws BadLocationException { if (offset > getLength() || offset < 0) { throw new BadLocationException("Invalid insert", offset); } if (data == null || data.length == 0) { return; } writeLock(); try { Content content = getContent(); //since instead of doing normal string insert we are going to use the gapvector directly, we don't do this //UndoableEdit cEdit = content.insertString(offset, sb.toString()); int charArraysSize = 0; int index = offset; for (ElementSpec e : data) { if (e.getLength() > 0) { charArraysSize += e.getLength(); bulkArgs[0] = index; bulkArgs[1] = e.getOffset(); bulkArgs[2] = e.getArray(); bulkArgs[3] = e.getLength(); index += e.getLength(); try { replace.invoke(content, bulkArgs); } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) { throw new AssertionError(ex); } } } if (charArraysSize == 0) { return; } //created the undoable edit corresponding to the whole inserted string //this can't be created because it is package protected in gapvector //UndoableEdit cEdit = new InsertUndo(offset, charArraysSize); DefaultDocumentEvent evnt = new DefaultDocumentEvent(offset, charArraysSize, DocumentEvent.EventType.INSERT); //evnt.addEdit(cEdit); buffer.insert(offset, charArraysSize, data, evnt); // update bidi (possibly) super.insertUpdate(evnt, null); // notify the listeners evnt.end(); fireInsertUpdate(evnt); fireUndoableEditUpdate(new UndoableEditEvent(this, evnt)); } finally { writeUnlock(); } } As you can see, i can't use undo-redo in this operation because the undoable edit i need to create is package protected in GapContent - it's a consequence of inlining the insertString function - but only for me, since this change in DefaultStyledDocument would compile. Obviously, the use of reflection would have to be replaced by a extension method, and this method is mostly worthwhile if you have a buffered builder that collects the ElementSpec's so as to insert them in bursts. I have such a builder, and it would be nice to use them in the test to simplify the building code. Can i use it? -------------- next part -------------- An HTML attachment was scrubbed... URL: From i30817 at gmail.com Wed Jul 11 12:17:11 2012 From: i30817 at gmail.com (Paulo Levi) Date: Wed, 11 Jul 2012 13:17:11 +0100 Subject: Extension method for AbstractDocument.Content? In-Reply-To: References: <4FFC1C0A.9080708@oracle.com> <4FFC4B97.4000700@oracle.com> Message-ID: Eh, never mind about the builder - it's only used in html parsing and i'd need to include it too. Not good, i will just read a large text document into a ElementSpec array line-by line and measure the difference. -------------- next part -------------- An HTML attachment was scrubbed... URL: From i30817 at gmail.com Wed Jul 11 13:55:49 2012 From: i30817 at gmail.com (Paulo Levi) Date: Wed, 11 Jul 2012 14:55:49 +0100 Subject: Extension method for AbstractDocument.Content? In-Reply-To: References: <4FFC1C0A.9080708@oracle.com> <4FFC4B97.4000700@oracle.com> Message-ID: Tried to do a performance and memory test; they fail or pass depending on the order the Documents are tested. Could someone more experienced tell me what am i doing wrong? The performance test i expected to fail (since reflection is much slower than override), but the memory test i did not expect to depend on order. import java.io.BufferedReader; import java.lang.management.ManagementFactory; import java.lang.management.MemoryMXBean; import java.lang.management.ThreadMXBean; import java.lang.reflect.Method; import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; import javax.swing.event.DocumentEvent; import javax.swing.event.UndoableEditEvent; import javax.swing.text.BadLocationException; import javax.swing.text.DefaultStyledDocument; import javax.swing.text.DefaultStyledDocument.ElementSpec; import javax.swing.text.GapContent; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; public class DocumentTest { public DocumentTest() { } @BeforeClass public static void setUpClass() throws Exception { } @AfterClass public static void tearDownClass() throws Exception { } @Before public void setUp() { } @After public void tearDown() { } OldTestDocument oldDoc = new OldTestDocument(); NewTestDocument newDoc = new NewTestDocument(); /** * Test of insert method performance and memory */ @Test public void testInsert() throws Exception { System.out.println("insert"); List l = new ArrayList<>(); try (BufferedReader r = Files.newBufferedReader(Paths.get("War and Peace.txt"), Charset.forName("us-ascii"))) { while (r.ready()) { String line = r.readLine(); l.add(new ElementSpec(null, ElementSpec.StartTagType)); l.add(new ElementSpec(null, ElementSpec.ContentType, line.toCharArray(), 0, line.length())); l.add(new ElementSpec(null, ElementSpec.EndTagType)); } } //every styled document must end with a 'implied newline' l.add(new ElementSpec(null, ElementSpec.ContentType, new char[]{'\n'}, 0, 1)); ElementSpec[] arr = (ElementSpec[]) l.toArray(new ElementSpec[0]); long time, mem, elapsedTime1, elapsedTime2, memory1, memory2; ThreadMXBean t = ManagementFactory.getThreadMXBean(); MemoryMXBean m = ManagementFactory.getMemoryMXBean(); //using non-heap memory because we are testing the memory impact of the stringbuilder //inside DefaultStyledDocument.insert(int offset, ElementSpec[] data) //to switch the order exchange the next 6 lines of code with the other six lines below m.gc(); mem = m.getNonHeapMemoryUsage().getUsed(); time = t.getCurrentThreadCpuTime(); oldDoc.insert(0, arr); elapsedTime2 = t.getCurrentThreadCpuTime() - time; memory2 = m.getNonHeapMemoryUsage().getUsed() - mem; m.gc(); mem = m.getNonHeapMemoryUsage().getUsed(); time = t.getCurrentThreadCpuTime(); newDoc.insert(0, arr); elapsedTime1 = t.getCurrentThreadCpuTime() - time; memory1 = m.getNonHeapMemoryUsage().getUsed() - mem; System.out.println("new style insert time : " + elapsedTime1 + " memory used : " + memory1); System.out.println("old style insert time : " + elapsedTime2 + " memory used : " + memory2); assert memory1 < memory2 : "old style insert took less memory than new style insert!"; assert elapsedTime1 < elapsedTime2 : "old style insert took less time than new style insert!"; } class OldTestDocument extends DefaultStyledDocument { @Override public void insert(int offset, ElementSpec[] data) throws BadLocationException { super.insert(offset, data); } } final class NewTestDocument extends DefaultStyledDocument { private final Method replace; private final Object[] bulkArgs = new Object[4]; public NewTestDocument() { super(); try { Class[] args = new Class[]{Integer.TYPE, Integer.TYPE, Object.class, Integer.TYPE}; replace = GapContent.class.getSuperclass().getDeclaredMethod("replace", args); replace.setAccessible(true); } catch (Exception ex) { throw new AssertionError(ex); } } @Override public void insert(int offset, ElementSpec[] data) throws BadLocationException { if (offset > getLength() || offset < 0) { throw new BadLocationException("Invalid insert", offset); } if (data == null || data.length == 0) { return; } writeLock(); try { Content content = getContent(); //since instead of doing normal string insert we are going to use the gapvector directly, we don't do this //UndoableEdit cEdit = content.insertString(offset, sb.toString()); int charArraysSize = 0; int index = offset; for (ElementSpec e : data) { if (e.getLength() > 0) { charArraysSize += e.getLength(); bulkArgs[0] = index; bulkArgs[1] = e.getOffset(); bulkArgs[2] = e.getArray(); bulkArgs[3] = e.getLength(); index += e.getLength(); try { replace.invoke(content, bulkArgs); } catch (Exception ex) { throw new AssertionError(ex); } } } if (charArraysSize == 0) { return; } //created the undoable edit corresponding to the whole inserted string //this can't be created since it is package default in GapContent //UndoableEdit cEdit = new InsertUndo(offset, charArraysSize); DefaultDocumentEvent evnt = new DefaultDocumentEvent(offset, charArraysSize, DocumentEvent.EventType.INSERT); //evnt.addEdit(cEdit); buffer.insert(offset, charArraysSize, data, evnt); // update bidi (possibly) super.insertUpdate(evnt, null); // notify the listeners evnt.end(); fireInsertUpdate(evnt); fireUndoableEditUpdate(new UndoableEditEvent(this, evnt)); } finally { writeUnlock(); } } } } -------------- next part -------------- An HTML attachment was scrubbed... URL: From i30817 at gmail.com Wed Jul 11 13:58:15 2012 From: i30817 at gmail.com (Paulo Levi) Date: Wed, 11 Jul 2012 14:58:15 +0100 Subject: Extension method for AbstractDocument.Content? In-Reply-To: References: <4FFC1C0A.9080708@oracle.com> <4FFC4B97.4000700@oracle.com> Message-ID: Forgot to say i used war and peace (renamed from '2600.txt' to 'War and Peace.txt') from here http://www.gutenberg.org/dirs/2/6/0/2600/2600.zip as a test document -------------- next part -------------- An HTML attachment was scrubbed... URL: From Sergey.Bylokhov at oracle.com Thu Jul 12 15:28:12 2012 From: Sergey.Bylokhov at oracle.com (Sergey Bylokhov) Date: Thu, 12 Jul 2012 19:28:12 +0400 Subject: [8] Review request for 7170657: [macosx] There seems to be no keyboard/mouse action to select non-contiguous items in List Message-ID: <4FFEED0C.2010709@oracle.com> Hi Everyone, Please review the fix. Bug in SwingUtilities.convertMouseEvent().This method does not convert extended state of the event. Bug: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7170657 Webrev can be found at: http://cr.openjdk.java.net/~serb/7170657/webrev.00 -- Best regards, Sergey. From pavel.porvatov at oracle.com Thu Jul 12 16:26:19 2012 From: pavel.porvatov at oracle.com (Pavel Porvatov) Date: Thu, 12 Jul 2012 20:26:19 +0400 Subject: [8] Review request for 7170657: [macosx] There seems to be no keyboard/mouse action to select non-contiguous items in List In-Reply-To: <4FFEED0C.2010709@oracle.com> References: <4FFEED0C.2010709@oracle.com> Message-ID: <4FFEFAAB.2040109@oracle.com> Hi Sergey, The fix looks good. Could you please remove unnecessary code from the test like: 1. @run main/othervm bug7170657 2. The "FAILED" field: you can throw exception from the "fail" method 3. What is the reason to use final here: "public final class"? Regards, Pavel > Hi Everyone, > Please review the fix. > Bug in SwingUtilities.convertMouseEvent().This method does not convert > extended state of the event. > > Bug: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7170657 > Webrev can be found at: > http://cr.openjdk.java.net/~serb/7170657/webrev.00 > From Sergey.Bylokhov at oracle.com Thu Jul 12 16:52:13 2012 From: Sergey.Bylokhov at oracle.com (Sergey Bylokhov) Date: Thu, 12 Jul 2012 20:52:13 +0400 Subject: [8] Review request for 7170657: [macosx] There seems to be no keyboard/mouse action to select non-contiguous items in List In-Reply-To: <4FFEFAAB.2040109@oracle.com> References: <4FFEED0C.2010709@oracle.com> <4FFEFAAB.2040109@oracle.com> Message-ID: <4FFF00BD.8030804@oracle.com> Hi, Pavel. Thanks for review. See comments inline 12.07.2012 20:26, Pavel Porvatov wrote: > Hi Sergey, > > The fix looks good. Could you please remove unnecessary code from the > test like: > > 1. @run main/othervm bug7170657 done > 2. The "FAILED" field: you can throw exception from the "fail" method In this case we skip part of the test. Useful for debug. > 3. What is the reason to use final here: "public final class"? I do not think that someone will want to be inherited from it. I just make all classes final by default. New version of the fix: http://cr.openjdk.java.net/~serb/7170657/webrev.01/ > > Regards, Pavel >> Hi Everyone, >> Please review the fix. >> Bug in SwingUtilities.convertMouseEvent().This method does not >> convert extended state of the event. >> >> Bug: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7170657 >> Webrev can be found at: >> http://cr.openjdk.java.net/~serb/7170657/webrev.00 >> > -- Best regards, Sergey. From pavel.porvatov at oracle.com Mon Jul 16 09:42:36 2012 From: pavel.porvatov at oracle.com (Pavel Porvatov) Date: Mon, 16 Jul 2012 13:42:36 +0400 Subject: [8] Review request for 7170657: [macosx] There seems to be no keyboard/mouse action to select non-contiguous items in List In-Reply-To: <4FFF00BD.8030804@oracle.com> References: <4FFEED0C.2010709@oracle.com> <4FFEFAAB.2040109@oracle.com> <4FFF00BD.8030804@oracle.com> Message-ID: <5003E20C.9010705@oracle.com> Hi Sergey, Looks good for me. Regards, Pavel > Hi, Pavel. > Thanks for review. See comments inline > 12.07.2012 20:26, Pavel Porvatov wrote: >> Hi Sergey, >> >> The fix looks good. Could you please remove unnecessary code from the >> test like: >> >> 1. @run main/othervm bug7170657 > done >> 2. The "FAILED" field: you can throw exception from the "fail" method > In this case we skip part of the test. Useful for debug. >> 3. What is the reason to use final here: "public final class"? > I do not think that someone will want to be inherited from it. I just > make all classes final by default. > > New version of the fix: > http://cr.openjdk.java.net/~serb/7170657/webrev.01/ >> >> Regards, Pavel >>> Hi Everyone, >>> Please review the fix. >>> Bug in SwingUtilities.convertMouseEvent().This method does not >>> convert extended state of the event. >>> >>> Bug: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7170657 >>> Webrev can be found at: >>> http://cr.openjdk.java.net/~serb/7170657/webrev.00 >>> >> > > From Sergey.Bylokhov at oracle.com Mon Jul 16 11:59:06 2012 From: Sergey.Bylokhov at oracle.com (Sergey Bylokhov) Date: Mon, 16 Jul 2012 15:59:06 +0400 Subject: [7u6] Review request for 7170657: [macosx] There seems to be no keyboard/mouse action to select non-contiguous items in List Message-ID: <5004020A.10701@oracle.com> Hi Everyone, Please review the fix.This is backport from jdk8 to jdk7u6. Bug in SwingUtilities.convertMouseEvent().This method does not convert extended state of the event. jdk8 changeset: http://hg.openjdk.java.net/jdk8/awt/jdk/rev/c277657e5e10 Bug: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7170657 Webrev can be found at: http://cr.openjdk.java.net/~serb/7170657/webrev.01/ -- Best regards, Sergey. From pavel.porvatov at oracle.com Mon Jul 16 15:04:13 2012 From: pavel.porvatov at oracle.com (Pavel Porvatov) Date: Mon, 16 Jul 2012 19:04:13 +0400 Subject: [7u6] Review request for 7170657: [macosx] There seems to be no keyboard/mouse action to select non-contiguous items in List In-Reply-To: <5004020A.10701@oracle.com> References: <5004020A.10701@oracle.com> Message-ID: <50042D6D.1030707@oracle.com> Looks good for me. > Hi Everyone, > Please review the fix.This is backport from jdk8 to jdk7u6. > Bug in SwingUtilities.convertMouseEvent().This method does not convert > extended state of the event. > > jdk8 changeset: http://hg.openjdk.java.net/jdk8/awt/jdk/rev/c277657e5e10 > Bug: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7170657 > Webrev can be found at: > http://cr.openjdk.java.net/~serb/7170657/webrev.01/ > From Vladislav.Karnaukhov at oracle.com Mon Jul 30 13:46:37 2012 From: Vladislav.Karnaukhov at oracle.com (Vladislav Karnaukhov) Date: Mon, 30 Jul 2012 17:46:37 +0400 Subject: [7] Review request for 7123767 Wrong tooltip location in Multi-Monitor configurations Message-ID: <5016903D.8010104@oracle.com> Hello, please review the fix for 7123767: Wrong tooltip location in Multi-Monitor configurations jdk7 webrev: http://cr.openjdk.java.net/~vkarnauk/7123767/webrev.00/ test source: http://cr.openjdk.java.net/~vkarnauk/7123767/test/ bug description: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7123767 This is also a customer escalated issue in jdk6. On multi-monitor configurations Component.getLocationOnScreen() may return negative values. Additionally, ToolTipManager.showTipWindow() method calculates tip window location from Component' getLocationOnScreen() return data and draws tip window using the same GraphicsConfiguration instance as component's top-left corner, which again can be of negative value. When component is stretched across multiple screen devices, this may lead to a situation when it's tooltip is drawn on wrong monitor. To fix this we should count all GraphicsConfiguration instances and determine correct screen device to draw on. We should also take into account that: 1) tip window preferred location could be set 2) preferred location could be greater than total virtual bounds of all monitors. To make tip window visible in such case we move it to the corresponding corner of total virtual bounds 3) exact order of monitors (left-to-right and top-to-bottom) is unknown I run jtreg against ToolTipManager tests and all tests passed (I run it several times with different monitor configurations). I also tested the fix with custom test program (please see the link provided) with 4 possible monitor configurations (left-to-right, right-to-left, top-to-bottom and bottom-to-top) and saw no issues. I added no new automated test(s) because this at least would require multiple monitors to run. Regards, - Vlad