[
https://issues.apache.org/jira/browse/PIVOT-751?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13065903#comment-13065903
]
Greg Brown commented on PIVOT-751:
----------------------------------
As noted, the bogus event is fired because TerraTabPaneSkin sets the selected
index in response to the initial tab insert event, and then TabPane fires an
additional event based on incorrect information.
This represents an interesting design challenge. It is similar to the challenge
of keeping a ListView's model and selection state in sync. In Swing, this is
handled by the UI delegate (i.e. the skin). When the model fires events, the
skin is responsible for updating the component's selection state.
We intentionally chose not to do it this way since it seemed like the component
should be responsible for maintaining its own state internally. However, after
some further thought I'm wondering if the Swing approach might be better. We
had initially viewed the skin as the "view" and the component as the
"controller" - however, in retrospect, I think the component is actually the
"view-model", and the skin is the "view-controller". The component is part view
because it is the object that actually receives user input and paint calls
(though it delegates them to the skin). It is part model since it generally
hosts the model (either as an intrinsic property like "buttonData" or as an
attached model like "listData"). The skin is part view because it actually
handles the paint calls, and part controller since it handles user input and
other events and updates the component's (i.e. model's) state in response to
them.
When viewed as a controller, it seems valid for the skin to be responsible for
keeping the component's various models in sync. Since there will never be a
practical case where a component does not have a skin installed, this seems OK
to me. It means that, in this case, TabPane wouldn't fire an indirect selection
change event when a tab is inserted - it would be up to the skin to respond to
that event appropriately (which it already does). The skin should also do
something similar when a tab is removed.
What do you think? FYI, this would be a big change, as it affects the design of
many components. However, I think it could probably be restricted to TabPane,
Accordion, and CardPane for now and propagated to ListView, TableView, etc.
later.
> TabPaneSelectionListener#selectedIndexChanged called twice when first tab is
> inserted
> -------------------------------------------------------------------------------------
>
> Key: PIVOT-751
> URL: https://issues.apache.org/jira/browse/PIVOT-751
> Project: Pivot
> Issue Type: Bug
> Components: wtk
> Affects Versions: 2.0
> Reporter: Edvin Syse
> Priority: Minor
> Fix For: 2.0.1
>
> Attachments: PIVOT751.java, PIVOT751.txt
>
>
> If you add a tab to an _empty_ tabpane, two selectedIndexChanged events are
> called. I.e, when you add a TabPaneSelectionListener to a tabpane and call:
> tabpane.getTabs().add(component);
> .. the listener fires twice, with previousSelectedIndex set to -1 and then 0.
> The two events are fired by line 68 and 72 in TabPane.java:
> 68 tabPaneListeners.tabInserted(TabPane.this, index);
> 69
> 70 // Fire selection change event, if necessary
> 71 if (selectedIndex != previousSelectedIndex) {
> 72 tabPaneSelectionListeners.selectedIndexChanged(TabPane.this,
> selectedIndex);
> 73 }
> This could be fixed by taking into account that previousSelectedIndex might
> have been -1 when invoked, like this:
> if (selectedIndex != previousSelectedIndex && previousSelectedIndex > -1) {
> See this thread for more info:
> http://apache-pivot-users.399431.n3.nabble.com/TabPaneSelectionListener-selectedIndexChanged-called-twice-when-first-tab-is-inserted-td3022515.html
> PS: According to Chris, CardPane and Accordion behave in the same way, so any
> changes to TabPane should also be made to these for consistency.
--
This message is automatically generated by JIRA.
For more information on JIRA, see: http://www.atlassian.com/software/jira