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.
> 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. :)
>>> 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, 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.
>>>> ... 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? 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.
>>> 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 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.
>>>> 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.
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.
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.
> 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.
> (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.
>>>>> 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.
>>>>> 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.
>>> 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.
> The next time this comes up for me I'll take a shot at implementing OnHit in
> the
> cdxml.
Ok.
>>>> I use
>>>> dBizobj without a UI regularly.
>>> You also code your UI by hand, which seems to have more features than what
>>> can
>>> be currently be done with .cdxml.
>> The cdxml wraps Dabo, not the other way around, so I think this will
>> always be the case.
>>
>>
>>>> Understand, I haven't played much with the cdxml-way of doing things, so
>>>> my answers may not be well-informed enough.
>>> there's the problem... you are missing out on its potential goodness that
>>> hasn't
>>> been coded yet because you don't need it :)
>> Thinking about it, I think I misspoke about OnHit not being implemented
>> yet in cdxml. This is a constructor argument, and the xml doesn't define
>> what goes to the constructor, but what the properties are to be set to.
>> So... this feature is either already implemented in cdxml and I'm not
>> aware of it, or it will not be implemented in cdxml because there are
>> already other ways to do it (doesn't apply).
>>
>
> One thing I have been contemplating is re-writing the code that implements
> what
> the cdxml describes. I don't like the "write a big wad of .py and execute
> it"
> way. I have a feeling the objects can be instantiated "on the fly" which
> might
> help. but not any time soon.
Ok.
--
pkm ~ http://paulmcnett.com
_______________________________________________
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]