Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Reset of canvas ID's

58 views
Skip to first unread message

Shaun Deacon

unread,
Sep 1, 2022, 6:39:42 PM9/1/22
to
I'm not expecting any action on following, I'm just curious about the reasoning behind it and perhaps I have overlooked a detail...

When an object is created on a canvas, the canvas ID is returned.

Looking at the C code, this seems to be stored in "canvasPtr->nextId" which is initialized to 1 on creation of the widget and incremented each time an object is created.

However, the value is never reset.

Assuming I have a canvas object $c, I would expect "$c delete all" to reset the 'nextId' value to 1 internally because all items are deleted. Currently, a new object created on the canvas (after the delete) returns an ID which is 'nextId++' where 'nextId' was the last object created before the deletion.

Is there a reason this field is not reset ?

In one of my applications I have a "replay" function which saves the current display by saving serialized canvas data. When the user wants to replay, the current canvas display is deleted and recreated from the serialized data. Unfortunately, I have other data that is stored which relies on the original canvas ID's - this has to be adjusted when the new canvas objects are created. If the initial canvas ID were reset, this would be simplified for me.

best regards
Shaun

Arjen Markus

unread,
Sep 2, 2022, 3:18:32 AM9/2/22
to
Could an alternative approach be to update the canvas items themselves? Or to store unique tags for each item?

Regards

Arjen

Robert Heller

unread,
Sep 2, 2022, 8:25:02 AM9/2/22
to
At Thu, 1 Sep 2022 15:39:39 -0700 (PDT) Shaun Deacon <shaun....@us.socionext.com> wrote:

> In one of my applications I have a "replay" function which saves the current
> display by saving serialized canvas data. When the user wants to replay, the
> current canvas display is deleted and recreated from the serialized data.
> Unfortunately, I have other data that is stored which relies on the original
> canvas ID's - this has to be adjusted when the new canvas objects are
> created. If the initial canvas ID were reset, this would be simplified for
> me.

It is probably bad practice to depend on something like the *internally
generated* canvas IDs, over which you don't have control. If you need unique
and *repeatable* IDs, you should generate them yourself in a way that is known
and controlled by your program.

>
> best regards
> Shaun
>
>
>

--
Robert Heller -- Cell: 413-658-7953 GV: 978-633-5364
Deepwoods Software -- Custom Software Services
http://www.deepsoft.com/ -- Linux Administration Services
hel...@deepsoft.com -- Webhosting Services

Ralf Fassel

unread,
Sep 2, 2022, 8:57:56 AM9/2/22
to
* Shaun Deacon <shaun....@us.socionext.com>
| In one of my applications I have a "replay" function which saves the
| current display by saving serialized canvas data. When the user wants
| to replay, the current canvas display is deleted and recreated from
| the serialized data. Unfortunately, I have other data that is stored
| which relies on the original canvas ID's - this has to be adjusted
| when the new canvas objects are created. If the initial canvas ID were
| reset, this would be simplified for me.

Check the -tags option when creating the items. If you reset the tag
number in your code when you delete the canvas, you can recreate the
items with the same -tags as before, and use the tag instead of the id
to adress individual items.

$canvas create ... -tags t[incr mycounter]
...
# now address objects by t1 t2 etc instead of the id returned by [canvas create]

# reset
set mycounter 0
# recreate
$canvas create ... -tags t[incr mycounter]

man canvas(n)
When specifying items in canvas widget commands, if the specifier
is an integer then it is assumed to refer to the single item with
that id. If the specifier is not an integer, then it is assumed
to refer to all of the items in the canvas that have a tag
matching the specifier. The symbol tagOrId is used below to
indicate that an argument specifies either an id that selects a
single item or a tag that selects zero or more items.

HTH
R'

Shaun Deacon

unread,
Sep 2, 2022, 3:27:10 PM9/2/22
to
Thank you all for your suggestions.

> Robert wrote
> It is probably bad practice to depend on something like the *internally
> generated* canvas IDs, over which you don't have control. If you need unique
> and *repeatable* IDs, you should generate them yourself in a way that is known
> and controlled by your program.

I take your point, and your key emphasis is *repeatable*. In most cases, I still think it is completely reasonable to use the returned ID from 'canvas create', otherwise what is the purpose of returning an ID at all if it shouldn't be used ?
BTW, From my original post, without knowing what is going on under the hood, intuitively one would still expect "canvas delete all' to reset the ID counter because all objects have been deleted.

> Arjen Wrote
> Could an alternative approach be to update the canvas items themselves? Or to store unique tags for each item?

Actually, when my <serialized> canvas data is reloaded this is kind of what I am doing - I use a map which I create by looking at the tags for each object (eg. set obj(<old>,id) <new>) when it is created. The map is then applied accordingly to each new canvas object to adjust the ID's (and tags).
BTW, I like the <serialize>/<deserialize> approach because it's a fast way to do a complete re-display even with my post creation adjustment.

> Ralf wrote
> Check the -tags option when creating the items. If you reset the tag
> number in your code when you delete the canvas, you can recreate the
> items with the same -tags as before, and use the tag instead of the id
> to adress individual items.
> $canvas create ... -tags t[incr mycounter]
> now address objects by t1 t2 etc instead of the id returned by [canvas create]
> # reset
> set mycounter 0
> # recreate
> $canvas create ... -tags t[incr mycounter]

Yes, I understand the approach and actually I use tags extensively to reference objects. However, I currently use the generated ID as a key for many tags - for example "C<id>" for cells, "P<id>" for ports, "N<id>" for nets etc...
I could do as you suggested, and maintain unique counters for different objects which would remove the dependence on the generated canvas ID's. However, of course this would mean more work internally for my application.

I'm still interested in why the ID counter is not reset internally when all objects are deleted (just from an understanding POV)...

BTW, even if the ID counter was reset, in my case I would still need to make adjustments to the new canvas objects because any objects that were individually deleted would still affect the new ID values when the objects are recreated.

best regards,
Shaun

Robert Heller

unread,
Sep 2, 2022, 4:46:55 PM9/2/22
to
At Fri, 2 Sep 2022 12:27:07 -0700 (PDT) Shaun Deacon <shaun....@us.socionext.com> wrote:

>
> Thank you all for your suggestions.
>
> > Robert wrote
> > It is probably bad practice to depend on something like the *internally
> > generated* canvas IDs, over which you don't have control. If you need unique
> > and *repeatable* IDs, you should generate them yourself in a way that is known
> > and controlled by your program.
>
> I take your point, and your key emphasis is *repeatable*. In most cases, I
> still think it is completely reasonable to use the returned ID from 'canvas
> create', otherwise what is the purpose of returning an ID at all if it
> shouldn't be used ?

They are like process IDs and like process IDs, they have no persistent
lifetime. They do have a "transient" lifetime, so can be used as such -- as
long as the item still exists, but when the item is gone (eg deleted), the ID
it *had* is no longer valid and never will be used again for this canvas
widget incarnation.

> BTW, From my original post, without knowing what is going on under the hood,
> intuitively one would still expect "canvas delete all' to reset the ID
> counter because all objects have been deleted.

"canvas delete all" is NOT anything special and is not really any different
than "canvas delete footag" where footag is just a tag shared by some random
set of canvas items. In other words, the "canvas delete <mumble>" command has
no way of knowing that all items will be deleted and thus all ids are now up
for grabs. It has to be coded such that there may be some ids still in use
and thus can't assume that all possible ids are available for re-use. So the
canvas code never recycles canvas IDs and the IDs are always monotonically
increasing until the canvas widget is destroyed.

>
> > Arjen Wrote
> > Could an alternative approach be to update the canvas items themselves? Or to store unique tags for each item?
>
> Actually, when my <serialized> canvas data is reloaded this is kind of what I am doing - I use a map which I create by looking at the tags for each object (eg. set obj(<old>,id) <new>) when it is created. The map is then applied accordingly to each new canvas object to adjust the ID's (and tags).
> BTW, I like the <serialize>/<deserialize> approach because it's a fast way to do a complete re-display even with my post creation adjustment.
>
> > Ralf wrote
> > Check the -tags option when creating the items. If you reset the tag
> > number in your code when you delete the canvas, you can recreate the
> > items with the same -tags as before, and use the tag instead of the id
> > to adress individual items.
> > $canvas create ... -tags t[incr mycounter]
> > now address objects by t1 t2 etc instead of the id returned by [canvas create]
> > # reset
> > set mycounter 0
> > # recreate
> > $canvas create ... -tags t[incr mycounter]
>
> Yes, I understand the approach and actually I use tags extensively to reference objects. However, I currently use the generated ID as a key for many tags - for example "C<id>" for cells, "P<id>" for ports, "N<id>" for nets etc...
> I could do as you suggested, and maintain unique counters for different objects which would remove the dependence on the generated canvas ID's. However, of course this would mean more work internally for my application.
>
> I'm still interested in why the ID counter is not reset internally when all objects are deleted (just from an understanding POV)...
>
> BTW, even if the ID counter was reset, in my case I would still need to make adjustments to the new canvas objects because any objects that were individually deleted would still affect the new ID values when the objects are recreated.
>
> best regards,
> Shaun
>
>
>

Shaun Deacon

unread,
Sep 2, 2022, 6:13:07 PM9/2/22
to
On Friday, September 2, 2022 at 1:46:55 PM UTC-7, Robert Heller wrote:
> "canvas delete all" is NOT anything special and is not really any different
> than "canvas delete footag" where footag is just a tag shared by some random
> set of canvas items. In other words, the "canvas delete <mumble>" command has
> no way of knowing that all items will be deleted and thus all ids are now up
> for grabs. It has to be coded such that there may be some ids still in use
> and thus can't assume that all possible ids are available for re-use. So the
> canvas code never recycles canvas IDs and the IDs are always monotonically
> increasing until the canvas widget is destroyed.

Your explanation makes perfect sense, thank-you.

Technically, the 'canvasPtr->nextId' field could be reset when the tag/object search list is empty (everything has been deleted)
However, on reflection, this doesn't really have that much merit.

Actually I have an analogous situation in my application (which is an EDA tool). For some cases, I need to create "logical nets" that are given generic names with a counter value ('ID") appended to make them unique. When a net is deleted, I don't re-use the ID because the name is not that important (it only needs to be unique) - keeping track of reusable ID's would only add unnecessary complexity.

Thanks for taking the time to explain.

best regards,
Shaun

Rich

unread,
Sep 2, 2022, 8:47:36 PM9/2/22
to
Shaun Deacon <shaun....@us.socionext.com> wrote:
> BTW, From my original post, without knowing what is going on under
> the hood, intuitively one would still expect "canvas delete all' to
> reset the ID counter because all objects have been deleted.

No one should not expect such, the current behavior of id's is
documented:

man canvas:

...
The id of an item never changes and id numbers are never re-used
within the lifetime of a canvas widget.
...

Note the clause after "and".

0 new messages