Subject Re: shortening references
From Gaetano <gaetanodd@hotmail.com>
Date Wed, 2 Sep 2020 18:55:45 +1000
Newsgroups dbase.getting-started
Attachment(s) dataForm.cfmmycontrols.cccustomer.wfm


Hi Andy,

Here are the files for the shortening of reference.

Customer.wfm is subclassed from base.cfm. Mytoolbar is in base.cfm.

Look at the Rowset_canSave event in customerForm.wfm. If the integrity
checks in that function are successful, I want to run the resetToolbar
function defined in the .cc file. I can reach it through
this.parent.parent.parent.mytoolbar1.resetToolbar() but I'd like to know
if it's possible to shorten that reference as well as understand why
FORM is unknown to that function, no matter how I store the reference (I
tried _app.oForm, public variable -- nothing makes the Form object
"known" to that canSave function.

Cheers,
Gaetano.


On 02/09/2020 09:38, Andy Taylor wrote:
> Gaetano,
>
> Just insert code like the following to gain confidence in the object tree:
>
> msgbox(""+this.name)
> msgbox(""+this.parent.name)
> msgbox(""+this.parent.parent.name)
>  
> What I don't understand is why you appear to have made the toolbar a child object of the rowset.
> I would have made the Toolbar a child object of the form.
>
> Andy
>
>> the 3 parent references take me back to a FORM object but my limited
>> understanding of object parenthood wrt SUBCLASSING doesn't allow me to
>> determine with certainty is whether that is base.cfm or customerForm.cfm
>>
>> I think it should be customerForm because:
>>
>> the 1st parent takes me from the form's rowset to the query level
>> the 2nd parent takes me to DMD level
>> the 3rd parent takes me to the form level of customerForm.wfm
>>
>>
>> Another thing that my limited understanding of object
>> parenthood/variable visibility doesn't enable me to understand is why I
>> cannot directly reference FORM.mytoolbar1 or customerForm.mytoolbar1 in
>> the canSave event.
>>
>> Any guidance would be much appreciated.
>>
>> Cheers,
>> Gaetano.
>>
>> On 02/09/2020 07:32, Lee Grant wrote:
>>> Gaetano,
>>>
>>> It might just be a typo but.....
>>>
>>> On 9/1/2020 4:52 PM, Gaetano wrote:
>>>>
>>>> I am trying to shorten script references by creating a shortcut to the
>>>> FORM object. This is in the tutorial's customer.wfm form that is
>>>> subclassed from the base.cfm form, in case it matters.
>>>>
>>>> I found this suggestion from Michael Nuwer and Ken in an old post but
>>>> I am unable to implement it.
>>>>
>>>> -------------------
>>>> function from_onOpen
>>>                ^
>>> Could this be the problem?
>>>
>>>
>>>> this.fMytablename1=form.testdatamaodule1.Mytablename1.rowset.fields
>>>>
>>>> function whatever
>>>> form.fMytablename1["myfieldName"].value
>>>> --------------------
>>>>
>>>>
>>>> Essentially, in the canSave event of customer.wfm, I want to write
>>>> something like:
>>>>
>>>> oF.mytoolbar1.resetToolbar()
>>>>
>>>> instead of
>>>>
>>>> this.parent.parent.parent.mytoolbar1.resetToolbar()
>>>>
>>>> Thanks for your help.
>>>>
>>>> Cheers,
>>>> Gaetano.
>>>>
>>>
>>
>




** END HEADER -- do not remove this line




class dataFormCForm of BASECFORM custom from :DT_custom:Base.cfm
   set procedure to :FormControls:seeker.cc additive
   set procedure to :DT_custom:mycontrols.cc additive
   with (this)
      onOpen = class::FORM_ONOPEN
      height = 473.0
      left = 247.0
      top = 163.0
      width = 619.0
      escExit = false
   endwith

   with (this.MYTITLETEXT1)
      text = "DataForm"
   endwith

   this.MYTABBOX1 = new MYTABBOX(this)
   with (this.MYTABBOX1)
      height = 22.0
      left = 0.0
      top = 449.0
      width = 617.0
   endwith

   this.SEEKER1 = new SEEKER(this)
   with (this.SEEKER1)
      height = 22.0
      left = 70.0
      top = 33.0
      width = 525.0
      pageno = 2
   endwith

   this.MYTEXTLABEL1 = new MYTEXTLABEL(this)
   with (this.MYTEXTLABEL1)
      height = 22.0
      left = 28.0
      top = 33.0
      width = 35.0
      text = "Find:"
      pageno = 2
   endwith

   this.MYGRID1 = new MYGRID(this)
   with (this.MYGRID1)
      pageno = 2
      height = 363.0
      left = 28.0
      top = 66.0
      width = 567.0
   endwith

   this.MYTOOLBAR1 = new MYTOOLBAR(this)
   with (this.MYTOOLBAR1)
      left = 99.0
      top = 35.0
      width = 429.0
      height = 37.0
   endwith


   function form_onOpen()
      if form.rowset # null
                        // don't allow automatic editing
                        form.rowset.autoEdit := false
                        // assign this method to the rowset's canNavigate:
                        form.rowset.canNavigate := class::rowset_canNavigate                        
                        // go to the first row ...
                        form.rowset.first()
                endif
   return


           function rowset_canNavigate()
                /*
                        Check to save any changes before allowing navigation.
                        For whatever reason, this gets called twice. If the
                        user chooses Yes to Save, or No to abandon, then
                        the next time through the rowset.modified property is
                        false so there's no problem. If the user chooses to
                        cancel the navigation, they'll get prompted twice.
                        For that reason, we set a flag to indicate it's been
                        here once. If the flag exists, we null it, if not we
                        run the validation.

                        BIG Note: If a future version of dBASE™ PLUS corrects the
                        behavior so the canNavigate routine does NOT fire
                        twice, this code will not work correctly.
                  
                        Applies to all dBASE builds through dBASE™ PLUS.

                        Code by Gary White
                */
                local bYes, nAnswer
                if type("_app.cancelNav") == "L" and _app.cancelNav
                        _app.cancelNav := null
                        bYes = false
                else
                        bYes = true
                        if this.modified
                                nAnswer = msgbox("Save changes before leaving record?",;
                                                          "Data has changed",32+3)
                                do case
                                        case nAnswer == 6 // Yes
                                                this.save()
                                        case nAnswer == 7 // No
                                                this.abandon()
                                        otherwise         // Cancel
                                                bYes := false
                                                _app.cancelNav = true
                                endcase
                        endif
                endif
        return bYes

        function resetToolbar                
                this.mytoolbar1.pbabandon.enabled=true
                this.mytoolbar1.pbsave.enabled=true
                this.mytoolbar1.pbdelete.enabled=true
                this.mytoolbar1.pbnext.enabled=true
                this.mytoolbar1.pbprevious.enabled=true
                this.mytoolbar1.pbedit.enabled=true
                this.mytoolbar1.pbnew.enabled=true

endclass



class MYENTRYFIELD(parentObj) of ENTRYFIELD(parentObj) custom
   with (this)
      onGotFocus = class::MYENTRYFIELD_ONGOTFOCUS
      height = 22.0
      left = 62.0
      top = 102.0
      width = 56.0
      metric = 6        // Pixels
      colorHighLight = "WindowText/0x80ffff"
      value = "MyEntryfield"
   endwith

   function MYENTRYFIELD_onGotFocus()
      this.keyboard( "{Home}" )
      return
endclass

class MYTEXT(parentObj) of TEXT(parentObj) custom
   with (this)
      height = 22.0
      left = 14.0
      top = 55.0
      width = 84.0
      metric = 6        // Pixels
      text = "MyText"
      borderStyle = 10        // Etched Out
   endwith

endclass

class MYTEXTLABEL(parentObj) of TEXTLABEL(parentObj) custom
   with (this)
      height = 22.0
      left = 53.0
      top = 107.0
      width = 84.0
      metric = 6        // Pixels
      transparent = true
      text = "MyTextLabel"
      fontBold = true
      alignHorizontal = 2        // Right
                alignVertical = 1          // Middle
   endwith

endclass


class MYSPINBOX(parentObj) of SPINBOX(parentObj) custom
   with (this)
      onGotFocus = class::MYSPINBOX_ONGOTFOCUS
      height = 22.0
      left = 60.0
      top = 202.0
      width = 56.0
      metric = 6        // Pixels
      picture = "99999"
      colorHighLight = "WindowText/0x80ffff"
      rangeMax = 100
      rangeMin = 1
      value = 1
   endwith

   function MYSPINBOX_onGotFocus()
      this.keyboard( "{Home}" )
        return
        
endclass

class MYCOMBOBOX(parentObj) of COMBOBOX(parentObj) custom
   with (this)
      onGotFocus = class::MYCOMBOBOX_ONGOTFOCUS
      onChange = class::MYCOMBOBOX_ONCHANGE
      height = 22.0
      left = 75.0
      top = 250.0
      width = 84.0
      metric = 6        // Pixels
      colorHighLight = "WindowText/0x80ffff"
      style = 2        // DropDownList
      dropDownHeight = 132.0
   endwith

   function MYCOMBOBOX_onGotFocus()
                this.savedValue = this.value
   return
   function MYCOMBOBOX_onChange()
      // this = combobox
                // datalink = field
                // parent = field array
                // parent = rowset
                if this.datalink.parent.parent.state == 1
                        this.value = this.savedValue
                        this.datalink.parent.parent.modified = false
                        this.datalink.parent.parent.abandon()
                endif
   return
endclass

class MYRADIOBUTTON(parentObj) of RADIOBUTTON(parentObj) custom
   with (this)
      transparent = true
      height = 24.0
      left = 217.0
      top = 22.0
      width = 110.0
      text = "Radiobutton"
      metric = 6        // Pixels
   endwith

endclass

class MYCONTAINER(parentObj) of CONTAINER(parentObj) custom
   with (this)
      transparent = true
      left = 432.0
      top = 42.0
      width = 184.0
      height = 101.0
      metric = 6        // Pixels
      borderStyle = 4        // Single
   endwith

endclass

class MYGRID(parentObj) of GRID(parentObj) custom
   with (this)
      colorHighLight = "WindowText/0x80ffff"
      cellHeight = 22.0
      rowSelect = true
      allowEditing = false
      allowAddRows = false
      height = 88.0
      left = 434.0
      top = 208.0
      width = 182.0
      metric = 6        // Pixels
                bgcolor="White"
   endwith

endclass

class MYTABBOX(parentObj) of TABBOX(parentObj) custom
   with (this)
      onSelChange = class::TABBOX_ONSELCHANGE
      onOpen = class::MYTABBOX_ONOPEN
      id = 110
      height = 22.0
      left = 0.0
      top = 316.0
      width = 644.0
      metric = 6        // Pixels
      colorHighLight = "WindowText/0x80ffff"
      dataSource = 'ARRAY {"Individual Record","Find Record"}'
   endwith

   function TABBOX_onSelChange()
      form.pageNo := this.curSel
   return
   function MYTABBOX_onOpen()
      this.curSel := 1
      form.pageNo := 1
   return
endclass

class MYIMAGE(parentObj) of IMAGE(parentObj) custom
   with (this)
      height = 88.0
      left = 209.0
      top = 80.0
      width = 99.0
      metric = 6        // Pixels
      alignment = 3        // Keep Aspect Stretch
   endwith

endclass

class MYEDITOR(parentObj) of EDITOR(parentObj) custom
   with (this)
      key = class::MYEDITOR_KEY
      height = 88.0
      left = 196.0
      top = 187.0
      width = 221.0
      metric = 6        // Pixels
      value = ""
      colorHighLight = "WindowText/0x80ffff"
      evalTags = false
      popupEnable = false
   endwith

   function MYEDITOR_key(nChar, nPosition,bShift,bControl)
      /*
                        This code by Gary White is provided to
                        get around a problem with rowsets that
                        have the autoEdit property set to false,
                        and editors. The editor seems to be immune
                        to this property once you make a change
                        in it -- if you then save or abandon, you
                        can actually edit the contents of the editor
                        object ...
                */
                // this = editor
                // dataLink = field
                // parent = fieldArray
                // parent = rowset
                if type( "this.datalink.parent.parent" ) # "U"
                        r = this.datalink.parent.parent
                        if r.autoEdit == false and ;
                                ( r.state # 2 and r.state # 3 )
                                return 0
                        endif
                endif
    return
endclass

class DISABLEDENTRY(parentObj) of MYENTRYFIELD(parentObj) custom
   with (this)
      when = class::DISABLEDENTRY_WHEN
      height = 22.0
      left = 71.0
      top = 324.0
      width = 56.0
      colorNormal = "White/Maroon"
      value = "DisabledEntry"
      mousePointer = 12        // No
   endwith

   function DISABLEDENTRY_when(bOpen)
      
      return false
endclass

class MYPUSHBUTTON(parentObj) of PUSHBUTTON(parentObj) custom
   with (this)
      height = 24.0
      left = 35.0
      top = 4.0
      width = 62.0
      text = "MyPushButton"
      metric = 6        // Pixels
   endwith

endclass

class MYTITLETEXT(parentObj) of MYTEXT(parentObj) custom
   with (this)
      height = 28.0
      left = 247.0
      top = 324.0
      width = 84.0
      colorNormal = "Blue/BtnFace"
      alignHorizontal = 1        // Center
      fontSize = 14.0
      text = "MyTitle"
      borderStyle = 1        // Raised
      speedTip = "Form Title"
   endwith

endclass
class MYTOOLBAR(parentObj, name) of MYCONTAINER(parentObj, name) custom
   with (this)      
      left = 182.0
      top = 363.0
      width = 429.0
      height = 37.0
   endwith

   this.PBNEW = new MYPUSHBUTTON(this)
   with (this.PBNEW)
      onClick = class::PBNEW_ONCLICK
      height = 24.0
      left = 7.0
      top = 6.0
      width = 64.0
      text = "&New"
      upBitmap = "filename :Glyfx:\Aero\CE\Dbase Aero\PNG\16x16\favourites_16.png"
      fontSize = 8.0
      speedTip = "Add new record"
      pageno = 0
   endwith

   this.PBEDIT = new MYPUSHBUTTON(this)
   with (this.PBEDIT)
      onClick = class::PBEDIT_ONCLICK
      height = 24.0
      left = 69.0
      top = 6.0
      width = 62.0
      text = "&Edit"
      upBitmap = "filename :Glyfx:\Aero\CE\Dbase Aero\PNG\16x16\document_open_16.png"
      fontSize = 8.0
      speedTip = "Edit current record"
      pageno = 0
   endwith

   this.PBSAVE = new MYPUSHBUTTON(this)
   with (this.PBSAVE)
      onClick = class::PBSAVE_ONCLICK
      height = 24.0
      left = 125.0
      top = 6.0
      width = 62.0
      text = "&Save"
      upBitmap = "filename :Glyfx:\Aero\CE\Dbase Aero\PNG\16x16\save_16.png"
      fontSize = 8.0
      speedTip = "Save current record"
      pageno = 0
   endwith

   this.PBABANDON = new MYPUSHBUTTON(this)
   with (this.PBABANDON)
      onClick = class::PBABANDON_ONCLICK
      height = 24.0
      left = 181.0
      top = 6.0
      width = 62.0
      text = "&Cancel"
      upBitmap = "filename :Glyfx:\Aero\CE\Dbase Aero\PNG\16x16\stop_16.png"
      fontSize = 8.0
      speedTip = "Cancel Changes"
      pageno = 0
   endwith

   this.PBDELETE = new MYPUSHBUTTON(this)
   with (this.PBDELETE)
      onClick = class::PBDELETE_ONCLICK
      height = 24.0
      left = 241.0
      top = 6.0
      width = 62.0
      text = "&Delete"
      upBitmap = "filename :Glyfx:\Aero\CE\Dbase Aero\PNG\16x16\delete_16.png"
      fontSize = 8.0
      speedTip = "Delete current record"
      pageno = 0
   endwith

   this.PBNEXT = new MYPUSHBUTTON(this)
   with (this.PBNEXT)
      onClick = class::PBNEXT_ONCLICK
      height = 24.0
      left = 360.0
      top = 6.0
      width = 62.0
      text = "&Next"
      upBitmap = "filename :Glyfx:\Aero\CE\Dbase Aero\PNG\16x16\arrow_right_16.png"
      fontSize = 8.0
      speedTip = "Next record"
      pageno = 0
   endwith

   this.PBPREVIOUS = new MYPUSHBUTTON(this)
   with (this.PBPREVIOUS)
      onClick = class::PBPREVIOUS_ONCLICK
      height = 24.0
      left = 300.0
      top = 6.0
      width = 62.0
      text = "&Previous"
      upBitmap = "filename :Glyfx:\Aero\CE\Dbase Aero\PNG\16x16\arrow_left_16.png"
      fontSize = 8.0
      speedTip = "Previous record"
      pageno = 0
   endwith

  
   function PBDELETE_onClick()
                if msgbox( "Delete this row?", "Delete Row?", 36 ) == 6
                        form.rowset.delete()
                        this.parent.resettoolbar()
                endif
      return
   function PBABANDON_onClick()
      if form.rowset.modified
                        if msgbox( "Abandon changes to this row?", "Abandon changes?", 36 ) == 6
                                form.rowset.abandon()
                                this.parent.resettoolbar()
                        endif
                else
                        form.rowset.abandon()
                endif
                
      return
   function PBPREVIOUS_onClick()
                if ( not form.rowset.next(-1) )
                        form.rowset.next()
                        msgbox( "At beginning of rowset", "Can't Navigate", 64 )
                endif  
      return
   function PBSAVE_onClick()
      form.rowset.save()
                this.parent.resettoolbar()
      return
   function PBNEW_onClick()
                this.parent.pbnext.enabled=false
                this.parent.pbprevious.enabled=false
      form.rowset.beginAppend()
   return
   function PBNEXT_onClick()
      if ( not form.rowset.next() )
               form.rowset.next( -1 )
               msgbox( "At end of rowset", "Can't Navigate", 64 )
            endif
      return
   function PBEDIT_onClick()
      form.rowset.edit()
      return
        function resetToolbar
                this.PBNEXT.enabled=true
                this.PBprevious.enabled=true
endclass


** END HEADER -- do not remove this line
//
// Generated on 02/09/2020
//
parameter bModal
local f
f = new customerForm()
if (bModal)
   f.mdi = false // ensure not MDI
   f.readModal()
else
   f.open()
endif

class customerForm of DATAFORMCFORM from :DT_custom:dataForm.cfm
   set procedure to customer.dmd additive
   set procedure to :FormControls:seeker.cc additive
   set procedure to :DT_custom:MyControls.cc additive
   with (this)
      onOpen = class::FORM_ONOPEN
      height = 465.0
      left = 559.0
      top = 137.0
      width = 638.0
      text = "Customer form"
   endwith

   this.CUSTOMERDATAMODULE1 = new CUSTOMERDATAMODULE()
   this.CUSTOMERDATAMODULE1.parent = this
   with (this.CUSTOMERDATAMODULE1)
      left = 511.0
      top = 396.0
      width = 100.0
      height = 37.0
   endwith

   with (this.MYTITLETEXT1)
      text = "Customer Information"
   endwith

   with (this.MYGRID1)
      dataLink = form.customerdatamodule1.customer1.rowset
      columns["COLUMN1"] = new GRIDCOLUMN(form.MYGRID1)
      with (columns["COLUMN1"])
         dataLink = form.customerdatamodule1.customer1.rowset.fields["last name"]
         editorType = 1        // EntryField
         width = 169.0
      endwith
      columns["COLUMN2"] = new GRIDCOLUMN(form.MYGRID1)
      with (columns["COLUMN2"])
         dataLink = form.customerdatamodule1.customer1.rowset.fields["first name"]
         editorType = 1        // EntryField
         width = 150.0
      endwith
      columns["COLUMN3"] = new GRIDCOLUMN(form.MYGRID1)
      with (columns["COLUMN3"])
         dataLink = form.customerdatamodule1.customer1.rowset.fields["city"]
         editorType = 1        // EntryField
         width = 203.0
      endwith
      with (columns["COLUMN1"].headingControl)
         value = "Last Name"
      endwith

      with (columns["COLUMN2"].headingControl)
         value = "First Name"
      endwith

      with (columns["COLUMN3"].headingControl)
         value = "City"
      endwith

   endwith

   this.LABNAME = new MYTEXTLABEL(this)
   with (this.LABNAME)
      height = 22.0
      left = 42.0
      top = 101.0
      width = 45.0
      text = "Name:"
   endwith

   this.ENTRYFIRST = new MYENTRYFIELD(this)
   with (this.ENTRYFIRST)
      dataLink = form.customerdatamodule1.customer1.rowset.fields["first name"]
      height = 22.0
      left = 105.0
      top = 101.0
      width = 112.0
   endwith

   this.ENTRYLAST = new MYENTRYFIELD(this)
   with (this.ENTRYLAST)
      dataLink = form.customerdatamodule1.customer1.rowset.fields["last name"]
      height = 22.0
      left = 231.0
      top = 101.0
      width = 168.0
   endwith

   this.LABADDRESS = new MYTEXTLABEL(this)
   with (this.LABADDRESS)
      height = 22.0
      left = 28.0
      top = 132.0
      width = 59.0
      text = "Address:"
   endwith

   this.ENTRYSTREET1 = new MYENTRYFIELD(this)
   with (this.ENTRYSTREET1)
      dataLink = form.customerdatamodule1.customer1.rowset.fields["street1"]
      height = 22.0
      left = 105.0
      top = 132.0
      width = 217.0
   endwith

   this.ENTRYSTREET2 = new MYENTRYFIELD(this)
   with (this.ENTRYSTREET2)
      dataLink = form.customerdatamodule1.customer1.rowset.fields["street2"]
      height = 22.0
      left = 105.0
      top = 154.0
      width = 217.0
   endwith

   this.ENTRYCITY = new MYENTRYFIELD(this)
   with (this.ENTRYCITY)
      dataLink = form.customerdatamodule1.customer1.rowset.fields["city"]
      height = 22.0
      left = 105.0
      top = 190.0
      width = 135.0
   endwith

   this.MYENTRYFIELD6 = new MYENTRYFIELD(this)
   with (this.MYENTRYFIELD6)
      dataLink = form.customerdatamodule1.customer1.rowset.fields["postal"]
      height = 22.0
      left = 385.0
      top = 190.0
      width = 70.0
   endwith

   this.COMBOSTATE = new MYCOMBOBOX(this)
   with (this.COMBOSTATE)
      dataLink = form.customerdatamodule1.customer1.rowset.fields["state id"]
      height = 22.0
      left = 243.0
      top = 190.0
      width = 121.0
   endwith

   this.COMBOCTY = new MYCOMBOBOX(this)
   with (this.COMBOCTY)
      dataLink = form.customerdatamodule1.customer1.rowset.fields["country id"]
      height = 22.0
      left = 469.0
      top = 190.0
      width = 154.0
   endwith

   this.LABCITY = new MYTEXTLABEL(this)
   with (this.LABCITY)
      height = 22.0
      left = 55.0
      top = 190.0
      width = 35.0
      text = "City:"
   endwith

   this.LABPHONE = new MYTEXTLABEL(this)
   with (this.LABPHONE)
      height = 22.0
      left = 40.0
      top = 226.0
      width = 50.0
      text = "Phone:"
   endwith

   this.LABCOMMENT = new MYTEXTLABEL(this)
   with (this.LABCOMMENT)
      height = 22.0
      left = 12.0
      top = 265.0
      width = 78.0
      text = "Comments:"
   endwith

   this.ENTRYPHONE = new MYENTRYFIELD(this)
   with (this.ENTRYPHONE)
      dataLink = form.customerdatamodule1.customer1.rowset.fields["phone"]
      height = 22.0
      left = 105.0
      top = 226.0
      width = 116.0
   endwith

   this.EDITCOMMENTS = new MYEDITOR(this)
   with (this.EDITCOMMENTS)
      height = 98.0
      left = 105.0
      top = 265.0
      width = 371.0
      dataLink = form.customerdatamodule1.customer1.rowset.fields["comments"]
   endwith

   this.rowset = this.customerdatamodule1.customer1.rowset

        
        function form_onOpen()
                public oForm
                oForm=form.rowset.parent.parent.parent
                //msgbox("super::mytoolbar1 is "+)
                //msgbox("This.oTop is "+this.oTop.baseclassname)
                //this.oTop=this.mytoolbar1
      if form.rowset # null
                        // don't allow automatic editing
                        form.rowset.autoEdit := false
                        // assign this method to the rowset's canNavigate:
                        form.rowset.canNavigate := class::rowset_canNavigate
                        form.rowset.canSave        := class::rowset_cansave                
                        // go to the first row ...
                        form.rowset.first()                                                
                endif
        
        

        function rowset_canNavigate()
        local bYes, nAnswer                
               if type("_app.cancelNav") == "L" and _app.cancelNav
                  _app.cancelNav := null
                  bYes = false
               else
                  bYes = true
                  if this.modified
                     nAnswer = msgbox("Save changes before leaving record?",;
                                "Data has changed",32+3)
                     do case
                        case nAnswer == 6 // Yes                                                                        
                           bYes = true
                                                                        if not this.canSave()
                                                                                _app.cancelNav = true
                                                                                bYes = false
                                                                        else        
                                                                                this.save()
                                                                                _app.cancelNav = true
                                                                        endif
                        case nAnswer == 7 // No
                           this.abandon() // abandon changes but stay on that record
                                                                        _app.cancelNav = true
                                                                        bYes = false
                        otherwise         // Cancel
                           bYes := false
                           _app.cancelNav = true
                     endcase
                  endif
               endif
            return bYes
                                
                                

        function rowset_canSave()
                local bRet
                bRet = true
                if type("_app.cancelNav") == "L" and _app.cancelNav
                  _app.cancelNav := null
                  bRet = false
                else
                        bRet = true
                        if this.modified                                     
                                cStr="|"+rtrim(this.parent.parent.parent.combocty.value)+"|"
                                cStr2="|"+rtrim(this.parent.parent.parent.combostate.value)+"|"
                                if this.state=="2" //if editing the row, country is a code
                                
                                                                                // TO-DO: this doesn't cover cases where the user may
                                                                                // accidentally change the country, in that scenario,
                                                                                //the country would be morphed too...
                                //msgbox("edit mode")
                                        if cStr$"|US|AU|"                                
                                                if empty(this.fields["state id"].value)
                                                        msgbox("The state ID cannot be empty for country "+;
                                                                this.fields["country id"].value,"Alert",64)
                                                                this.abandon()                                                                
                                                                bRet = false
                                                endif
                                        endif
                                        
                                elseif this.state=="3" //if appending a row, country is morphed
                                        if cStr $ "|United States|Australia|"        
                                                if empty(this.fields["state id"].value)
                                                        msgbox("The state ID cannot be empty for country "+;
                                                                this.fields["country id"].value,"Alert",64)                                                                
                                                                bRet = false
                                                endif
                                        endif
                                endif
                        endif
                endif
                
                if bRet=true
                msgbox("type of oForm is "+type("oForm")+", baseclass is "+oForm.baseclassname)
                        //oForm.mytoolbox1.resetToolbar()
                        //the above addressing doesn't work
                        
                        
                        this.parent.parent.parent.mytoolbar1.resettoolbar()
                        // the above addressing works
                        
                endif
                return bRet

endclass