Paul McNett wrote:
> Carl Karsten wrote:
>> Paul McNett wrote:
>>> Carl Karsten wrote:
>>>> Paul McNett wrote:
>>>>> Carl Karsten wrote:
>>>>>> Paul McNett wrote:
>>>>>>> Carl Karsten wrote:
>>>>>>>>> Where are these files again? Please don't point me to the list 
>>>>>>>>> archives, 
>>>>>>>>> as I can't easily copy/paste code from that webpage.
>>>>>>>> Oh yeah, that whole html eats whitespace thing...
>>>>>>>>
>>>>>>>> hnmm, looks like I botched the file name too. - was called bd1, 
>>>>>>>> renamed the 
>>>>>>>> files to cdxml2objDemo1 but didn't change dabo.ui.createForm()
>>>>>>>>
>>>>>>>> http://dev.personnelware.com/carl/temp/May31/a/cdxml2objDemo1.tgz
>>>>>>> Ok, your code runs, and when I click "swap" it swaps. What's the 
>>>>>>> problem?
>>>>>>>
>>>>>> I am trying to replace this code in this file:
>>>>>>
>>>>>> # cdxml2objDemo1-code.py
>>>>>> ## *!* ## Dabo Code ID: dButton-dForm
>>>>>> def onHit(self, evt):
>>>>>> self.Form.myObj1.swap()
>>>>>> self.Form.update()
>>>>>>
>>>>>> With something in the cdxml file that connects the button to 
>>>>>> myObj1.swap() in a 
>>>>>> similar way that the text box's are connected to the attributes.  (once 
>>>>>> that 
>>>>>> happens, the displaced .update() can be dealt wtih.)
>>>>> Well, it appears that Ed hasn't yet added the ability to put a 
>>>>> OnHit="self.Form.myObj1.swap" in the attributes for the button, but 
>>>>> that's how you would do it if it were supported. You'd also have to add 
>>>>> an evt arg to your swap function:
>>>>>
>>>>>    def swap(self, evt=None):
>>>> um, if it hasn't been implemented, then how do you know it would need the 
>>>> parameter?
>>> Because that's how event binding works - the callback takes an argument 
>>> that contains the event object. This *has been* implemented in Dabo for 
>>> years now. What hasn't been implemented in cdxml is the ability to 
>>> specify the binding in the constructor. Here, in raw-dabo:
>>>
>>> import dabo
>>> dabo.ui.loadUI("wx")
>>>
>>> def onButtonHit(evt):
>>>     print "hit!", evt.EventObject
>>>
>>> app = dabo.App()
>>> app.setup()
>>> but = dabo.ui.dButton(app.MainForm, OnHit=onButtonHit, Caption="!")
>>> app.start()
>>>
>> OK, so it could be implemented without that:
>>
>> well, first it has to run with it....
>>      app = dabo.App()
>> AttributeError: 'module' object has no attribute 'App'
>>
>> ok, no prob, I can add a d...
> 
> :)  Cool, you passed that test.
> 
> 
>> it runs, but I see no button.
> 
> Forgot that there's a platform inconsistency there. It works on Mac, BTW.

eh!?  Is anyone cataloging the platform inconsistencies?  I think I am now 
aware 
of 3,

Any chance of a linux ver?

> 
>> The plan was to pipe the call through a generic function that strips the 
>> event 
>> argument.
> 
> The event argument is kind of important; I never thought of trying to 
> strip it out. Good luck with that. :)
> 

So far the only use I have seen for the event argument is to identify what 
object raised the event, which can be dealt with by having each event call a 
unique function.  I am not sure which is better :)

current way (kinda):
UI1 calls OnHitX(1)
UI2 calls OnHitX(2)
UI3 calls OnHitX(3)

Without event arg:
UI1 calls OnHit1()
UI2 calls OnHit2()
UI3 calls OnHit3()

def OnHitX(objID): pass
def OnHit1(): OnHitX(1)
def OnHit2(): OnHitX(2)
def OnHit3(): OnHitX(3)


> 
>>>> or, why does it need that parameter?
>>> Because that's how event binding works, the callback function takes an 
>>> event argument.
>> um, you may as well say "because it is written that way."  The code you 
>> posted 
>> doesn't use the parameter for anything useful.  I can see the thought that 
>> it 
>> might be handy, but has anyone actually used it?
> 
> Occasionally it is useful, 

That defines everything in a computer, but I sure don't everything passed :)

I know in VFE I often wished that my BO code had a reference to the UI, but 
right now I can't really think of a good reason.

 > usually my code doesn't need it, but as I
> said above it is somewhat important to keep alive because of the way wx 
> events work. Once that event object goes out of scope, wx takes over 
> again and propagates it up a level. In order to keep things working 
> sanely, you really need to accept the evt arg even if you don't actually 
> use it.

When you say "out of scope" you really mean released/destroyed right?

otherwise this would not work:

def onButtonHit(evt):
         foo()
         return

def foo():
         print "hit!"

Which means the evt arg could be kept alive in some framework code.

> 
>>>>> ... and yes, you do need to explicitly call update(): how else do you 
>>>>> expect Dabo to know that your object's attribute values have changed?
>>>> Few things come to mind:
>>>>
>>>> Given that most button clicks cause something to happen that requires the 
>>>> form 
>>>> to be updated, build it into the button.  If that causes a problem, add an 
>>>> switch to turn it off.
>>> You are saying that every time any button on the form gets clicked, call 
>>> but.Form.update()?
>> yes.  given my given, seems reasonable.  (course I am not sure how valid my 
>> given is.)
> 
> Is it too much to ask the end programmer to make some explicit calls now 
> and then? 

Yes, if the framework can take care of it.  I pretty much don't want code in my 
  app that could be coded in the framework.

 >
The Dabo framework has no idea how much processing is going to
> be triggered by a call to update(). Could be minimal, but could be huge. 
> I, for one, would like to have control over when it is called.

  "If that causes a problem, add an switch to turn it off."

How many of your button's don't result in a .update()?

> 
> 
>>>> Create a class that is specifically for storing values that might be 
>>>> displayed 
>>>> using Dabo UI objects.  When the Dabo UI object is bound to the 'value 
>>>> object', 
>>>> it registers itself.  Now the value object has a reference to all the UI 
>>>> objects 
>>>> that are bound to it. When the value object's value is updated, it calls 
>>>> the 
>>>> .update() of the UI objects bound to it.  This may sound like a bit of 
>>>> overhead 
>>>> that will slow things down, but I bet it is faster than calling .update().
>>> FWIW, there is just such a device already: binding controls to a 
>>> dBizobj, and registering the bizobj with the dForm: whenever the bizobj 
>>> field value changes, the form calls update() automatically.
>> um, make up your mind...
>>
>> I'm guessing you meant .update() needed to be called somehow, and that I 
>> needed 
>> to do something to make that happen.  sounds like one thing that could be 
>> done 
>> is change
>> class myClass(object):
>> to
>> class myClass(dabo.biz.dBizobj):
>> and register the bizobj with the dForm -
>> which sounds pretty good.  course I have no idea how to register it with the 
>> form.  shouldn't this be something that happens when the UI control is bound?
> 
> Ok, ok... it is when the dForm recognizes that the record pointer has 
> moved, or that a requery has happened, that update() is called 
> automatically. The dForm methods like next(), prior(), new(), delete(), 
> requery() all result in a update() being called. It only relies on a 
> bizobj being present because those form methods assume that a bizobj is 
> present.
> 
> Remember, we designed Dabo assuming a database, mediated by a dBizobj, 
> and a form mediating the dBizobj calls.

I'm starting to think the n-tier thing didn't get done as well as it could.

otoh, I may be trying to take some short cuts and screwing things up.

thrird hand, it isn't as important as having something working, so I am not 
going to loose too much sleep over it.


> 
> 
>>>> I am somewhat surprised that the wx controls don't do this automatically, 
>>>> but I 
>>>> have 0.0 idea what wx controls can/can't do.
>>> You have to do programming to specify what the wx controls 
>>> should/shouldn't do. You say that a wx.Button should call 
>>> dabo.ui.dForm.update(), when wx is completely unaware of the existence 
>>> of Dabo?
>> No, I am saying that the wx text box should update itself (just the text 
>> box) 
>> when the value it is bound to changes.  (again, I have no clue how feasible 
>> that 
>> is.)
> 
> wx has no notion of data binding at all. To set the value, you call 
> wx.TextCtrl.SetValue(), and to get the value, you call GetValue(). Data 
> binding is one of the things Dabo adds to the picture.
> 
> 

Oh... see, your comment about learning raw dabo could be extended to learning 
wxPyton, and on to pure wx - none of witch I have enough desire to do :)


>>>>> Until the OnHit works within cdxml, you can put the following at the 
>>>>> bottom of your main .py file:
>>>>>
>>>>> if __name__ == "__main__":
>>>>>
>>>>>     app = dabo.dApp(MainFormClass=None)
>>>>>     app.setup()
>>>>>     frm = dabo.ui.createForm('cdxml2objDemo1.cdxml')
>>>>>     frm.myObj1=myClass()
>>>>> ## - new line below
>>>>>     frm.but.bindEvent(dabo.dEvents.Hit, frm.myObj1.swap)
>>>>> ## - new line above
>>>>>     frm.show()
>>>>>     app.start()
>>>>>
>>>>> ...and then get rid of the -code.py file.
>>>>>
>>>> Traceback (most recent call last):
>>>>    File "cdxml2objDemo1.py", line 31, in ?
>>>>      frm.but.bindEvent(dabo.dEvents.Hit, frm.myObj1.swap)
>>>> AttributeError: 'dForm_276318141' object has no attribute 'but'
>>>>
>>>> <dButton sizerInfo="{'BorderSides': ['All'], 'Proportion': 0, 'HAlign':
>>>> 'Center', 'VAlign': 'Middle', 'Border': 0, 'Expand': False}"
>>>> code-ID="dButton-dForm" designerClass="controlMix" Caption="Swap" />
>>>>
>>>> Where did the 'but' in frm.but.bindEvent come from?
>>> Sorry, forgot to tell you to add RegID="but" in the dButton attributes 
>>> in the xml.
>>>
>> bingo.
>>
>> OK, added some code:
>>
>>     def swap(self, evt):
>>       self.myAttrib1, self.myAttrib2 = self.myAttrib2, self.myAttrib1
>>       print evt.EventObject
>>       code.interact(local=locals())
>>
>>
>>  >>> dir(evt)
>> ['Application', 'BaseClass', 'BasePrefKey', 'Class', 'Continue', 
>> 'EventData', 
>> 'EventObject', 'LogEvents', 'Name', 'Parent', 'PreferenceManager', 
>> '_EventBindings', '__class__', '__delattr__', '__dict__', '__doc__', 
>> '__getattr__', '__getattribute__', '__hash__', '__init__', '__module__', 
>> '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', 
>> '__slots__', '__str__', '__weakref__', '_addCodeAsMethod', '_afterInit', 
>> '_args', '_autoBindEvents', '_baseClass', '_beforeInit', '_call_afterInit', 
>> '_call_beforeInit', '_call_initProperties', '_continue', '_eventData', 
>> '_eventObject', '_expandPropStringValue', '_extractKey', 
>> '_extractKeyWordEventBindings', '_extractKeywordProperties', 
>> '_getApplication', 
>> '_getBaseClass', '_getBasePrefKey', '_getClass', '_getContinue', 
>> '_getEventBindings', '_getEventData', '_getEventObject', '_getLogEvents', 
>> '_getName', '_getParent', '_getPreferenceManager', '_initProperties', 
>> '_insertEventData', '_kwargs', '_logEvent', '_removeAutoBindings', 
>> '_setBasePrefKey', '_setContinue', '_setEventBindings', '_setEventData', 
>> '_setEventObject', '_setKwEventBindings', '_setLogEvents', '_setName', 
>> '_setParent', '_setPreferenceManager', '_uiEvent', 'afterInit', 
>> 'appliesToClass', 'autoBindEvents', 'beforeInit', 'bindEvent', 'bindEvents', 
>> 'doDefault', 'getAbsoluteName', 'getEventList', 'getMethodList', 
>> 'getProperties', 'getPropertyInfo', 'getPropertyList', 'getValidEvents', 
>> 'initEvents', 'initProperties', 'raiseEvent', 'setProperties', 
>> 'setPropertiesFromAtts', 'stop', 'super', 'unBindEvent', 'unbindEvent']
>>
>> What is the point of the evt parameter?
> 
> 1) It gives you a hook into the event propagation process. Call 
> evt.stop() and no other handlers bound to that event will be called. 
> This includes base native behavior.

I think this caused something to click:

frm.but.bindEvent(dabo.dEvents.Hit, frm.myObj1.swap)

This is connecting the wx event to frm.myObj1.swap - no Dabo code will be run, 
right?

If so, then I totally see the point in "all of this."  Not sure I like it, but 
I 
sure don't know enough to have an opinion that matters :)

> 
> 2) If you have a generic event handler that could receive events from 
> several objects, you may well need to know what object emitted the 
> event, so you'd get that reference using evt.EventObject.

I can shoot that one down in a heartbeat: Don't have a generic event handler.

That reason could be applied to every single function: you need to pass a 
reference of the calling object in case the function needs to know who called 
it.  no, that's dumb.

> 
> 3) Some data is included with the event that may or may not otherwise be 
> available from the object directly, such as the exact position of the 
> mouse on the screen when the event occurred (mouse could be in a 
> completely different place by the time our event handler responds to the 
> event), what modifier keys were down when the event occurred, what list 
> item was selected when the event occurred, etc. etc.
> 

yeah, I'm seeing that whatever gets called is the first place any 'app side' 
code can run, maybe even framework code.  I may actually be breaking n-tier 
rules by having the wx object call my BO method - (n>3 in this case.  i'm 
seeing 
wx in it's own tier, above some python UI code (mix of dabo and app), above the 
BO code.

> 
>> Is there any way I can use it to get to the form to call .update?
> 
> No, and I don't understand why you are resisting just calling 
> self.Form.update() when needed.

cuz self is my BO, which has no Form or any other reference to the form.

> 
> 
>> (not that I think that is a good idea, just trying to get a grip on what I 
>> can 
>> do with that parameter.)
> 
> The three things I listed comprise nearly 100% of the use I've seen for it.
> 
> 
>>>>>> 4. To me it is poor style to have code in the UI, and I thought Ed 
>>>>>> claimed the 
>>>>>> x-code.py file was just for the convince of the developer that wanted to 
>>>>>> edit 
>>>>>> code using the Dabo CD.
>>>>> I don't see how you'll get rid of all UI code. I have a ton of UI code 
>>>>> and don't feel badly about it at all.
>>>> I think we need to define what this UI code is I want to get rid of.  I 
>>>> see a 
>>>> typical 3-tier framework app having 6 places code can live: each of the 3 
>>>> tiers 
>>>> will have framework code and 'app developer code.'  For the UI tier, if 
>>>> the 
>>>> app's UI is not doing anything that the Framework UI code can't handle, 
>>>> then the 
>>>> closest thing to code will be config data describing how to setup the 
>>>> controls 
>>>> (exactly what is in the .cdxml)
>>>>
>>>> If the app needs some loopy UI gizmo like "increase the font every time 
>>>> the 
>>>> mouse passes over it" then I need to write some UI code.
>>> Most UI code is layout code, yes. But also event handlers for acting 
>>> when the user clicks a button or something.
>> so tying the button to some method code, and the method code isn't UI 
>> specific, 
>> right?
> 
> Well, it receives the event parameter, which is ui specific. But 
> typically my event handler will call some bizobj method to actually do 
> the logical processing of whatever needs to happen, and get the return 
> value to work with at the UI level.

right.

So typically you don't need the event parameter.  same here, and I bet same 
with 
many other developers.  May want to consider a framework feature that deals 
with 
this so the app developers can concentrate on there app an not this extra 
parameter.

VFE had a button with a prop that contained the name of a method to call.  at 
run time, when the button was clicked, it magically figured out what object had 
the method.  it was handy, but I did not like the way the magic was implemented 
- cuz sometimes I had to help it, and i still wonder if it was worth the hassle 
it caused.

> 
>>>>>> Assuming this is correct:
>>>>>>  >>      Just add that line to the object's afterInit() method.
>>>>>> (which it isn't - object, [event], and .myMethod need to be replaced 
>>>>>> with the 
>>>>>> right names, and my object doesn't have an afterInit() method.  but 
>>>>>> assuming it 
>>>>>> is correct anyway...)
>>>>> That's where you edit it from within the -code.py file. You add the 
>>>>> afterInit() method there.
>>>>>
>>>> huh?  I can't even guess what you are talking about.  please elaborate.
>>> Open up your -code.py file, and after the "def onHit.." block, add:
>>>
>>> def afterInit(self):
>>>     print "afterInit", self
>>>
>>> Now run the main .py file. You should see:
>>> afterInit <dButton_9370141723 (baseclass dabo.ui.dButton)>
>>>
>>> Now put whatever code Ed wanted you to put there in that method. It gets 
>>> called after the button's init cycle is complete.
>> Ok, that seems plausible.  kinda goes against the goal of eliminating the 
>> -code.py file.
> 
> That was your goal, not mine. Eliminating the -code.py file is akin to 
> confining yourself to writing no code at all in the ui level. A bit 
> limiting, to say the least.

If I have no special (non framework provided) UI needs, I should not be writing 
UI code.  After using a framework for 10 years you may get on board with this 
concept :)

> 
> 
>>>>>> It seems awkward to have to have the BO layer attach itself to the UI 
>>>>>> objects, 
>>>>>> especially when some of the UI object attach themselves to the BO object 
>>>>>> (like 
>>>>>> the text box.)  Not to mention that means you can't use that BO object 
>>>>>> without 
>>>>>> the UI, unless you write some conditional code, which seems beyond 
>>>>>> awkward.
>>>>> I don't understand. How does the BO layer "attach itself" to the UI 
>>>>> objects? dBizobj isn't even aware that the UI layer exists. 
>>>> I was assuming I had to add that line to my BO class.  I don't know what 
>>>> else 
>>>> "the object's afterInit() method" would refer to.
>>> I interpreted it to be the button, but whatever, afterInit() is a hook 
>>> method of all Dabo objects. It is in fact one of the most commonly-used 
>>> hook methods, and I'm surprised you didn't know about it yet.
>> I kinda know about it, but in what I posted there just isn't anything 
>> applicable.  The only 2 things I could think of were  myClass(object) which 
>> isn't a dabo object, and it sure seemed like the button couldn't get to the 
>> instance of my class for scope reasons or something.
> 
> Well, it could get to it because your form has a reference to it, but 
> I'm not clear on what you were trying to do so I'll stop at that.
> 

Someone should ask Ed what he was talking about :)

>>>> I see you added it to the app's 'main' which is 'better' but still not the 
>>>> "Don't Repeat Yourself" mentality that I would expect from a framework. 
>>>> Actually nothing is being repeated... but it seems there is an extra step. 
>>>>  hmm, 
>>>> maybe it is just the 2 places to set things up: in the .cdxml for text 
>>>> boxes, 
>>>> and app's main for the button.  bah, this is just a side effect of the 
>>>> workaround to an unconfirmed missing feature.  This paragraph may not have 
>>>> anything to do with reality :)
>>> I think maybe you should take cdxml out of the picture for a while. Get 
>>> comfy with raw-dabo. You'll have a better understanding and appreciation 
>>> for what cdxml brings to the table. 
>> I can see the value, but I am skeptical it is worth the time.  I think my 
>> biggest problem is knowing what limitations the cdxml imposes.
> 
> It imposes some limits, sure. Not a lot of limits, I don't think. It's 
> biggest benefit is saving time laying out the controls. But it is in 
> active flux, and always changing, while the underlying Dabo is actually 
> quite stable. In the future I think people could start with cdxml and be 
> just fine; currently, I think everyone should spend the time to learn 
> the base Dabo way to do things first. But that's just me, I think.

In the end, I was able to use the CD much more effectively than trying to do it 
by hand.  The stuff I did by hand looked like total crap.  With the CD and less 
time I created a UI that was good enough.

BTW, thanks for waling me though this.  I think I learned something.

Carl K


_______________________________________________
Post Messages to: [email protected]
Subscription Maintenance: http://leafe.com/mailman/listinfo/dabo-users
Searchable Archives: http://leafe.com/archives/search/dabo-users
This message: http://leafe.com/archives/byMID/dabo-users/[EMAIL PROTECTED]

Reply via email to