ActiveX and MVP design

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

ActiveX and MVP design

Mikael Svane
During the past few days, I have experimented with an ActiveX control called
SpriteX that can be used for simple sprite animations. It is shareware and
can be downloaded from http://www.catalystpics.co.uk/spritex.htm . I am,
however, not able to get it to work properly and I don't quite understand
why.

Therefore, I thought that I might describe what I have done step-by-step in
case someone with more experience from this could explain to me what I
should change in order to make it work. The goal is to wrap this control
using the Basic MVP Component pattern, because I want to be able to use a
number of these controls in Shells.

1) The first thing I did after downloading and installing the control was to
open an AX Control Browser and examining it. This works and events are
generated.

2) I opened the AX Component Wizard and generated the two interfaces of the
control, _DSpriteX and _DSpriteEvents.

3) I subclassed AXControlSite with a new class that I called SpriteX.

4) I added the SpriteX class>>spriteX which looks like this (comments
removed):

SpriteX class>>spriteX

 | spriteX |

 spriteX := self progId: 'SPRITEX.SpriteXCtrl.1'.
 spriteX dispControl: (spriteX controlUnknown queryInterface: _DSpriteX).

 ^ spriteX

5) After that I added this instance side accessing method:

SpriteX>>dispControl: interface

 dispControl := interface

6) I then added another instance side method used to test the control:

SpriteX>>aboutBox
    "open the about box of the control."

    dispControl aboutBox

7) I then registered the new SpriteX class as a resource like this:

SpriteX makeResource: 'Default view' inClass: SpriteX

8) Now it was time to create a shell for testing the control. I made it a
subclass of Shell and called it SpriteTest.

9) I added an instance variable called spriteX to keep the SpriteX presenter
(which is also the view). After that I created #createComponents like this:

SpriteTest>>createComponents

    super createComponents.
    spriteX := self add: SpriteX spriteX name: 'SpriteX'

10) since the control doesn't have a proper model (instead it has a number
of sprites and a background) I decided not to override the default
#defaultModel class method.

11) I added a new view to SpriteTest using the VC and saved it as 'Default
view'. Therefore, I didn't have to override #defaultView either.

12) Thinking that I was finished, I evaluated:

SpriteTest show

which gave me the first walkback:

01:13:50,  den 30 december 2000: 'SpriteX does not understand
#parentPresenter:'
SpriteX(Object)>>doesNotUnderstand:
SpriteTest(CompositePresenter)>>add:name:
SpriteTest>>createComponents
SpriteTest(CompositePresenter)>>initialize
SpriteTest(Presenter)>>on:
SpriteTest class(Presenter class)>>on:
SpriteTest class(Presenter class)>>new
SpriteTest class(Shell class)>>create:
SpriteTest class(Presenter class)>>create
SpriteTest class(Presenter class)>>show

13) I guessed that this was because of me using the view as both view and
presenter (not finding #parentPresenter: since it belongs to Presenter and
not View) and therefore added an instance variable called parentPresenter to
SpriteX and generated accessors for it. Then I tried again:

01:22:18,  den 30 december 2000: 'SpriteX does not understand #view:'
SpriteX(Object)>>doesNotUnderstand:
[] in SpriteTest(CompositePresenter)>>view:
OrderedCollection>>do:
SpriteTest(CompositePresenter)>>view:
SpriteTest(Shell)>>view:
SpriteTest class(Shell class)>>create:
SpriteTest class(Presenter class)>>create
SpriteTest class(Presenter class)>>show

14) I repeated the above process with an instance variable called view. Then
I tried again. The result this time was that the 'Active-X Control Site
Copyright Object Arts Ltd' was shown instead of the SpriteX control.
Normally this means that the control hasn't been properly registered, but
after modifying AXControlSite class>>example2 I found out that this was not
the case this time. By debugging the code and examining the SpriteX instance
that was created, I found one thing that seemed strange. Although the
SpriteX instance's #parentPresenter is the SpriteTest instance, it's
#parentView isn't the ShellView of SpriteTest but instead a DesktopView. In
#example2 when the parentView is set manually to a ShellView which seems
more logical. I therefore tried to do something similar by modifying number
9) above:

SpriteTest>>createComponents

    super createComponents.
    spriteX := self add: (SpriteX spriteXOn: self view) name: 'SpriteX'

Unfortunately, this doesn't work, since the 'self view' at that time is a
DeafObject and not a proper view.


This leads to a number of questions:

a) are there any major design flaws in what I have described above?

b) is the analysis in 14) correct or is there another reason for the strange
behaviour?

c) asked in another thread: does my adding of #parentPresenter: and #view to
SpriteX have anything to do with the strange result and in that case, what
should be done instead?

d) and of course: what should I change in order to make it work?



If someone is still reading this I would be very grateful for any help in
solving the problem. By the way, if anyone would like to take a look at the
code, the package is only 29kB (but of course the ActiveX control is a bit
larger).

Thanks in advance

Mikael Svane
[hidden email]


Reply | Threaded
Open this post in threaded view
|

Re: ActiveX and MVP design

Ian Bartholomew
Mikael,

I know sod all about the ActiveX stuff but looking at the examples
(especially AXControlSite>>exanmple3) they don't appear to try to provide a
Presenter for the View.  The only linkage is seems to be that the
AXControlSite view knows who it's parent view is, and that should
automatically be done for you anyway when the views are created.

Try deleting the #createComponents method completely (which should get rid
of your #parentPresenter problem?) and communicate directly with the view.

SpriteText>>onViewOpened
    super onViewOpened.
    spriteX := self view viewNamed: 'SpriteX'.

But remember that it's just a guess from a position of complete ignorance
<g>

Ian


Reply | Threaded
Open this post in threaded view
|

Re: ActiveX and MVP design

Mikael Svane
Ian,

Thank you very much. This solved both the #parentPresenter: and the #view:
problems. However, the control still showed the Object Arts text instead of
the right one. Inspecting the SpriteX instance of SpriteTest showed that
it's progId was not the one that I had specified but instead was the
AXControlSite>>defaultProgId. Changing SpriteTest>>onViewOpened to this:

SpriteTest>>onViewOpened
    super onViewOpened.
    spriteX := self view viewNamed: 'SpriteX'.
    spriteX progId: 'SPRITEX.SpriteXCtrl.1'

solved the problem. I still haven't found why AXControlSite class>>progId:
(see SpriteX class>>spriteX in the original post) doesn't work in this case,
but I will investigate.

>
>But remember that it's just a guess from a position of complete ignorance
><g>


If my entire program didn't consist of "guesses from a position of complete
ignorance" it would probably work better. What you wrote seems to be more of
an educated guess to me ;)

Thanks a lot for your help!

Mikael Svane
[hidden email]


Reply | Threaded
Open this post in threaded view
|

Re: ActiveX and MVP design

Mikael Svane
>
>SpriteTest>>onViewOpened
>    super onViewOpened.
>    spriteX := self view viewNamed: 'SpriteX'.
>    spriteX progId: 'SPRITEX.SpriteXCtrl.1'
>
>solved the problem. I still haven't found why AXControlSite class>>progId:
>(see SpriteX class>>spriteX in the original post) doesn't work in this
case,
>but I will investigate.
>


There is a simple reason for this. Since the SpriteX is no longer created
using SpriteX class>>spriteX (which was evaluated in
SpriteTest>>createComponents which was removed), the default progId is used.
However, simply adding SpriteX>>defaultProgId doesn't work. For some reason

spriteX progId: 'SPRITEX.SpriteXCtrl.1'

must be used.


/Mikael
[hidden email]


Reply | Threaded
Open this post in threaded view
|

Re: ActiveX and MVP design

Ian Bartholomew
Mikael,

Glad I could help with the original problem.

> However, simply adding SpriteX>>defaultProgId doesn't work.

I can hopefully explain that as well as it's probably just a manifestation
of behaviour that you have to be aware of when creating View subclasses.
#defaultProgId is called from the view's #initialize method (when it is used
in the way you intend here) and the #initialize method is only called when
the view is initially created. Just adding #defaultProgId to a class will
not make any diference to existing instances (including the one stored in
the binary resource) of the class.

Try adding the #defaultProgId method, recreate the resource (using
#makeResource) and then recreate your Test shell to use the new resource.
Using 'mutate' in the VC will also work but only for the shellview instance
containing the subview you mutate (I think?)

Ian