I'd prefer to hold off until 2.0.1 - Todd just created the 2.0 tag, and we really need to get it out the door (we have a press release tentatively scheduled to go out the week of Jan 10).
On Dec 21, 2010, at 1:15 AM, Chris Bartlett wrote: > Greg, > > Is there time before the 2.0 vote to put in the constructor work-around I > suggested? I see there have been a few commits recently and see it as very > low risk. > > Either way I will add it to JIRA for 2.0.1. As a pure fix, or the fix and > removal of the workaround. > > Chris > > On 12 December 2010 21:08, Greg Brown <gk_br...@verizon.net> wrote: > >> Yes, that would definitely explain it. >> >> On Dec 12, 2010, at 9:01 AM, Chris Bartlett wrote: >> >>> I didn't think to look that closely at installSkin(), but it sounds like >> the >>> behaviour you describe would give the same problem due to there not being >> a >>> skin installed when the setText() call occurs, so no there is no listener >> to >>> catch the TextAreaContentListener#paragraphInserted(TextArea, int) event. >>> >>> On 12 December 2010 20:03, Greg Brown <gk_br...@verizon.net> wrote: >>> >>>> I don't think the problem is that the skin is getting installed twice - >>>> installSkin() was written specifically to handle that case. When a more >>>> specific component/skin mapping exists, installSkin() is supposed to >> ignore >>>> the first call because it knows a more specific skin will be installed >>>> later. So something else is probably going on, most likely related to >> the >>>> call to setText(). >>>> >>>> On Dec 11, 2010, at 1:48 PM, Chris Bartlett wrote: >>>> >>>>> I created a custom skin extended from TerraTextAreaSkin in order to >>>> handle these keypresses. >>>>> However I had problems after associating my subclass of TextArea with a >>>> custom skin. >>>>> >>>>> >>>>> TextArea only has one constructor, a public no args one which will >> always >>>> be called when instantiating a subclass. >>>>> public TextArea() { >>>>> installSkin(TextArea.class); >>>>> setText(""); >>>>> } >>>>> >>>>> The problem is that org.apache.pivot.wtk.skin.TextAreaSkin is installed >>>> immediately, and this skin holds some state. >>>>> The setText() call ultimately adds a empty paragraph via >>>> TerraTextAreaSkin(TextAreaSkin).paragraphInserted(TextArea, int), and >> this >>>> is tracked within TextAreaSkin. >>>>> >>>>> >>>>> Normally I would extends a skin & component as follows >>>>> public class MyTextAreaSkin extends TerraTextAreaSkin { >>>>> public MyTextAreaSkin() { >>>>> super(); >>>>> } >>>>> // My styles, overrides & supporting code >>>>> } >>>>> >>>>> public class MyTextArea extends TextArea { >>>>> public MyTextArea() { >>>>> super(); >>>>> installSkin(MyTextArea.class); >>>>> } >>>>> // My properties, overrides & supporting code >>>>> } >>>>> >>>>> And make them known to the Theme >>>>> Theme.getTheme().set(MyTextArea.class, MyTextAreaSkin.class); >>>>> >>>>> >>>>> This will fail because by the time I get to install my custom skin in >> the >>>> MyTextArea constructor, it superclass has already installed a skin, >> *and* >>>> altered its state. >>>>> The installSkin() in MyTextArea runs again, and essentially resets the >>>> state by installing a new skin over the old one. >>>>> The next call to TextArea.setText(Reader) will fail with the following >>>> error >>>>> >>>>> Exception in thread "main" java.lang.IndexOutOfBoundsException: index 0 >>>> out of bounds. >>>>> at >>>> >> org.apache.pivot.collections.ArrayList.verifyIndexBounds(ArrayList.java:577) >>>>> at org.apache.pivot.collections.ArrayList.get(ArrayList.java:346) >>>>> at >>>> >> org.apache.pivot.wtk.skin.TextAreaSkin.paragraphsRemoved(TextAreaSkin.java:1216) >>>>> at >>>> >> org.apache.pivot.wtk.TextArea$TextAreaContentListenerList.paragraphsRemoved(TextArea.java:511) >>>>> at >>>> >> org.apache.pivot.wtk.TextArea$ParagraphSequence.remove(TextArea.java:420) >>>>> at org.apache.pivot.wtk.TextArea.setText(TextArea.java:722) >>>>> at org.apache.pivot.wtk.TextArea.setText(TextArea.java:667) >>>>> at mytextarea.SimpleTest.test(SimpleTest.java:23) >>>>> at mytextarea.SimpleTest.main(SimpleTest.java:27) >>>>> >>>>> >>>>> This occurs because the state held in the TextArea component is now out >>>> of sync with the state held in the TextAreaSkin. (The component >> remembers >>>> the first paragraph that was added, but the newly installed skin knows >>>> nothing about it, so fails when it tries to remove the paragraph) >>>>> >>>>> Hopefully that all makes sense! >>>>> >>>>> >>>>> A simple fix would be something like changing the TextArea constructors >>>> as follows >>>>> // Single constructor to be replaced with 2 new constructors >>>>> public TextArea() { >>>>> installSkin(TextArea.class); >>>>> setText(""); >>>>> } >>>>> >>>>> ...becomes... >>>>> >>>>> // Default >>>>> public TextArea() { >>>>> this(TextArea.class); >>>>> } >>>>> >>>>> // To be called by any class extending this which wishes to use a >> custom >>>> skin >>>>> public TextArea(Class<? extends TextArea> componentClass) { >>>>> installSkin(componentClass); >>>>> setText(""); >>>>> } >>>>> >>>>> >>>>> Then in the constructor for MyTextArea() I can call the 2nd constructor >>>> and only install a single skin instance >>>>> public MyTextArea() { >>>>> super(MyTextArea.class); >>>>> } >>>>> >>>>> Zip file (hopefully) attached with some simple test code to demonstrate >>>> the issue. >>>>> >>>>> Chris >>>>> >>>>> On 11 December 2010 17:25, Chris Bartlett <cbartlet...@gmail.com> >> wrote: >>>>> I forgot to add that it would be nice to be able to place the caret at >>>> the start and end of the file with keystrokes such as CTRL+HOME and >>>> CTRL+END. >>>>> Holding SHIFT in addition to the other keys would bound the selection >>>> from the caret to the start/end point respectively. >>>>> >>>>> As I will be following up on the whole component keystroke handling >> area >>>> in PIVOT-638, I will just make a note to include it then. >>>>> >>>>> Chris >>>>> >>>>> On 11 December 2010 17:12, Chris Bartlett <cbartlet...@gmail.com> >> wrote: >>>>> Greg, >>>>> >>>>> I finally found a little time to play around with TextArea today, and >> it >>>> looks good. The only points of note I could find are the following. >>>>> >>>>> >>>>> TextAreaSkin fails as follows if when the END key is pressed on the >> final >>>> line of a TextArea (ie, a line without a linebreak) >>>>> java.lang.IndexOutOfBoundsException >>>>> at org.apache.pivot.wtk.TextArea.getCharacterAt(TextArea.java:870) >>>>> at >>>> org.apache.pivot.wtk.skin.TextAreaSkin.keyPressed(TextAreaSkin.java:934) >>>>> at >>>> >> org.apache.pivot.wtk.Component$ComponentKeyListenerList.keyPressed(Component.java:524) >>>>> at org.apache.pivot.wtk.Component.keyPressed(Component.java:2813) >>>>> at >>>> >> org.apache.pivot.wtk.ApplicationContext$DisplayHost.processKeyEvent(ApplicationContext.java:1257) >>>>> at java.awt.Component.processEvent(Unknown Source) >>>>> at >>>> >> org.apache.pivot.wtk.ApplicationContext$DisplayHost.processEvent(ApplicationContext.java:709) >>>>> ... >>>>> You can see this by simply pressing END with a freshly created TextArea >>>> with no content. >>>>> If you add a second line, END will work on the first line, but throw on >>>> the last one. >>>>> >>>>> >>>>> TextAreaSkin.getInsertionPoint(int, int) did not behave as I >> anticipated >>>> in one scenario. >>>>> I was expecting it to place the caret at the end of the text (the same >>>> placement that would occur if I press the END key) if I left click >> anywhere >>>> within the 'space' following the final character in TextArea. >>>>> Clicking in that space currently seems to have no effect. >>>>> >>>>> Chris >>>>> >>>>> >>>>> <mytextarea.zip> >>>> >>>> >> >>