pivot-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Chris Bartlett <cbartlet...@gmail.com>
Subject Re: TextAreaSkin
Date Sun, 12 Dec 2010 14:01:16 GMT
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_brown@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 <cbartlett.x@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 <cbartlett.x@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>
>
>

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message