Better MVP Resources?

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

Better MVP Resources?

Me
I know how to use google. I've seen every MVP tutorial that seems to
be out there. Is there anything that actual goes through what each
method does and the order these methods get called? I understand the
pattern, I'm just lost when it comes to Dolphin's implementation. Some
sort of interaction diagram would go a long way to clearing things up.

I would also very much like to find a decent example of how to create
a view (and tie it into the presenter) without using the view
composer. I HATE visual builders and I wish that IDEs would stop
shoving them down my throught. Specifically, I want to know how to tie
a view to a presenter when the view doesn't have a resource name.
Everything seems to revolve around the resource manager.

Basically, I have a component and I want to represent a scrollable
list of those components. I could have done this in Java in about a
half an hour. I've been spending days trying to figure out how to do
this in Dolphin with MVP and there doesn't seem to be a simple way.

What do I have to know if I don't use MVP? The more I look into it,
the less I want to use it. It's just too much overkill. I went with
Smalltalk so I can crank code out quickly. MVP is making development
slower than C++. It may be powerful, but I've got along quite well
without that kind of power in the past. Will I not be able to use
layout managers if I bypass MVP? Does anyone know of a good non-MVP
example that shows how to create a simple window with a few controls,
and the ability to handle resize events (assuming I can't use layout
managers)? You know, something simple I can build off of to create
anything, including a more productive framework. Just tell me how to
do the Win SDK basics and I'll handle the rest. I would kill for the
simplicity of Java GUI building in Smalltalk.

BTW, how do I open up a window with a label that has text in a non-MVP
way? The following leaves the model out, I guess (i.e. I don't see the
text):

        ContainerView show
                addSubView: (StaticText new text: 'Bla'; yourself)

Thanks for any help. MVP may have many benefits, but clarity of design
is not one of them. And clarity of design is the single most important
thing to me when it comes to developing an application. I want to be
able to sit down in a couple of years and understand what my app is
doing without having to figure out how Dolphin MVP works each time.
That either means good, specific documentation (which has been
promised for sometime, but has never materialized) or using a more
straight forward framework.

--chris corcoran


Me
Reply | Threaded
Open this post in threaded view
|

Re: Better MVP Resources?

Me
>BTW, how do I open up a window with a label that has text in a non-MVP
>way? The following leaves the model out, I guess (i.e. I don't see the
>text):
>
> ContainerView show
> addSubView: (StaticText new text: 'Bla'; yourself)

Oh, I got this part now. You can't set the text until the view is
added.


Reply | Threaded
Open this post in threaded view
|

Re: Better MVP Resources?

Ian Bartholomew-18
In reply to this post by Me
Chris,

I can't really address your main points as I am quite happy using the
ViewComposer (I haven't therefore had to, or wanted to, build views in code
since Dolphin 1) and am also reasonably happy about using MVP.  NB I'm *not*
saying you should feel the same - just that I haven't got the experience to
answer your questions.

> Basically, I have a component and I want to represent a scrollable
> list of those components. I could have done this in Java in about a
> half an hour. I've been spending days trying to figure out how to do
> this in Dolphin with MVP and there doesn't seem to be a simple way.

Here is a bit of workspace code that, I think, achieves what you want?

"show a shell"
s := Shell show.

"the top shell has a BorderLayout..."
s view layoutManager: BorderLayout new.

"...so we can centre the ScrollingDecorator we are about to add"
s view addSubView: (sc := ScrollingDecorator new).
sc arrangement: #center.

"now add a Container View to the ScrollingDecorator. This view, and anything
we put in it, will be scrolled as one"
sc addSubView: (cv := ContainerView new).
cv usePreferredExtent: true.

"add a couple of widgets to the ContainerView"
cv addSubView: (cb1 := CheckBox new).
cb1 position: 10 @ 10.
cv addSubView: (cb2 := CheckBox new).
cb2 position: 10 @ 50.

"now we change the preferred extent of the container and tell the
ScrollingDecorator to allow for the change. Scroll bars should appear and
you should be able to scroll the Container and CheckBoxes around"

cv preferredExtent: 1000@1000.
sc layout

The only thing you need do, from this point on, is to change the
ContainerViews preferredExtent when you add/remove components.  Everything
else is automatically taken care of.

The process of creating the structure is exactly the same when using the
ViewComposer.  As long as you give the ContainerView a name, so that you can
always locate it using

(aTopViewOfSomeSort) viewName: 'theContainerViewName'

then the only code you will need is the last bit above which tells the
ContainerView it's new extent.

You can also use a LayoutManager for the ContainerView if it's easier. As
in -

s := Shell show.
s view layoutManager: BorderLayout new.
s view addSubView: (sc := ScrollingDecorator new).
sc arrangement: #center.
sc addSubView: (cv := ContainerView new).
cv usePreferredExtent: true.
cv layoutManager: GridLayout new.
cv layoutManager
    columns: 4;
    rows: 20.
80 timesRepeat: [cv addSubView: CheckBox new].
cv preferredExtent: 1000@1000.
sc layout

> What do I have to know if I don't use MVP?

The above does use MVP.  At this sort of level you can usually just let the
components get on with it by themselves and only give it a prod, when you
want the container to resize in the above example, when needed.

Ian


Reply | Threaded
Open this post in threaded view
|

Re: Better MVP Resources?

Andy Bower
In reply to this post by Me
Chris,

> I know how to use google. I've seen every MVP tutorial that seems to
> be out there. Is there anything that actual goes through what each
> method does and the order these methods get called? I understand the
> pattern, I'm just lost when it comes to Dolphin's implementation. Some
> sort of interaction diagram would go a long way to clearing things up.
>
> I would also very much like to find a decent example of how to create
> a view (and tie it into the presenter) without using the view
> composer. I HATE visual builders and I wish that IDEs would stop
> shoving them down my throught. Specifically, I want to know how to tie
> a view to a presenter when the view doesn't have a resource name.
> Everything seems to revolve around the resource manager.
>
> Basically, I have a component and I want to represent a scrollable
> list of those components. I could have done this in Java in about a
> half an hour. I've been spending days trying to figure out how to do
> this in Dolphin with MVP and there doesn't seem to be a simple way.

I think you have two issues here that are exacerbating each other. You have
a problem that you are trying to solve (to dynamically create a scrollable
list of components) and, because you couldn't find an easy way to do this
within the MVP framework you've started to consider non-MVP and non-View
Composer methods of doing this.

First of all let me say that you can do what you want any of these ways;
using MVP and the VC, using MVP without the VC or without using MVP at all.
The simplest way by far(because that is the way that Dolphin is intended to
be used) is to use MVP and the View Composer. I can well accept that you
might find this hard to figure out without having "cut your teeth" on some
simpler MVP projects first but I'm attaching a sample file that took me 20
minutes to knock up (well 20 mins to do the code and another 15 mins to
write the package comment). I'd be interested to know if you'd have been
able knock this up in Java in 30 minutes if you had no experience using the
GUI framework. Somehow, I doubt it.

Load up the package at the end of this message and follow the instructions
in the package comment. You may find that transferring the package like this
will lose the method and comment formatting. Unfortunately, the news server
I'm posting this to does not accept attachments. I'll post an attachment
version in a separate message via another news server.

> What do I have to know if I don't use MVP? The more I look into it,
> the less I want to use it. It's just too much overkill. I went with
> Smalltalk so I can crank code out quickly. MVP is making development
> slower than C++. It may be powerful, but I've got along quite well
> without that kind of power in the past. Will I not be able to use
> layout managers if I bypass MVP? Does anyone know of a good non-MVP
> example that shows how to create a simple window with a few controls,
> and the ability to handle resize events (assuming I can't use layout
> managers)? You know, something simple I can build off of to create
> anything, including a more productive framework. Just tell me how to
> do the Win SDK basics and I'll handle the rest. I would kill for the
> simplicity of Java GUI building in Smalltalk.

If you want to dispenser with MVP and the View Composer altogether then you
can do so. As you rightly surmise this can be done by just sticking with
classes in the View hierarchy and by writing code to assemble the views
dynamically. I've just read Ian's reply and this would seem to illustrate
how to do this. Ian suggests that what he is doing is still MVP but I would
beg to differ. Apart from the fact he uses a Shell presenter as the top
level container nothing else involves presenters. If you use a ShellView
rather than a Shell then I would say that Ian's example is a pretty good
illustration of how to do it the "non-MVP" way.

Note: strictly speaking Dolphin Views still follow MVP. They have a model
and they are, in fact, their own presenters. However, you can forget all
this and program them as if they are just widgets and just use their
accessor methods to get and set data. Having said this, you may find come
across some odd "gotchas" with this way of working. This will simply be
because, AFAIK, no one else uses this method so there may be bugs that have
not yet been shaken out.

Best Regards,

Andy Bower
Dolphin Support
http://www.object-arts.com
---
Are you trying too hard?
http://www.object-arts.com/Relax.htm
---

***********************************

Save this to: Dynamic Component Demo.pac
and install using the Package Browser

***********************************


| package |

package := Package name: 'Dynamic Component Demo'.

package paxVersion: 0;

basicComment: 'Dolphin Smalltalk Dynamic Components Sample.

Copyright (c) Object Arts Ltd, 2002.

This sample shows how to dynamically add components to a presenter during
program execution. It also demonstrates how these may be arranged within a
scrolling view.

In general the best way to achieve the dynamic addition of presenters at
runtime is by first designing a "static" presenter and view that include a
placeholder under which the dynamic components will be added.
DynamicComponentDemo is such a presenter. It contains an instanceVariable
called dynamicContainer which will be setup by #createComponents as an empty
presenter to act as the placeholder. This dynamicContainer will be connected
to a container view (that has also been labelled "dynamicContainer") which
has be drawn as part of the overall view using the View Composer.

Scrolling is achieved by including a ScrollingDecorator in the view. The
container view for the dynamicContainer is placed inisde this. As items are
added to the dynamicContainer we have to ensure that its view is resized to
appropriately reflect the vertical extent required to show all the dynamic
components that have been added. This is done in
#resizeDynamicContainerForNewItem:.

We use a FlowLayout manager to automatically arrange the dynamic component
views in a vertical array. One might assume that a GridLayout would be more
appropriate but this will automatically resize the views that it manages to
fill the full area available. This is not what we wanted in this case. In
order to persuade the FlowLayout manager to arrange the dynamic views with
only one per row we set its #horizontalGap to be a large number in the View
Composer. A better solution would be to create a new style of layout manager
that performs the exact layout required.

****

You can run the demo by evaluating

shell := DynamicComponentDemo show.

As you press the "Add Dynamic Component" button, a new component (in this
case a Scribble) will be added to the window. If you add enough components
to fill the window then it will enable a vertical scroll bar to allow all of
them to be reached.

You can access the model information for each component by using
#dynamicModelAt:. Try adding 4 or 5 Scribbles and drawing in each one. Then
try this:

EtchASketch showOn: (shell dynamicModelAt: 1).

EtchASketch showOn: (shell dynamicModelAt: 2). "etc"

Now, when you draw in the first couple of scribbles you will see the ink
reflected in the etch-a-sketch windows and vice versa.

'.



package classNames

add: #DynamicComponentDemo;

yourself.

package binaryGlobalNames: (Set new

yourself).

package globalAliases: (Set new

yourself).

package allResourceNames: (Set new

add: #DynamicComponentDemo -> 'Default view';

yourself).

package setPrerequisites: (IdentitySet new

add: '..\..\..\Dolphin\Base\Dolphin';

add: '..\..\..\Dolphin\MVP\Base\Dolphin MVP Base';

add: '..\Scribble\Scribble';

yourself).

package!

"Class Definitions"!

Shell subclass: #DynamicComponentDemo

instanceVariableNames: 'dynamicContainer'

classVariableNames: ''

poolDictionaries: ''

classInstanceVariableNames: ''!

"Global Aliases"!



"Loose Methods"!

"End of package definition"!

"Source Globals"!

"Classes"!

DynamicComponentDemo guid: (GUID fromString:
'{C71C6720-7563-47E0-8A18-1C74D884D854}')!

DynamicComponentDemo comment: ''!

!DynamicComponentDemo categoriesForClass!MVP-Presenters! !

!DynamicComponentDemo methodsFor!

addDynamicComponent

"Dynamically add a new component (described by #dynamicComponentClass) to
the receiver"

| newItem |

newItem := self dynamicComponentClass createIn: dynamicContainer.

self resizeDynamicContainerForNewItem: newItem.

self scrollToLastItem!

createComponents

"Create the presenters contained by the receiver"

super createComponents.

dynamicContainer := self add: Presenter new name: 'dynamicContainer'.

!

dynamicComponentClass

^Scribble!

dynamicComponents

"Answer an <OrderedCollection> of the dynamic components in the receiver"

^dynamicContainer subPresenters!

dynamicModelAt: anInteger

"Answer the model data for the dynamic component at an anInteger index"

^(self dynamicComponents at: anInteger) model!

resizeDynamicContainerForNewItem: newItem

"Private- Resize the dynamic container to incorporate the recently added
newItem"

"Note we perform this resize in two steps, first vertically and then
horizontally, so that

we can validate the layout in between. This avoids the temporary appearence
of a

horizontal scrollbar when the vertical scrollbar first appears."

dynamicContainer view height: newItem view height * self dynamicComponents
size.

self view validateLayout.

dynamicContainer view width: newItem view width.

!

scrollerView

^dynamicContainer view parentView!

scrollToLastItem

self scrollerView verticalScrollTo: SmallInteger maximum! !

!DynamicComponentDemo categoriesFor: #addDynamicComponent!commands!public! !

!DynamicComponentDemo categoriesFor: #createComponents!initializing!public!
!

!DynamicComponentDemo categoriesFor:
#dynamicComponentClass!constants!public! !

!DynamicComponentDemo categoriesFor: #dynamicComponents!operations!public! !

!DynamicComponentDemo categoriesFor: #dynamicModelAt:!accessing!public! !

!DynamicComponentDemo categoriesFor:
#resizeDynamicContainerForNewItem:!operations!private! !

!DynamicComponentDemo categoriesFor: #scrollerView!accessing!private! !

!DynamicComponentDemo categoriesFor: #scrollToLastItem!operations!private! !

"Binary Globals"!

"Resources"!

(ResourceIdentifier class: DynamicComponentDemo name: 'Default view')
assign: (Object fromBinaryStoreBytes:

(ByteArray fromHexString:
'2153544220312046020C0001000000566965775265736F75726365000000000E01240053544
25265736F757263655354424279746541727261794163636573736F7250726F7879000000007
2000000BB070000215354422031204E080C000A0000005354425669657750726F78790000000
09A000000000000005200000010000000446F6C7068696E204D5650204261736552000000090
000005368656C6C56696577620000001B0000000000000000000000620000000200000001009
E0101000200A001000000000000000000000000000007020000000000000000000000000000A
001000006070C00426F726465724C61796F7574000000000100000001000000000000009A010
000000000009A00000000000000C0010000520000000A00000050757368427574746F6E62000
0001100000000000000A00100006200000002000000820000000400000000200144010000002
0020000000000000000000000000000070000000000000000000000000000002002000000000
00082000000080000009607FFFF000000004605120004000000436F6D6D616E6444657363726
97074696F6E00000000BA00000000000000520000001300000061646444796E616D6963436F6
D706F6E656E7452000000150000004164642044796E616D696320436F6D706F6E656E7401000
0000100000000000000000000000100000006010F004D65737361676553657175656E6365000
00000CA00000000000000D0000000620000000300000006030B004D65737361676553656E640
0000000BA00000000000000520000001000000063726561746541743A657874656E743A62000
0000200000006020500506F696E740000000001000000E50100007203000000000000E905000
03D000000200200002203000000000000BA00000000000000520000000A0000006973456E616
26C65643A620000000100000020000000200200002203000000000000BA00000000000000520
0000005000000746578743A620000000100000052000000150000004164642044796E616D696
320436F6D706F6E656E742002000006010F0057494E444F57504C4143454D454E54000000007
20000002C0000002C0000000000000001000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000
000F2000000F402000010010000CA00000000000000D00000006200000000000000720300000
0000000C1000000C1000000000000001300000000000000000000009A010000000000009A000
00000000000C001000052000000120000005363726F6C6C696E674465636F7261746F7262000
0001200000000000000A00100006200000002000000820000000400000000003044010002009
0040000000000000000000000000000070000000000000000000000000000009004000006001
8005363726F6C6C696E674465636F7261746F724C61796F757400000000EA000000000000000
001000062000000020000009A010000000000009A00000000000000C0010000520000000D000
000436F6E7461696E657256696577620000000F0000000000000090040000620000000200000
0820000000400000000000044010002003005000000000000000000000000000007000000000
0000000000000000000003005000006030A00466C6F774C61796F757400000000214E0000010
00000BA0000000000000052000000040000006C656674EA00000000000000000100007004000
000000000E202000000000000CA00000000000000D0000000620000000100000022030000000
0000040030000620000000200000072030000000000000100000001000000720300000000000
0E9050000E9020000300500003204000000000000720000002C0000002C00000000000000010
00000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000000000F402000074010000CA00000
000000000D000000070040000800400000000000013000000520000001000000064796E616D6
963436F6E7461696E65720000000072030000000000000100000001000000100000007203000
0000000001100000011000000E202000000000000CA00000000000000D000000062000000010
0000022030000000000004003000062000000020000007203000000000000010000000100000
07203000000000000E9050000E5010000900400003204000000000000720000002C0000002C0
000000000000001000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000000000F402000
0F2000000CA00000000000000D00000006200000001000000300500008004000000000000130
00000EA000000000000000001000062000000020000009004000052000000120000007363726
F6C6C696E67436F6E7461696E657200000000000000000000000000000000000000000100000
000000000000000000000000000000000010000000000000000000000E202000000000000CA0
0000000000000D00000006200000003000000220300000000000040030000620000000200000
072030000000000000B000000010000007203000000000000F905000065020000A0010000220
3000000000000F00300006200000001000000520000001600000044796E616D696320436F6D7
06F6E656E742044656D6FA00100002203000000000000BA00000000000000520000000800000
06D656E754261723A620000000100000000000000A00100003204000000000000720000002C0
000002C0000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF050000000000000
00103000032010000CA00000000000000D000000062000000020000009004000020020000800
400000000000015000000460504000300000049636F6E0000000000000000100000000E02110
053544253696E676C65746F6E50726F7879000000009A0000000000000052000000070000004
46F6C7068696E5200000018000000496D61676552656C617469766546696C654C6F6361746F7
2BA00000000000000520000000700000063757272656E74520000000D0000005368656C6C566
965772E69636F0E021F0053544245787465726E616C5265736F757263654C696272617279507
26F7879000000005200000010000000646F6C7068696E64723030352E646C6C00000000'))!


Reply | Threaded
Open this post in threaded view
|

Re: Better MVP Resources?

Andy Bower
Here is an attachment for that package.

Best Regards,

Andy Bower
Dolphin Support
http://www.object-arts.com
---
Are you trying too hard?
http://www.object-arts.com/Relax.htm
---






begin 666 Dynamic Component Demo.pac
M?"!P86-K86=E('P-"G!A8VMA9V4@.CT@4&%C:V%G92!N86UE.B G1'EN86UI
M8R!#;VUP;VYE;G0@1&5M;R<N#0IP86-K86=E('!A>%9E<G-I;VXZ(# [#0H)
M8F%S:6-#;VUM96YT.B G1&]L<&AI;B!3;6%L;'1A;&L@1'EN86UI8R!#;VUP
M;VYE;G1S(%-A;7!L92X@#0I#;W!Y<FEG:'0@*&,I($]B:F5C="!!<G1S($QT
M9"P@,C P,BX-"@T*5&AI<R!S86UP;&4@<VAO=W,@:&]W('1O(&1Y;F%M:6-A
M;&QY(&%D9"!C;VUP;VYE;G1S('1O(&$@<')E<V5N=&5R(&1U<FEN9R!P<F]G
M<F%M(&5X96-U=&EO;BX@270@86QS;R!D96UO;G-T<F%T97,@:&]W('1H97-E
M(&UA>2!B92!A<G)A;F=E9"!W:71H:6X@82!S8W)O;&QI;F<@=FEE=RX-"@T*
M26X@9V5N97)A;"!T:&4@8F5S="!W87D@=&\@86-H:65V92!T:&4@9'EN86UI
M8R!A9&1I=&EO;B!O9B!P<F5S96YT97)S(&%T(')U;G1I;64@:7,@8GD@9FER
M<W0@9&5S:6=N:6YG(&$@(G-T871I8R(@<')E<V5N=&5R(&%N9"!V:65W('1H
M870@:6YC;'5D92!A('!L86-E:&]L9&5R('5N9&5R('=H:6-H('1H92!D>6YA
M;6EC(&-O;7!O;F5N=',@=VEL;"!B92!A9&1E9"X@1'EN86UI8T-O;7!O;F5N
M=$1E;6\@:7,@<W5C:"!A('!R97-E;G1E<BX@270@8V]N=&%I;G,@86X@:6YS
M=&%N8V5687)I86)L92!C86QL960@9'EN86UI8T-O;G1A:6YE<B!W:&EC:"!W
M:6QL(&)E('-E='5P(&)Y("-C<F5A=&5#;VUP;VYE;G1S(&%S(&%N(&5M<'1Y
M('!R97-E;G1E<B!T;R!A8W0@87,@=&AE('!L86-E:&]L9&5R+B!4:&ES(&1Y
M;F%M:6-#;VYT86EN97(@=VEL;"!B92!C;VYN96-T960@=&\@82!C;VYT86EN
M97(@=FEE=R H=&AA="!H87,@86QS;R!B965N(&QA8F5L;&5D(")D>6YA;6EC
M0V]N=&%I;F5R(BD@=VAI8V@@:&%S(&)E(&1R87=N(&%S('!A<G0@;V8@=&AE
M(&]V97)A;&P@=FEE=R!U<VEN9R!T:&4@5FEE=R!#;VUP;W-E<BX-"@T*4V-R
M;VQL:6YG(&ES(&%C:&EE=F5D(&)Y(&EN8VQU9&EN9R!A(%-C<F]L;&EN9T1E
M8V]R871O<B!I;B!T:&4@=FEE=RX@5&AE(&-O;G1A:6YE<B!V:65W(&9O<B!T
M:&4@9'EN86UI8T-O;G1A:6YE<B!I<R!P;&%C960@:6YI<V1E('1H:7,N($%S
M(&ET96US(&%R92!A9&1E9"!T;R!T:&4@9'EN86UI8T-O;G1A:6YE<B!W92!H
M879E('1O(&5N<W5R92!T:&%T(&ET<R!V:65W(&ES(')E<VEZ960@=&\@87!P
M<F]P<FEA=&5L>2!R969L96-T('1H92!V97)T:6-A;"!E>'1E;G0@<F5Q=6ER
M960@=&\@<VAO=R!A;&P@=&AE(&1Y;F%M:6,@8V]M<&]N96YT<R!T:&%T(&AA
M=F4@8F5E;B!A9&1E9"X@5&AI<R!I<R!D;VYE(&EN("-R97-I>F5$>6YA;6EC
M0V]N=&%I;F5R1F]R3F5W271E;3HN#0H-"E=E('5S92!A($9L;W=,87EO=70@
M;6%N86=E<B!T;R!A=71O;6%T:6-A;&QY(&%R<F%N9V4@=&AE(&1Y;F%M:6,@
M8V]M<&]N96YT('9I97=S(&EN(&$@=F5R=&EC86P@87)R87DN($]N92!M:6=H
M="!A<W-U;64@=&AA="!A($=R:61,87EO=70@=V]U;&0@8F4@;6]R92!A<'!R
M;W!R:6%T92!B=70@=&AI<R!W:6QL(&%U=&]M871I8V%L;'D@<F5S:7IE('1H
M92!V:65W<R!T:&%T(&ET(&UA;F%G97,@=&\@9FEL;"!T:&4@9G5L;"!A<F5A
M(&%V86EL86)L92X@5&AI<R!I<R!N;W0@=VAA="!W92!W86YT960@:6X@=&AI
M<R!C87-E+B!);B!O<F1E<B!T;R!P97)S=6%D92!T:&4@1FQO=TQA>6]U="!M
M86YA9V5R('1O(&%R<F%N9V4@=&AE(&1Y;F%M:6,@=FEE=W,@=VET:"!O;FQY
M(&]N92!P97(@<F]W('=E('-E="!I=',@(VAO<FEZ;VYT86Q'87 @=&\@8F4@
M82!L87)G92!N=6UB97(@:6X@=&AE(%9I97<@0V]M<&]S97(N($$@8F5T=&5R
M('-O;'5T:6]N('=O=6QD(&)E('1O(&-R96%T92!A(&YE=R!S='EL92!O9B!L
M87EO=70@;6%N86=E<B!T:&%T('!E<F9O<FUS('1H92!E>&%C="!L87EO=70@
M<F5Q=6ER960N( T*#0HJ*BHJ#0H-"EEO=2!C86X@<G5N('1H92!D96UO(&)Y
M(&5V86QU871I;F<-"@T*<VAE;&P@.CT@1'EN86UI8T-O;7!O;F5N=$1E;6\@
M<VAO=RX-"@T*07,@>6]U('!R97-S('1H92 B061D($1Y;F%M:6,@0V]M<&]N
M96YT(B!B=71T;VXL(&$@;F5W(&-O;7!O;F5N=" H:6X@=&AI<R!C87-E(&$@
M4V-R:6)B;&4I('=I;&P@8F4@861D960@=&\@=&AE('=I;F1O=RX@268@>6]U
M(&%D9"!E;F]U9V@@8V]M<&]N96YT<R!T;R!F:6QL('1H92!W:6YD;W<@=&AE
M;B!I="!W:6QL(&5N86)L92!A('9E<G1I8V%L('-C<F]L;"!B87(@=&\@86QL
M;W<@86QL(&]F('1H96T@=&\@8F4@<F5A8VAE9"X@#0H-"EEO=2!C86X@86-C
M97-S('1H92!M;V1E;"!I;F9O<FUA=&EO;B!F;W(@96%C:"!C;VUP;VYE;G0@
M8GD@=7-I;F<@(V1Y;F%M:6--;V1E;$%T.BX@5')Y(&%D9&EN9R T(&]R(#4@
M4V-R:6)B;&5S(&%N9"!D<F%W:6YG(&EN(&5A8V@@;VYE+B!4:&5N('1R>2!T
M:&ES.@T*#0I%=&-H05-K971C:"!S:&]W3VXZ("AS:&5L;"!D>6YA;6EC36]D
M96Q!=#H@,2DN#0I%=&-H05-K971C:"!S:&]W3VXZ("AS:&5L;"!D>6YA;6EC
M36]D96Q!=#H@,BDN(")E=&,B#0H-"DYO=RP@=VAE;B!Y;W4@9')A=R!I;B!T
M:&4@9FER<W0@8V]U<&QE(&]F('-C<FEB8FQE<R!Y;W4@=VEL;"!S964@=&AE
M(&EN:R!R969L96-T960@:6X@=&AE(&5T8V@M82US:V5T8V@@=VEN9&]W<R!A
M;F0@=FEC92!V97)S82X-"B<N#0H-"@T*<&%C:V%G92!C;&%S<TYA;65S#0H)
M861D.B C1'EN86UI8T-O;7!O;F5N=$1E;6\[#0H)>6]U<G-E;&8N#0H-"G!A
M8VMA9V4@8FEN87)Y1VQO8F%L3F%M97,Z("A3970@;F5W#0H)>6]U<G-E;&8I
M+@T*#0IP86-K86=E(&=L;V)A;$%L:6%S97,Z("A3970@;F5W#0H)>6]U<G-E
M;&8I+@T*#0IP86-K86=E(&%L;%)E<V]U<F-E3F%M97,Z("A3970@;F5W#0H)
M861D.B C1'EN86UI8T-O;7!O;F5N=$1E;6\@+3X@)T1E9F%U;'0@=FEE=R<[
M#0H)>6]U<G-E;&8I+@T*#0IP86-K86=E('-E=%!R97)E<75I<VET97,Z("A)
M9&5N=&ET>5-E="!N97<-"@EA9&0Z("<N+EPN+EPN+EQ$;VQP:&EN7$)A<V5<
M1&]L<&AI;B<[#0H)861D.B G+BY<+BY<+BY<1&]L<&AI;EQ-5E!<0F%S95Q$
M;VQP:&EN($U64"!"87-E)SL-"@EA9&0Z("<N+EQ38W)I8F)L95Q38W)I8F)L
M92<[#0H)>6]U<G-E;&8I+@T*#0IP86-K86=E(0T*#0HB0VQA<W,@1&5F:6YI
M=&EO;G,B(0T*#0I3:&5L;"!S=6)C;&%S<SH@(T1Y;F%M:6-#;VUP;VYE;G1$
M96UO#0H):6YS=&%N8V5687)I86)L94YA;65S.B G9'EN86UI8T-O;G1A:6YE
M<B<-"@EC;&%S<U9A<FEA8FQE3F%M97,Z("<G#0H)<&]O;$1I8W1I;VYA<FEE
M<SH@)R<-"@EC;&%S<TEN<W1A;F-E5F%R:6%B;&5.86UE<SH@)R<A#0H-"B)'
M;&]B86P@06QI87-E<R(A#0H-"@T*(DQO;W-E($UE=&AO9',B(0T*#0HB16YD
M(&]F('!A8VMA9V4@9&5F:6YI=&EO;B(A#0H-"B)3;W5R8V4@1VQO8F%L<R(A
M#0H-"B)#;&%S<V5S(B$-"@T*1'EN86UI8T-O;7!O;F5N=$1E;6\@9W5I9#H@
M*$=5240@9G)O;5-T<FEN9SH@)WM#-S%#-C<R,"TW-38S+30W13 M.$$Q."TQ
M0S<T1#@X-$0X-31])RDA#0I$>6YA;6EC0V]M<&]N96YT1&5M;R!C;VUM96YT
M.B G)R$-"B%$>6YA;6EC0V]M<&]N96YT1&5M;R!C871E9V]R:65S1F]R0VQA
M<W,A3590+5!R97-E;G1E<G,A("$-"B%$>6YA;6EC0V]M<&]N96YT1&5M;R!M
M971H;V1S1F]R(0T*#0IA9&1$>6YA;6EC0V]M<&]N96YT#0H)(D1Y;F%M:6-A
M;&QY(&%D9"!A(&YE=R!C;VUP;VYE;G0@*&1E<V-R:6)E9"!B>2 C9'EN86UI
M8T-O;7!O;F5N=$-L87-S*2!T;R!T:&4@<F5C96EV97(B#0H-"@E\(&YE=TET
M96T@? T*"6YE=TET96T@.CT@<V5L9B!D>6YA;6EC0V]M<&]N96YT0VQA<W,@
M8W)E871E26XZ(&1Y;F%M:6-#;VYT86EN97(N#0H)<V5L9B!R97-I>F5$>6YA
M;6EC0V]N=&%I;F5R1F]R3F5W271E;3H@;F5W271E;2X-"@ES96QF('-C<F]L
M;%1O3&%S=$ET96TA#0H-"F-R96%T94-O;7!O;F5N=',-"@DB0W)E871E('1H
M92!P<F5S96YT97)S(&-O;G1A:6YE9"!B>2!T:&4@<F5C96EV97(B#0H-"@ES
M=7!E<B!C<F5A=&5#;VUP;VYE;G1S+@T*"61Y;F%M:6-#;VYT86EN97(@.CT@
M<V5L9B!A9&0Z(%!R97-E;G1E<B!N97<@;F%M93H@)V1Y;F%M:6-#;VYT86EN
M97(G+@T*(0T*#0ID>6YA;6EC0V]M<&]N96YT0VQA<W,-"@E>4V-R:6)B;&4A
M#0H-"F1Y;F%M:6-#;VUP;VYE;G1S#0H)(D%N<W=E<B!A;B \3W)D97)E9$-O
M;&QE8W1I;VX^(&]F('1H92!D>6YA;6EC(&-O;7!O;F5N=',@:6X@=&AE(')E
M8V5I=F5R(@T*#0H)7F1Y;F%M:6-#;VYT86EN97(@<W5B4')E<V5N=&5R<R$-
M"@T*9'EN86UI8TUO9&5L070Z(&%N26YT96=E<B -"@DB06YS=V5R('1H92!M
M;V1E;"!D871A(&9O<B!T:&4@9'EN86UI8R!C;VUP;VYE;G0@870@86X@86Y)
M;G1E9V5R(&EN9&5X(@T*#0H)7BAS96QF(&1Y;F%M:6-#;VUP;VYE;G1S(&%T
M.B!A;DEN=&5G97(I(&UO9&5L(0T*#0IR97-I>F5$>6YA;6EC0V]N=&%I;F5R
M1F]R3F5W271E;3H@;F5W271E;2 -"@DB4')I=F%T92T@4F5S:7IE('1H92!D
M>6YA;6EC(&-O;G1A:6YE<B!T;R!I;F-O<G!O<F%T92!T:&4@<F5C96YT;'D@
M861D960@;F5W271E;2(-"@T*"2).;W1E('=E('!E<F9O<FT@=&AI<R!R97-I
M>F4@:6X@='=O('-T97!S+"!F:7)S="!V97)T:6-A;&QY(&%N9"!T:&5N(&AO
M<FEZ;VYT86QL>2P@<V\@=&AA= T*"7=E(&-A;B!V86QI9&%T92!T:&4@;&%Y
M;W5T(&EN(&)E='=E96XN(%1H:7,@879O:61S('1H92!T96UP;W)A<GD@87!P
M96%R96YC92!O9B!A( T*"6AO<FEZ;VYT86P@<V-R;VQL8F%R('=H96X@=&AE
M('9E<G1I8V%L('-C<F]L;&)A<B!F:7)S="!A<'!E87)S+B(-"@T*"61Y;F%M
M:6-#;VYT86EN97(@=FEE=R!H96EG:'0Z(&YE=TET96T@=FEE=R!H96EG:'0@
M*B!S96QF(&1Y;F%M:6-#;VUP;VYE;G1S('-I>F4N#0H)<V5L9B!V:65W('9A
M;&ED871E3&%Y;W5T+@T*"61Y;F%M:6-#;VYT86EN97(@=FEE=R!W:61T:#H@
M;F5W271E;2!V:65W('=I9'1H+@T*(0T*#0IS8W)O;&QE<E9I97<-"@E>9'EN
M86UI8T-O;G1A:6YE<B!V:65W('!A<F5N=%9I97<A#0H-"G-C<F]L;%1O3&%S
M=$ET96T-"@ES96QF('-C<F]L;&5R5FEE=R!V97)T:6-A;%-C<F]L;%1O.B!3
M;6%L;$EN=&5G97(@;6%X:6UU;2$@(0T*(41Y;F%M:6-#;VUP;VYE;G1$96UO
M(&-A=&5G;W)I97-&;W(Z("-A9&1$>6YA;6EC0V]M<&]N96YT(6-O;6UA;F1S
M(7!U8FQI8R$@(0T*(41Y;F%M:6-#;VUP;VYE;G1$96UO(&-A=&5G;W)I97-&
M;W(Z("-C<F5A=&5#;VUP;VYE;G1S(6EN:71I86QI>FEN9R%P=6)L:6,A("$-
M"B%$>6YA;6EC0V]M<&]N96YT1&5M;R!C871E9V]R:65S1F]R.B C9'EN86UI
M8T-O;7!O;F5N=$-L87-S(6-O;G-T86YT<R%P=6)L:6,A("$-"B%$>6YA;6EC
M0V]M<&]N96YT1&5M;R!C871E9V]R:65S1F]R.B C9'EN86UI8T-O;7!O;F5N
M=',A;W!E<F%T:6]N<R%P=6)L:6,A("$-"B%$>6YA;6EC0V]M<&]N96YT1&5M
M;R!C871E9V]R:65S1F]R.B C9'EN86UI8TUO9&5L070Z(6%C8V5S<VEN9R%P
M=6)L:6,A("$-"B%$>6YA;6EC0V]M<&]N96YT1&5M;R!C871E9V]R:65S1F]R
M.B C<F5S:7IE1'EN86UI8T-O;G1A:6YE<D9O<DYE=TET96TZ(6]P97)A=&EO
M;G,A<')I=F%T92$@(0T*(41Y;F%M:6-#;VUP;VYE;G1$96UO(&-A=&5G;W)I
M97-&;W(Z("-S8W)O;&QE<E9I97<A86-C97-S:6YG(7!R:79A=&4A("$-"B%$
M>6YA;6EC0V]M<&]N96YT1&5M;R!C871E9V]R:65S1F]R.B C<V-R;VQL5&],
M87-T271E;2%O<&5R871I;VYS(7!R:79A=&4A("$-"@T*(D)I;F%R>2!';&]B
M86QS(B$-"@T*(E)E<V]U<F-E<R(A#0H-"BA297-O=7)C94ED96YT:69I97(@
M8VQA<W,Z($1Y;F%M:6-#;VUP;VYE;G1$96UO(&YA;64Z("=$969A=6QT('9I
M97<G*2!A<W-I9VXZ("A/8FIE8W0@9G)O;4)I;F%R>5-T;W)E0GET97,Z#0HH
M0GET94%R<F%Y(&9R;VU(97A3=')I;F<Z("<R,34S-30T,C(P,S$R,#0V,#(P
M0S P,#$P,# P,# U-C8Y-C4W-S4R-C4W,S9&-S4W,C8S-C4P,# P,# P,#!%
M,#$R-# P-3,U-#0R-3(V-3<S-D8W-3<R-C,V-34S-30T,C0R-SDW-#8U-#$W
M,C<R-C$W.30Q-C,V,S8U-S,W,S9&-S(U,#<R-D8W.#<Y,# P,# P,# W,C P
M,# P,$)",#<P,# P,C$U,S4T-#(R,#,Q,C T13 X,$,P,#!!,# P,# P-3,U
M-#0R-38V.38U-S<U,#<R-D8W.#<Y,# P,# P,# Y03 P,# P,# P,# P,# P
M-3(P,# P,# Q,# P,# P,#0T-D8V0S<P-C@V.39%,C T1#4V-3 R,#0R-C$W
M,S8U-3(P,# P,# P.3 P,# P,#4S-C@V-39#-D,U-C8Y-C4W-S8R,# P,# P
M,4(P,# P,# P,# P,# P,# P,# P,# P-C(P,# P,# P,C P,# P,# Q,# Y
M13 Q,#$P,# R,#!!,# Q,# P,# P,# P,# P,# P,# P,# P,# P,# P,# W
M,#(P,# P,# P,# P,# P,# P,# P,# P,# P,# P03 P,3 P,# P-C W,$,P
M,#0R-D8W,C8T-C4W,C1#-C$W.39&-S4W-# P,# P,# P,#$P,# P,# P,3 P
M,# P,# P,# P,# P.4$P,3 P,# P,# P,# P,#E!,# P,# P,# P,# P,#!#
M,# Q,# P,#4R,# P,# P,$$P,# P,# U,#<U-S,V.#0R-S4W-#<T-D8V138R
M,# P,# P,3$P,# P,# P,# P,# P,$$P,#$P,# P-C(P,# P,# P,C P,# P
M,#@R,# P,# P,#0P,# P,# P,#(P,#$T-# Q,# P,# P,C P,C P,# P,# P
M,# P,# P,# P,# P,# P,# P,# P-S P,# P,# P,# P,# P,# P,# P,# P
M,# P,# P,#(P,#(P,# P,# P,# P,# X,C P,# P,# X,# P,# P.38P-T9&
M1D8P,# P,# P,#0V,#4Q,C P,#0P,# P,# T,S9&-D0V1#8Q-D4V-#0T-C4W
M,S8S-S(V.3<P-S0V.39&-D4P,# P,# P,$)!,# P,# P,# P,# P,# U,C P
M,# P,#$S,# P,# P-C$V-#8T-#0W.39%-C$V1#8Y-C,T,S9&-D0W,#9&-D4V
M-39%-S0U,C P,# P,#$U,# P,# P-#$V-#8T,C T-#<Y-D4V,39$-CDV,S(P
M-#,V1C9$-S V1C9%-C4V13<T,#$P,# P,# P,3 P,# P,# P,# P,# P,# P
M,# P,# P,3 P,# P,# V,#$P1C P-$0V-3<S-S,V,38W-C4U,S8U-S$W-38U
M-D4V,S8U,# P,# P,#!#03 P,# P,# P,# P,# P1# P,# P,# V,C P,# P
M,# S,# P,# P,#8P,S!",# T1#8U-S,W,S8Q-C<V-34S-C4V138T,# P,# P
M,#!"03 P,# P,# P,# P,# P-3(P,# P,# Q,# P,# P,#8S-S(V-38Q-S0V
M-30Q-S0S038U-S@W-#8U-D4W-#-!-C(P,# P,# P,C P,# P,# V,#(P-3 P
M-3 V1C8Y-D4W-# P,# P,# P,#$P,# P,#!%-3 Q,# P,#<R,#,P,# P,# P
M,# P,#!%.3 U,# P,#-$,# P,# P,C P,C P,# R,C S,# P,# P,# P,# P
M0D$P,# P,# P,# P,# P,#4R,# P,# P,$$P,# P,# V.3<S-#4V138Q-C(V
M0S8U-C0S038R,# P,# P,#$P,# P,# R,# P,# P,#(P,#(P,# P,C(P,S P
M,# P,# P,# P,$)!,# P,# P,# P,# P,# U,C P,# P,# U,# P,# P-S0V
M-3<X-S0S038R,# P,# P,#$P,# P,# U,C P,# P,#$U,# P,# P-#$V-#8T
M,C T-#<Y-D4V,39$-CDV,S(P-#,V1C9$-S V1C9%-C4V13<T,C P,C P,# P
M-C Q,$8P,#4W-#DT130T-$8U-S4P-$,T,30S-#4T1#0U-$4U-# P,# P,# P
M-S(P,# P,# R0S P,# P,#)#,# P,# P,# P,# P,# P,3 P,# P,$9&1D9&
M1D9&1D9&1D9&1D9&1D9&1D9&1D9&1D9&1D9&,# P,# P,#!&,C P,# P,$8T
M,#(P,# P,3 P,3 P,#!#03 P,# P,# P,# P,# P1# P,# P,# V,C P,# P
M,# P,# P,# P-S(P,S P,# P,# P,# P,$,Q,# P,# P0S$P,# P,# P,# P
M,# P,#$S,# P,# P,# P,# P,# P,# P,# P,#E!,#$P,# P,# P,# P,# Y
M03 P,# P,# P,# P,# P0S P,3 P,# U,C P,# P,#$R,# P,# P-3,V,S<R
M-D8V0S9#-CDV138W-#0V-38S-D8W,C8Q-S0V1C<R-C(P,# P,# Q,C P,# P
M,# P,# P,# P03 P,3 P,# V,C P,# P,# R,# P,# P.#(P,# P,# P-# P
M,# P,# P,# S,#0T,#$P,# R,# Y,# T,# P,# P,# P,# P,# P,# P,# P
M,# P,# P,# W,# P,# P,# P,# P,# P,# P,# P,# P,# P,# P.3 P-# P
M,# P-C P,3@P,#4S-C,W,C9&-D,V0S8Y-D4V-S0T-C4V,S9&-S(V,3<T-D8W
M,C1#-C$W.39&-S4W-# P,# P,# P14$P,# P,# P,# P,# P,# P,#$P,# P
M-C(P,# P,# P,C P,# P,#E!,#$P,# P,# P,# P,# Y03 P,# P,# P,# P
M,# P0S P,3 P,# U,C P,# P,#!$,# P,# P-#,V1C9%-S0V,38Y-D4V-3<R
M-38V.38U-S<V,C P,# P,#!&,# P,# P,# P,# P,# Y,# T,# P,#8R,# P
M,# P,#(P,# P,# X,C P,# P,# T,# P,# P,# P,# P-#0P,3 P,#(P,#,P
M,#4P,# P,# P,# P,# P,# P,# P,# P,# P,# P,#<P,# P,# P,# P,# P
M,# P,# P,# P,# P,# P,# S,# U,# P,# V,#,P03 P-#8V0S9&-S<T0S8Q
M-SDV1C<U-S0P,# P,# P,#(Q-$4P,# P,#$P,# P,#!"03 P,# P,# P,# P
M,# P-3(P,# P,# P-# P,# P,#9#-C4V-C<T14$P,# P,# P,# P,# P,# P
M,#$P,# P-S P-# P,# P,# P,# P,$4R,#(P,# P,# P,# P,#!#03 P,# P
M,# P,# P,# P1# P,# P,# V,C P,# P,# Q,# P,# P,C(P,S P,# P,# P
M,# P,#0P,#,P,# P-C(P,# P,# P,C P,# P,#<R,#,P,# P,# P,# P,# P
M,3 P,# P,# Q,# P,# P-S(P,S P,# P,# P,# P,$4Y,#4P,# P13DP,C P
M,# S,# U,# P,#,R,#0P,# P,# P,# P,# W,C P,# P,#)#,# P,# P,D,P
M,# P,# P,# P,# P,# Q,# P,# P1D9&1D9&1D9&1D9&1D9&1D9&1D9&1D9&
M1D9&1D9&1D8P,# P,# P,# P,# P,# P1C0P,C P,# W-# Q,# P,$-!,# P
M,# P,# P,# P,#!$,# P,# P,#<P,#0P,# P.# P-# P,# P,# P,# P,#$S
M,# P,# P-3(P,# P,# Q,# P,# P,#8T-SDV138Q-D0V.38S-#,V1C9%-S0V
M,38Y-D4V-3<R,# P,# P,# W,C S,# P,# P,# P,# P,#$P,# P,# P,3 P
M,# P,#$P,# P,# P-S(P,S P,# P,# P,# P,#$Q,# P,# P,3$P,# P,#!%
M,C R,# P,# P,# P,# P0T$P,# P,# P,# P,# P,$0P,# P,# P-C(P,# P
M,# P,3 P,# P,#(R,#,P,# P,# P,# P,# T,# S,# P,#8R,# P,# P,#(P
M,# P,# W,C S,# P,# P,# P,# P,#$P,# P,# P,3 P,# P,#<R,#,P,# P
M,# P,# P,#!%.3 U,# P,$4U,#$P,# P.3 P-# P,# S,C T,# P,# P,# P
M,# P-S(P,# P,# R0S P,# P,#)#,# P,# P,# P,# P,# P,3 P,# P,$9&
M1D9&1D9&1D9&1D9&1D9&1D9&1D9&1D9&1D9&1D9&,# P,# P,# P,# P,# P
M,$8T,#(P,# P1C(P,# P,#!#03 P,# P,# P,# P,# P1# P,# P,# V,C P
M,# P,# Q,# P,# P,S P-3 P,# X,# T,# P,# P,# P,# P,3,P,# P,#!%
M03 P,# P,# P,# P,# P,# P,3 P,# V,C P,# P,# R,# P,# P.3 P-# P
M,# U,C P,# P,#$R,# P,# P-S,V,S<R-D8V0S9#-CDV138W-#,V1C9%-S0V
M,38Y-D4V-3<R,# P,# P,# P,# P,# P,# P,# P,# P,# P,# P,# P,# P
M,# P,# Q,# P,# P,# P,# P,# P,# P,# P,# P,# P,# P,# P,# P,# P
M,3 P,# P,# P,# P,# P,# P,# P,#!%,C R,# P,# P,# P,# P0T$P,# P
M,# P,# P,# P,$0P,# P,# P-C(P,# P,# P,S P,# P,#(R,#,P,# P,# P
M,# P,# T,# S,# P,#8R,# P,# P,#(P,# P,# W,C S,# P,# P,# P,# P
M,$(P,# P,# P,3 P,# P,#<R,#,P,# P,# P,# P,#!&.3 U,# P,#8U,#(P
M,# P03 P,3 P,# R,C S,# P,# P,# P,# P1C P,S P,# V,C P,# P,# Q
M,# P,# P-3(P,# P,# Q-C P,# P,#0T-SDV138Q-D0V.38S,C T,S9&-D0W
M,#9&-D4V-39%-S0R,#0T-C4V1#9&03 P,3 P,# R,C S,# P,# P,# P,# P
M0D$P,# P,# P,# P,# P,#4R,# P,# P,#@P,# P,# V1#8U-D4W-30R-C$W
M,C-!-C(P,# P,# P,3 P,# P,# P,# P,# P03 P,3 P,# S,C T,# P,# P
M,# P,# P-S(P,# P,# R0S P,# P,#)#,# P,# P,# P,# P,# P,# P,# P
M,$9&1D9&1D9&1D9&1D9&1D9&1D9&1D9&1D9&1D9&1D9&,#4P,# P,# P,# P
M,# P,# Q,#,P,# P,S(P,3 P,#!#03 P,# P,# P,# P,# P1# P,# P,# V
M,C P,# P,# R,# P,# P.3 P-# P,# R,# R,# P,#@P,#0P,# P,# P,# P
M,# Q-3 P,# P,#0V,#4P-# P,#,P,# P,# T.38S-D8V13 P,# P,# P,# P
M,# P,# Q,# P,# P,#!%,#(Q,3 P-3,U-#0R-3,V.39%-C<V0S8U-S0V1C9%
M-3 W,C9&-S@W.3 P,# P,# P.4$P,# P,# P,# P,# P,#4R,# P,# P,#<P
M,# P,# T-#9&-D,W,#8X-CDV134R,# P,# P,3@P,# P,# T.39$-C$V-S8U
M-3(V-39#-C$W-#8Y-S8V-30V-CDV0S8U-$,V1C8S-C$W-#9&-S)"03 P,# P
M,# P,# P,# P-3(P,# P,# P-S P,# P,#8S-S4W,C<R-C4V13<T-3(P,# P
M,# P1# P,# P,#4S-C@V-39#-D,U-C8Y-C4W-S)%-CDV,S9&,$4P,C%&,# U
M,S4T-#(T-3<X-S0V-3<R-D4V,39#-3(V-3<S-D8W-3<R-C,V-31#-CDV,C<R
M-C$W,C<Y-3 W,C9&-S@W.3 P,# P,# P-3(P,# P,# Q,# P,# P,#8T-D8V
K0S<P-C@V.39%-C0W,C,P,S S-3)%-C0V0S9#,# P,# P,# G*2DA#0H-"@``
`
end


Reply | Threaded
Open this post in threaded view
|

Re: Better MVP Resources?

Andy Bower
In reply to this post by Me
Chris,

I noticed that this reply did not get transfered to some newsgroups that
don't accept "binary" in messages. Hence I have snipped the "binary" (ASCII
hex) from this message by removing the package source. If you want the
package source you should be able to find it on the news.totallyobjects.com
server (amongst others).

> I know how to use google. I've seen every MVP tutorial that seems to
> be out there. Is there anything that actual goes through what each
> method does and the order these methods get called? I understand the
> pattern, I'm just lost when it comes to Dolphin's implementation. Some
> sort of interaction diagram would go a long way to clearing things up.
>
> I would also very much like to find a decent example of how to create
> a view (and tie it into the presenter) without using the view
> composer. I HATE visual builders and I wish that IDEs would stop
> shoving them down my throught. Specifically, I want to know how to tie
> a view to a presenter when the view doesn't have a resource name.
> Everything seems to revolve around the resource manager.
>
> Basically, I have a component and I want to represent a scrollable
> list of those components. I could have done this in Java in about a
> half an hour. I've been spending days trying to figure out how to do
> this in Dolphin with MVP and there doesn't seem to be a simple way.

I think you have two issues here that are exacerbating each other. You have
a problem that you are trying to solve (to dynamically create a scrollable
list of components) and, because you couldn't find an easy way to do this
within the MVP framework you've started to consider non-MVP and non-View
Composer methods of doing this.

First of all let me say that you can do what you want any of these ways;
using MVP and the VC, using MVP without the VC or without using MVP at all.
The simplest way by far(because that is the way that Dolphin is intended to
be used) is to use MVP and the View Composer. I can well accept that you
might find this hard to figure out without having "cut your teeth" on some
simpler MVP projects first but I'm attaching a sample file that took me 20
minutes to knock up (well 20 mins to do the code and another 15 mins to
write the package comment). I'd be interested to know if you'd have been
able knock this up in Java in 30 minutes if you had no experience using the
GUI framework. Somehow, I doubt it.

Load up the package at the end of this message and follow the instructions
in the package comment. You may find that transferring the package like this
will lose the method and comment formatting. Unfortunately, the news server
I'm posting this to does not accept attachments. I'll post an attachment
version in a separate message via another news server.

> What do I have to know if I don't use MVP? The more I look into it,
> the less I want to use it. It's just too much overkill. I went with
> Smalltalk so I can crank code out quickly. MVP is making development
> slower than C++. It may be powerful, but I've got along quite well
> without that kind of power in the past. Will I not be able to use
> layout managers if I bypass MVP? Does anyone know of a good non-MVP
> example that shows how to create a simple window with a few controls,
> and the ability to handle resize events (assuming I can't use layout
> managers)? You know, something simple I can build off of to create
> anything, including a more productive framework. Just tell me how to
> do the Win SDK basics and I'll handle the rest. I would kill for the
> simplicity of Java GUI building in Smalltalk.

If you want to dispenser with MVP and the View Composer altogether then you
can do so. As you rightly surmise this can be done by just sticking with
classes in the View hierarchy and by writing code to assemble the views
dynamically. I've just read Ian's reply and this would seem to illustrate
how to do this. Ian suggests that what he is doing is still MVP but I would
beg to differ. Apart from the fact he uses a Shell presenter as the top
level container nothing else involves presenters. If you use a ShellView
rather than a Shell then I would say that Ian's example is a pretty good
illustration of how to do it the "non-MVP" way.

Note: strictly speaking Dolphin Views still follow MVP. They have a model
and they are, in fact, their own presenters. However, you can forget all
this and program them as if they are just widgets and just use their
accessor methods to get and set data. Having said this, you may find come
across some odd "gotchas" with this way of working. This will simply be
because, AFAIK, no one else uses this method so there may be bugs that have
not yet been shaken out.

Best Regards,

Andy Bower
Dolphin Support
http://www.object-arts.com
---
Are you trying too hard?
http://www.object-arts.com/Relax.htm
---


Reply | Threaded
Open this post in threaded view
|

Re: Better MVP Resources?

Bill Schwab
Hello all,

On a _really_ quick scan of this thread, the component list is sounding a
lot like a job for my PaneHolders package.  As for avoiding the VC, take a
look at ViewGenerator and friends.  For the latter, there is probably a
substantial revision yet to be posted on my web site.  The old version
should give you a feel for it though, and I can prepare an update and get it
posted next week.

Have a good one,

Bill

--
Wilhelm K. Schwab, Ph.D.
[hidden email]


Reply | Threaded
Open this post in threaded view
|

Re: Better MVP Resources?

Syver Enstad-3
"Bill Schwab" <[hidden email]> writes:

> Hello all,
>
> On a _really_ quick scan of this thread, the component list is
> sounding a
>
> lot like a job for my PaneHolders package.  As for avoiding the VC,
> take a
>
> look at ViewGenerator and friends.  For the latter, there is probably
> a
>
> substantial revision yet to be posted on my web site.  The old version
>
> should give you a feel for it though, and I can prepare an update and
> get it
>
> posted next week.
>
> Have a good one,
>
> Bill

I don't know if it is relevant but Tkinter with Python (Tcl/Tk), has a
really nice layoutmanager for coding up quick and dirty GUI's. It is
called the packer, and often does what you want without having to
postition anything.
 

--

Vennlig hilsen

Syver Enstad


Me
Reply | Threaded
Open this post in threaded view
|

Re: Better MVP Resources?

Me
In reply to this post by Ian Bartholomew-18
Thanks, that cleared things up a bit. I still think there should be a
practical reference somewhere. I suppose I should just take up the
time to map out my own call flow diagram between the model, view, and
presenter. I think I just need to know what gets called when and when
events are triggered. Still, for $350, it might be nice if something
more basic than a tutorial was provided.

I do really like Dolphin though, and I plan to do a lot of development
in it. Still, I hope that newer versions focus on the editor a bit
more. It's such an important part of any IDE. A simple, yet great
improvement would be to update the context hilighting after ever
character typed. I was looking into seeing if I could do it in my
image. Another useful improvment would be the option to save the
entire package when I save any change to it. I've had Dolphin crash on
me a number of times (in response to my improper code) and then I lose
all of my changes. So now, I'm in the habit of going to the package
browser, each time, to save things before running anything with loops
in it. Kind of a pain. But again, I imagine I can hack the image to
get the behavior I want. It's good to be doing Smalltalk again.

--chris


On Thu, 28 Nov 2002 12:25:43 -0000, "Ian Bartholomew" <[hidden email]>
wrote:

>Chris,
>
>I can't really address your main points as I am quite happy using the
>ViewComposer (I haven't therefore had to, or wanted to, build views in code
>since Dolphin 1) and am also reasonably happy about using MVP.  NB I'm *not*
>saying you should feel the same - just that I haven't got the experience to
>answer your questions.
>
>> Basically, I have a component and I want to represent a scrollable
>> list of those components. I could have done this in Java in about a
>> half an hour. I've been spending days trying to figure out how to do
>> this in Dolphin with MVP and there doesn't seem to be a simple way.
>
>Here is a bit of workspace code that, I think, achieves what you want?
>
>"show a shell"
>s := Shell show.
>
>"the top shell has a BorderLayout..."
>s view layoutManager: BorderLayout new.
>
>"...so we can centre the ScrollingDecorator we are about to add"
>s view addSubView: (sc := ScrollingDecorator new).
>sc arrangement: #center.
>
>"now add a Container View to the ScrollingDecorator. This view, and anything
>we put in it, will be scrolled as one"
>sc addSubView: (cv := ContainerView new).
>cv usePreferredExtent: true.
>
>"add a couple of widgets to the ContainerView"
>cv addSubView: (cb1 := CheckBox new).
>cb1 position: 10 @ 10.
>cv addSubView: (cb2 := CheckBox new).
>cb2 position: 10 @ 50.
>
>"now we change the preferred extent of the container and tell the
>ScrollingDecorator to allow for the change. Scroll bars should appear and
>you should be able to scroll the Container and CheckBoxes around"
>
>cv preferredExtent: 1000@1000.
>sc layout
>
>The only thing you need do, from this point on, is to change the
>ContainerViews preferredExtent when you add/remove components.  Everything
>else is automatically taken care of.
>
>The process of creating the structure is exactly the same when using the
>ViewComposer.  As long as you give the ContainerView a name, so that you can
>always locate it using
>
>(aTopViewOfSomeSort) viewName: 'theContainerViewName'
>
>then the only code you will need is the last bit above which tells the
>ContainerView it's new extent.
>
>You can also use a LayoutManager for the ContainerView if it's easier. As
>in -
>
>s := Shell show.
>s view layoutManager: BorderLayout new.
>s view addSubView: (sc := ScrollingDecorator new).
>sc arrangement: #center.
>sc addSubView: (cv := ContainerView new).
>cv usePreferredExtent: true.
>cv layoutManager: GridLayout new.
>cv layoutManager
>    columns: 4;
>    rows: 20.
>80 timesRepeat: [cv addSubView: CheckBox new].
>cv preferredExtent: 1000@1000.
>sc layout
>
>> What do I have to know if I don't use MVP?
>
>The above does use MVP.  At this sort of level you can usually just let the
>components get on with it by themselves and only give it a prod, when you
>want the container to resize in the above example, when needed.
>
>Ian
>
>
>


Reply | Threaded
Open this post in threaded view
|

Re: Better MVP Resources?

Ian Bartholomew-18
Chris,

> more. It's such an important part of any IDE. A simple, yet great
> improvement would be to update the context hilighting after ever
> character typed. I was looking into seeing if I could do it in my
> image.

Not quite that simple I'm afraid.  However, now that the RefactoringBrowser
and it's integral compiler are available it may be a lot easier than it
would have been with previous Dolphin versions - or maybe not :-)

>             Another useful improvment would be the option to save the
> entire package when I save any change to it. I've had Dolphin crash on
> me a number of times (in response to my improper code) and then I lose
> all of my changes.

All the changes are sitting in the change log so are not completely lost.
If you get a crash then you can open the change log in a text editor, or use
a more specialised tool like my ChunkBrowser or MethodHistory goodies, and
retrieve all (usually) of the code you have lost.

You might also want to investigate the source management packages available
for Dolphin which, I imagine, keep copies of all changed methods and
classes.

Ian


Reply | Threaded
Open this post in threaded view
|

Re: Better MVP Resources?

Bill Schwab
In reply to this post by Me
Chris,

> Thanks, that cleared things up a bit. I still think there should be a
> practical reference somewhere. I suppose I should just take up the
> time to map out my own call flow diagram between the model, view, and
> presenter. I think I just need to know what gets called when and when
> events are triggered. Still, for $350, it might be nice if something
> more basic than a tutorial was provided.

You're not the first to suggest that, and I know I found MVP quite difficult
to learn - now I wonder why I had trouble.  It's also true that Dolphin was
not nearly so mature in those days as it is now, so even the VC was a source
of problems requiring workarounds.  Still, I suspect it would be challenging
to learn now too.

Your average Visual XYZ++ (which of course now has to be renamed Visual
X#.NET) book is full of examples.  <SmalltalkBias>How much do they really
help?  Before Dolphin became publicly available, I was using Smalltalk/V
purchased on educational discounts and was trying to decide whether or not
to sink big bucks into a commercial Smalltalk or to switch over to something
else.  I even looked at VB; it was traumatic<g>, but I looked.  Naturally I
was using a book or two.  It became very clear even with my rather limited
Smalltalk expertise at the time, that in the VB world, I was learning how to
solve indivdual problems.  The next problem I encountered was not noticeably
easier to solve because I had solved the previous one - it seemed like an
endless chain of special cases.  In contrast, even the pathetic IDE (in
comparision with Dolphin, and even Squeak) of STV allowed me to apply simple
browsing skills to solve new problems.  The language itself was a little
funny looking, but it worked the same way everywhere rather than having all
kinds of unpredictable "it just works that way" cases that necessitate a
shelf full of self-help books.</SmalltalkBias>

FWIW, I liked the Education Centre a lot more when it was delivered as HTML
vs. compiled help.  The older format documents were quite useful on the n+1
reading<g>.  I think there is adequate documentation (with all resources
combined, including Ian's archives of this group), and the challenge now is
to build some IDE extensions that get a newbie going quickly and offer
contex-sensitive features and help.


> Another useful improvment would be the option to save the
> entire package when I save any change to it. I've had Dolphin crash on
> me a number of times (in response to my improper code) and then I lose
> all of my changes. So now, I'm in the habit of going to the package
> browser, each time, to save things before running anything with loops
> in it. Kind of a pain. But again, I imagine I can hack the image to
> get the behavior I want. It's good to be doing Smalltalk again.

You certainly can build any tools you want.  My recommendation is to make
frequent backups (changes, image, and sources together - see the Wiki if
you're not sure what I mean by that) and to save the image before you do
anything dangerous.  At that point, Ian's ChunkBrowser should be able
recover anything that do occaisionally lose.  The problem with saving
packages is that saving too often can overwite things you'd prefer to have
kept, and the _real_ problem is that they won't always save due to cycles.

Have a good one,

Bill

--
Wilhelm K. Schwab, Ph.D.
[hidden email]


Reply | Threaded
Open this post in threaded view
|

Re: Better MVP Resources?

Christopher J. Demers
In reply to this post by Me
Chris Corcoran <[hidden email]> wrote in message
news:[hidden email]...
...
> more. It's such an important part of any IDE. A simple, yet great
> improvement would be to update the context hilighting after ever
> character typed. I was looking into seeing if I could do it in my

Check out this add-on:
Tools+
http://www.solutionsoft.co.uk/toolsplus/
This adds dynamic syntax highlighting, an easy way to step into blocks in
the debugger, and some other goodies.  I am currently evaluating it, and so
far I like it.  I have not purchased this yet, but I do use his ReStore
tool, and the support from John has been great.  The syntax highlighting
does not appear to work on NT, but works on 2000, and probably ME.  He has a
demo available.

> image. Another useful improvment would be the option to save the
> entire package when I save any change to it. I've had Dolphin crash on
> me a number of times (in response to my improper code) and then I lose
> all of my changes. So now, I'm in the habit of going to the package

Get Ian's ChunkBrowser goodie.  It is the ultimate crash recovery tool.  I
have used it a few times to recover changes after a crash, it has been a
real life saver.  You can read more about it here
http://www.idb.me.uk/goodies5/chunkbrowser.html .


Chris


Reply | Threaded
Open this post in threaded view
|

Re: Better MVP Resources?

Louis Sumberg-2
In reply to this post by Andy Bower
In an attempt to implement a scrollable FlowLayout, I took a closer look at
Andy's DynamicComponentDemo package, where there's a containerview (with a
FlowLayout), on top of a ScrollingDecorator.  I noticed it doesn't behave
all that well-mannered when the view is resized.  (I realize
this demo was put together quickly so I'm not knocking it, btw.)  For
example, try maximizing and unmaximizing the view with or without any
subviews in it and you'll see scrollbars appearing where you don't really
want them.

I played around with changing extent but came to the conclusion that
changing preferredExtent is really the way to go for "fine-grain" control.
In the case where you want no scrollbars to appear when the shellview first
appears or is resized, the following seems to work:  In the VC, change
dynamicContainer's aspects #usePreferredExtent to true and #preferredExtent
to 1 @ 1.

Once you start relying on preferredExtent, then
#resizeDynamicContainerForNewItem: also needs to be changed to change
preferredExtent instead of width and height, as follows:

resizeDynamicContainerForNewItem: newItem
    dynamicContainer view preferredExtent: newItem view width @
        (newItem view height * self dynamicComponents size).
    self view validateLayout

One interesting thing about this approach is that the two previous separate
calls, one to #width: and the other to #height:, are not needed -- a single
call to #preferredExtent: does the job, though 'self view validateLayout' is
still needed.

The next thing I did was to change it from single-column to multi-column.
In the VC, change dynamicContainer's layoutManager aspect for #horizontalGap
to zero or something small.

The scribble views now seem to flow correctly, but the vertical scrollbar
appears quicker than expected.  This is because the preferred height is
still set based on a single column, whereas it now should be based on the
bottom of the last subview, as in:

resizeDynamicContainerForNewItem: newItem
    dynamicContainer view preferredExtent: newItem view width @
        newItem view rectangle bottom.
    self view validateLayout

Now the vertical scrollbar appears at the right time and is adjusted
properly as subviews are added, though it's still off when the shellview is
resized.  Frankly, I don't know why a horizontal scrollbar doesn't appear
since the preferredWidth is still based on a single subview's (newItem)
width.  In fact, changing 'newItem view width' to '1' in above method seems
to work fine.

The next thing to do is add some code for when the shellview is
resized.  This involves implementing #onPositionChanged: in the shell which
calls a helper method.

onPositionChanged: aPositionEvent
    aPositionEvent isResize ifTrue: [self resizeDynamicContainer].
    ^super onPositionChanged: aPositionEvent.

resizeDynamicContainer
    | x y rect |
    dynamicContainer view preferredExtent: 1 @ 1.
    self view validateLayout.
    x := y := 1.
    dynamicContainer view allSubViews do:
            [:e |
            rect := e rectangle.
            rect right > x ifTrue: [x := rect right].
            rect bottom > y ifTrue: [y := rect bottom]].
    dynamicContainer view preferredExtent: x @ y.
    self view validateLayout

The first pair of lines force a layout using the width of the container, the
rest of the method forces another layout, taking into account what the new
extent should be.  To see this at work a little more clearly, insert 'self
halt' in #onPositionChanged, as the first statement inside the block, then
step through #resizeDynamicContainer in the debugger.

Though not necessary, a little refactoring can be done at this point,
deleting #resizeDynamicContainerForNewItem: and changing
#addDynamicComponent to call #resizeDynamicContainer.

addDynamicComponent
    "Dynamically add a new component to the receiver"
    self dynamicComponentClass createIn: dynamicContainer.
    self resizeDynamicContainer.
    self scrollToLastItem

Voila, a scrollable flowing layout!

-- Louis