Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix selection container default index #1823

Merged

Conversation

SylvainCorlay
Copy link
Member

cf discussions on #1822

  • It does not make sense to default to 0 for an empty list of children.
  • The default value of most attributes allowing None is None.

@jasongrout
Copy link
Member

jasongrout commented Nov 17, 2017

I think it makes sense for Tab to default to the first item selected. Notice the logic in the selection widgets about choosing a default selection:

self.index = 0 if len(options) > 0 else None

We could do something like that.

I agree that a default of None for the accordion makes sense.

@jasongrout jasongrout added this to the 7.x milestone Nov 17, 2017
@SylvainCorlay SylvainCorlay force-pushed the selection-container-default branch from 4519ca8 to 7a499a6 Compare November 18, 2017 12:42
@SylvainCorlay
Copy link
Member Author

OK, I changed the logic to the following:

  • general default for selection container index is None.
  • general behavior when changing the children is setting the new selected index to None when the previous value was higher than the new number of children.
  • in the case of the tab:
    • if we provide a non-empty children list, the first tab will be selected by default.

@SylvainCorlay
Copy link
Member Author

@jasongrout are you ok with this new logic? If yes, I will merge the companion PR in xwidgets.

@observe('children')
def _observe_children(self, change):
if len(change.new) > 0:
self.selected_index = 0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This means that if I keep adding a tab to the end (I think @rmenegaux did this, for example), the selected index keeps being reset to 0.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is right. Although, we don't have operational transforms on sequences, we change all at once.

Since setting the selected index to None is not something we want for tabs, this is one way to go.

@@ -29,6 +30,11 @@ def _validated_index(self, proposal):
else:
raise TraitError('Invalid selection: index out of bounds')

@observe('children')
def _observe_children(self, change):
if self.selected_index is not None and len(change.new) < self.selected_index:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't necessarily select the same child (if we delete a child from the front, now the selected container is not the same), which may be confusing.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above

@jasongrout
Copy link
Member

I'm thinking through various scenarios with the current behavior and your new behavior. Two scenarios are:

  1. Creating a selection container, then deleting the first container. What should be shown after that?

  2. Creating a selection container and adding a new container at the end. What should be shown after that?

@jasongrout
Copy link
Member

Part of the problem here is that we don't have the notion of inserting or removing a single container - we only have the notion of refreshing the entire children list. When you have more semantic information about what was done (e.g., deleting a tab), you can do something more intelligent like selecting the tab next to it. See, for example, the phosphor insert and remove behavior options at http://phosphorjs.github.io/phosphor/api/widgets/classes/tabbar.html#insertbehavior.

@SylvainCorlay
Copy link
Member Author

This new behavior is still better than the current one, which does not handle the case of an empty list (and causes failures in the C++ backend).

We could try to check if old_children[selected_index] is an item in the new sequence, but this will also be the case when multiple tabs have the same content.

@jasongrout
Copy link
Member

Is there a way to preserve the current behavior for cases where the children list is nonempty, and only insert a workaround for when the children list is empty?

If we are changing the current behavior for non-empty children lists, we're breaking user's code, so we really should wait until 8.0. I can imagine the frustration of updating to a patch or even a minor release and having your code managing the children of a selection container break.

@SylvainCorlay
Copy link
Member Author

We should make a decision on this one for 8.0 IMO.

I am not so opinionated about the solution but I think that selection containers should be default-constructible.

@jasongrout jasongrout force-pushed the selection-container-default branch from 7a499a6 to 4483e55 Compare January 22, 2020 18:44
@jasongrout
Copy link
Member

Rebased on master

…et selected index to 0.

It will be the user’s responsibility to set the selected index to something that makes sense when they change the children.
@jasongrout
Copy link
Member

I thought more about it, and I think it should be the user's responsibility to set the selected index to something that makes sense when they change the children list, especially for the tab widget:

  1. Because we have no semantic information about what the user did to the children list, it's impossible to guess what the right behavior should be. Encoding a guess may make it more difficult for the user to implement their desired behavior
  2. For tab widgets, we do actually support selecting no tab
  3. We'll have some very minor logic to not touch the selected index if it still makes sense (i.e., if the children array is at least that big). If it doesn't make sense, we just set it to None and rely on the user to set the index to something that makes sense.

@jasongrout jasongrout merged commit 28ab143 into jupyter-widgets:master Jan 22, 2020
@jasongrout
Copy link
Member

Thanks @SylvainCorlay!

@lock lock bot added the resolved-locked Closed issues are locked after 30 days inactivity. Please open a new issue for related discussion. label May 20, 2020
@lock lock bot locked as resolved and limited conversation to collaborators May 20, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
resolved-locked Closed issues are locked after 30 days inactivity. Please open a new issue for related discussion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants