(Cut & paste from earlier email...)

A simple [workaround] 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);
}
(End cut & paste)


This at least allows the subclassing of TextArea, but is not consistent with
the rest of the Components, and just hides the problem.  It would still need
to be investigated properly and fixed later.

Do you have any timescales in mind for a 2.0.1 release?  2.0 + x weeks?
If 2.0.1 is likely to come out soon after 2.0 then I am happy to leave it
for now, especially as there are other known issues with TextArea already in
JIRA.

I was only asking as there had been a few commits since previous vote was
cancelled.

Chris


On 21 December 2010 20:14, Greg Brown <gk_br...@verizon.net> wrote:

> Can you remind me what the proposed fix is? Do you have a patch for it?
>
> 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>
> >>>>
> >>>>
> >>
> >>
>
>

Reply via email to