Trapping data on destroy

I've an app with a splitter window (split left-right) on top of a frame. A tree control is displayed in the left pane. When an object in the tree is selected, it's shown in the right pane in a wx.Notebook object that's a child of the panel (right pane).

When another item is selected in the left pane, my app is first destroying the children of the right pane, and then creating a new child object:

target.DestroyChildren()

I want to determine whether any data has been changed in any controls (i.e., children of) the wx.Notebook. If so, don't destroy and ask the user if he wants to save his changes. The wx.EVT_DESTROY event is bound to OnDestroy method:

def OnDestroy(self, event):
  print '**debug**','children=',self.GetChildren()
  for child in self.GetChildren():
    print '**debug**','child=',child

But, the children are already destroyed when this method is run.

Any suggestions?
Thanks.
Brian

I would think that you could store the currently selected item's text in
an instance variable like this:

self.selectedItem = treeObj.GetItemText(item)

Then when you select another item, you do some kind of check to see if the
new item's text matches the old item's text (or ID, or some other unique
identifier). If they're different, ask the user if they want to save.
Otherwise, destroy the children. Untested code below:

def OnSelection(self, event)
  previousItem = self.selectedItem
  # set the instance variable to the selected item
  self.selectedItem = treeObj.GetItemText(item)
  # compare the two
  if previousItem == self.selectedItem:
    # don't do anything
    pass
  else:
    # call the destroy children method

Then again, I may be looking at this completely wrong. I hope this gives
you some ideas anyway.

Mike

···

-----Original Message-----
From: Brian Wolf [mailto:brian.wolf@activustech.com]
Sent: Monday, May 21, 2007 10:34 AM
To: wxPython-users@lists.wxwidgets.org
Subject: Trapping data on destroy

I've an app with a splitter window (split left-right) on top
of a frame.
  A tree control is displayed in the left pane. When an
object in the tree is selected, it's shown in the right pane
in a wx.Notebook object that's a child of the panel (right pane).

When another item is selected in the left pane, my app is
first destroying the children of the right pane, and then
creating a new child
object:

target.DestroyChildren()

I want to determine whether any data has been changed in any
controls (i.e., children of) the wx.Notebook. If so, don't
destroy and ask the user if he wants to save his changes.
The wx.EVT_DESTROY event is bound to OnDestroy method:

def OnDestroy(self, event):
  print '**debug**','children=',self.GetChildren()
  for child in self.GetChildren():
    print '**debug**','child=',child

But, the children are already destroyed when this method is run.

Any suggestions?
Thanks.
Brian

Brian Wolf wrote:

I've an app with a splitter window (split left-right) on top of a frame. A tree control is displayed in the left pane. When an object in the tree is selected, it's shown in the right pane in a wx.Notebook object that's a child of the panel (right pane).

When another item is selected in the left pane, my app is first destroying the children of the right pane, and then creating a new child object:

target.DestroyChildren()

I want to determine whether any data has been changed in any controls (i.e., children of) the wx.Notebook. If so, don't destroy and ask the user if he wants to save his changes. The wx.EVT_DESTROY event is bound to OnDestroy method:

def OnDestroy(self, event):
    print '**debug**','children=',self.GetChildren()
    for child in self.GetChildren():
        print '**debug**','child=',child

But, the children are already destroyed when this method is run.

Give the right panel a way to get/set modified status, and probably a way to save the data as well. Then each of the items that will appear in the right panel will need to follow the same protocol too, and the right panel can traverse the children to find out their modified status. Then before you call DestroyChildren you can just call this new code, perhaps something like this pseudo code:

  if target.DataModified() and AskToSaveData():
    target.SaveData()
  target.DestroyChildren()

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

Hi,

I wasn't picturing the program in that light. I think your idea sounds
valid. You can use validators for the format and content part of the
program if you require specific input(s), although they'll probably need
some customization. Still, registering the object with a class is a valid
way to go. Hopefully the validation process itself won't slow the
performance noticeably.

Here's info on validators if you'd like to learn more:

http://wiki.wxpython.org/Creating_Validators_Based_on_State_Machines%2C_Pa
rt_I (this is part of a 4-part series)
http://wiki.wxpython.org/Validator_for_Object_Attributes

Mike

···

-----Original Message-----
From: Brian Wolf [mailto:brian.wolf@activustech.com]
Sent: Monday, May 21, 2007 2:24 PM
To: Mike Driscoll
Subject: Re: Trapping data on destroy

Thanks, Mike.

One factor is that there are many data items/controls on the
parent window. There are three types of validation to do on
data in a control:
format (particularly with dates, email addresses and the
like), content (for instance, Feb 30 might be good format but
bad content) and whether it has been modified.

I was thinking that perhaps I could write a class that would
allow each control on a window to be "registered" with the
class: data type, format and original value. The class could
have a method such as Validate() which performed (3 types of)
validation for each registered control.

Thoughts?

Brian

------------------------------------------------------
> Brian Wolf |
> Activus Technologies Corporation |
> brian@activustech.com | 410.367.2958 |
------------------------------------------------------
> Helping organizations gain a competitive advantage |
> through intelligent application of technology. |
------------------------------------------------------

Mike Driscoll wrote:
>
>
>> -----Original Message-----
>> From: Brian Wolf [mailto:brian.wolf@activustech.com]
>> Sent: Monday, May 21, 2007 10:34 AM
>> To: wxPython-users@lists.wxwidgets.org
>> Subject: Trapping data on destroy
>>
>> I've an app with a splitter window (split left-right) on top of a
>> frame.
>> A tree control is displayed in the left pane. When an object in
>> the tree is selected, it's shown in the right pane in a
wx.Notebook
>> object that's a child of the panel (right pane).
>>
>> When another item is selected in the left pane, my app is first
>> destroying the children of the right pane, and then creating a new
>> child
>> object:
>>
>> target.DestroyChildren()
>>
>> I want to determine whether any data has been changed in
any controls
>> (i.e., children of) the wx.Notebook. If so, don't destroy and ask
>> the user if he wants to save his changes.
>> The wx.EVT_DESTROY event is bound to OnDestroy method:
>>
>> def OnDestroy(self, event):
>> print '**debug**','children=',self.GetChildren()
>> for child in self.GetChildren():
>> print '**debug**','child=',child
>>
>> But, the children are already destroyed when this method is run.
>>
>>
>> Any suggestions?
>> Thanks.
>> Brian
>>
>>
>>
>
> I would think that you could store the currently selected
item's text
> in an instance variable like this:
>
> self.selectedItem = treeObj.GetItemText(item)
>
> Then when you select another item, you do some kind of
check to see if
> the new item's text matches the old item's text (or ID, or
some other
> unique identifier). If they're different, ask the user if
they want to save.
> Otherwise, destroy the children. Untested code below:
>
> def OnSelection(self, event)
> previousItem = self.selectedItem
> # set the instance variable to the selected item
> self.selectedItem = treeObj.GetItemText(item)
> # compare the two
> if previousItem == self.selectedItem:
> # don't do anything
> pass
> else:
> # call the destroy children method
>
>
> Then again, I may be looking at this completely wrong. I hope this
> gives you some ideas anyway.
>
> Mike
>

Thanks, Mike.

His (their collective) solution covers many cases, but probably *way* more complex than my app requires. For instance, in my app the user enters the dimensions of an item in feet and inches, in the ranges 0-200 and 0-11 respectively. That can easily be accomplished in a few lines of code in the EVT_CHAR event on a validator.

So I'll probably use subclasses of wx.PyValidator to perform format and content validation, while a Registrar (Mediator?) class can keep track of modifications and when to update the database.

Thanks.
Brian

Mike Driscoll wrote:

···

Hi,

I wasn't picturing the program in that light. I think your idea sounds
valid. You can use validators for the format and content part of the
program if you require specific input(s), although they'll probably need
some customization. Still, registering the object with a class is a valid
way to go. Hopefully the validation process itself won't slow the
performance noticeably.

Here's info on validators if you'd like to learn more:

http://wiki.wxpython.org/Creating_Validators_Based_on_State_Machines%2C_Pa
rt_I (this is part of a 4-part series)
Validator for Object Attributes - wxPyWiki

Mike

-----Original Message-----
From: Brian Wolf [mailto:brian.wolf@activustech.com] Sent: Monday, May 21, 2007 2:24 PM
To: Mike Driscoll
Subject: Re: Trapping data on destroy

Thanks, Mike.

One factor is that there are many data items/controls on the parent window. There are three types of validation to do on data in a control: format (particularly with dates, email addresses and the like), content (for instance, Feb 30 might be good format but bad content) and whether it has been modified.

I was thinking that perhaps I could write a class that would allow each control on a window to be "registered" with the class: data type, format and original value. The class could have a method such as Validate() which performed (3 types of) validation for each registered control.

Thoughts?

Brian

------------------------------------------------------
> Brian Wolf |
> Activus Technologies Corporation |
> brian@activustech.com | 410.367.2958 |
------------------------------------------------------
> Helping organizations gain a competitive advantage |
> through intelligent application of technology. |
------------------------------------------------------

Mike Driscoll wrote:

-----Original Message-----
From: Brian Wolf [mailto:brian.wolf@activustech.com]
Sent: Monday, May 21, 2007 10:34 AM
To: wxPython-users@lists.wxwidgets.org
Subject: Trapping data on destroy

I've an app with a splitter window (split left-right) on top of a frame.
  A tree control is displayed in the left pane. When an object in the tree is selected, it's shown in the right pane in a

wx.Notebook

object that's a child of the panel (right pane).

When another item is selected in the left pane, my app is first destroying the children of the right pane, and then creating a new child
object:

target.DestroyChildren()

I want to determine whether any data has been changed in

any controls

(i.e., children of) the wx.Notebook. If so, don't destroy and ask the user if he wants to save his changes.
The wx.EVT_DESTROY event is bound to OnDestroy method:

def OnDestroy(self, event):
  print '**debug**','children=',self.GetChildren()
  for child in self.GetChildren():
    print '**debug**','child=',child

But, the children are already destroyed when this method is run.

Any suggestions?
Thanks.
Brian

I would think that you could store the currently selected

item's text

in an instance variable like this:

self.selectedItem = treeObj.GetItemText(item)

Then when you select another item, you do some kind of

check to see if

the new item's text matches the old item's text (or ID, or

some other

unique identifier). If they're different, ask the user if

they want to save.

Otherwise, destroy the children. Untested code below:

def OnSelection(self, event)
  previousItem = self.selectedItem
  # set the instance variable to the selected item
  self.selectedItem = treeObj.GetItemText(item) # compare the two
  if previousItem == self.selectedItem:
    # don't do anything
    pass
  else:
    # call the destroy children method

Then again, I may be looking at this completely wrong. I hope this gives you some ideas anyway.

Mike