toga icon indicating copy to clipboard operation
toga copied to clipboard

Add API to replace children

Open hyuri opened this issue 1 year ago • 4 comments

What is the problem or limitation you are having?

Currently, if I use a multi-pages design and create multiple pages (multiple boxes containing multiple widgets), and I want to switch between these pages — between page1_box and page2_box, for example — I need to:

main_box.remove(page1_box)
main_box.insert(pos, page2_box)

So, not only it's 2 steps to do 1 thing (swap out/replace a child), but I also need to know the right index for the insert, which seems cumbersome to keep track of if I plan on adding/removing a few widgets during runtime.

Describe the solution you'd like

Add a .replace() method to nodes, that will join the likes of .remove() .add() and .insert(), so that we can:

  1. Replace a child node in one step;
  2. Not have to worry about index numbers.

Example: main_box.replace(page1_box, page2_box)

In other words: Box.replace(old_child, new_child)

This pattern follows the way Python's string replace works — str.replace(old, new).

Describe alternatives you've considered

Add method to replace its calling node. page1_box.replace(page2_box)

In other words: old_child.replace(new_child)

But this seems to break the existing convention with add, remove and insert.

Additional context

No response

hyuri avatar Dec 28 '23 13:12 hyuri

I liked the proposal, I'm trying to do something similar, but I hadn't found anything related to this page design in the documentation, I think this proposal would help my project too

Heus-Sueh avatar Dec 28 '23 15:12 Heus-Sueh

I have some hesitation about this proposal - it seems to be predicated on the assumption that widget containers are "string like". I think it's a lot more reasonable to consider them to be "list like" - if only because of the "hoodoo".replace("o", "e") example.

That said, I accept that "replacing X with Y" is a common use case, and the multiple-replace case can't happen, so there's no risk in using the same API name.

As part of any implementation, we should also add an index() method, which returns the current position of a widget in the list of children. We'll need an index() method in order to implement replace() anyway, so we might as well expose the capability.

freakboy3742 avatar Dec 30 '23 00:12 freakboy3742

it seems to be predicated on the assumption that widget containers are "string like". I think it's a lot more reasonable to consider them to be "list like"

In that case, instead of replace, the API should use square bracket syntax via __getitem__ and __setitem__.

EDIT: Well, I suppose we could have them both, as they're useful in different situations.

mhsmith avatar Jan 10 '24 08:01 mhsmith

Agreed that __getitem__/__setitem__ syntax (in addition to replace) would also make sense.

freakboy3742 avatar Jan 11 '24 01:01 freakboy3742

I'm taking a look at this at the PyCon US sprint

funkyrailroad avatar May 21 '24 12:05 funkyrailroad