BorlandTalk.com Forum Index BorlandTalk.com
Borland discussion newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

How to reflect the state of a View into the Model?
Goto page 1, 2  Next
 
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> Delphi OO design
View previous topic :: View next topic  
Author Message
Shawn Oster
Guest





PostPosted: Wed Nov 19, 2003 9:29 pm    Post subject: How to reflect the state of a View into the Model? Reply with quote




I have a vector drawing application and I need a way to distinguish between
when I'm rendering the drawing objects in a 'live' mode or a 'design' mode.
In design mode I ignore visibility factors, draw a dotted box around images
for a place holder, etc. Think of it like designing a form in the IDE vs
running the application. To me this is a function of a View, not the Model.
Even if I split it out into two Views, a Design and a Live, I still have the
same issue, how do I tell the model which drawing style I want?

I've been casting about for various methods to accomplish this and I see two
options:

1. Pass the state as a parameter to my Draw() routines.

2. Use a state flag like TComponent.ComponentState to put all my drawing
objects into either a design or live 'state'.

Thoughts or any pattern-based approaches to this issue?

Thanks,
Shawn


Back to top
Joanna Carter (TeamB)
Guest





PostPosted: Wed Nov 19, 2003 10:23 pm    Post subject: Re: How to reflect the state of a View into the Model? Reply with quote



Shawn Oster wrote:

Quote:
I have a vector drawing application and I need a way to distinguish
between when I'm rendering the drawing objects in a 'live' mode or a
'design' mode. In design mode I ignore visibility factors, draw a
dotted box around images for a place holder, etc. Think of it like
designing a form in the IDE vs running the application. To me this
is a function of a View, not the Model. Even if I split it out into
two Views, a Design and a Live, I still have the same issue, how do I
tell the model which drawing style I want?

You don't. The whole idea of MVP is that the Model doesn't know how it is
being displayed, it is merely a description of the data that will be
rendered.

Assuming you have a Presenter that creates an appropriate View for the Model
passed to it, then it would be the job of the Presenter to know whether this
was a design or live situation and it would then attach the appropriate
View.

Joanna

--
Joanna Carter (TeamB)

Consultant Software Engineer
TeamBUG support for UK-BUG
TeamMM support for ModelMaker



Back to top
Marc Rohloff
Guest





PostPosted: Wed Nov 19, 2003 10:36 pm    Post subject: Re: How to reflect the state of a View into the Model? Reply with quote



On Wed, 19 Nov 2003 14:29:29 -0700, Shawn Oster<soster (AT) moc (DOT) xelfroloc>
said ...
Quote:

I have a vector drawing application and I need a way to distinguish between
when I'm rendering the drawing objects in a 'live' mode or a 'design' mode.
In design mode I ignore visibility factors, draw a dotted box around images
for a place holder, etc. Think of it like designing a form in the IDE vs
running the application. To me this is a function of a View, not the Model.
Even if I split it out into two Views, a Design and a Live, I still have the
same issue, how do I tell the model which drawing style I want?

I've been casting about for various methods to accomplish this and I see two
options:

1. Pass the state as a parameter to my Draw() routines.

2. Use a state flag like TComponent.ComponentState to put all my drawing
objects into either a design or live 'state'.

Thoughts or any pattern-based approaches to this issue?
It sounds like you are trying to get a Model-View seperation. The idea

here is that the model and the view are seperate entities. The model
knows nothing about the view (or views in general) or how to draw itself.

The view would be completely responsible for drawing itself. To do this
it might have to have a set of classes which mirror those of the model
but do the drawing.

Since you are describing something like a CAD program this is
probably not appropriate since the drawing is very tightly bound to the
model.

A common alternative is to give each object a way to get a context object
(which would also include the drawing style/design mode and maybe other
things like color). I assume that all you classes derive from a common
base class so this wouldn't be to hard to add. Normally the
'getContext' method would just ask it's container for it's contex,
which would ask it's container, etc, until you get to a class which
definitely knows its context (the root container normally)

Marc

Back to top
Shawn Oster
Guest





PostPosted: Wed Nov 19, 2003 11:45 pm    Post subject: Re: How to reflect the state of a View into the Model? Reply with quote


"Joanna Carter (TeamB)" <joannac (AT) btinternetXX (DOT) com> wrote

Quote:
Shawn Oster wrote:

| I have a vector drawing application and I need a way to distinguish
| between when I'm rendering the drawing objects in a 'live' mode or a
| 'design' mode. In design mode I ignore visibility factors, draw a
| dotted box around images for a place holder, etc. Think of it like
| designing a form in the IDE vs running the application. To me this
| is a function of a View, not the Model. Even if I split it out into
| two Views, a Design and a Live, I still have the same issue, how do I
| tell the model which drawing style I want?

You don't. The whole idea of MVP is that the Model doesn't know how it is
being displayed, it is merely a description of the data that will be
rendered.

Assuming you have a Presenter that creates an appropriate View for the
Model
passed to it, then it would be the job of the Presenter to know whether
this
was a design or live situation and it would then attach the appropriate
View.

I went rounds and rounds with this when I was designing the application and
some days I pat myself on the back and others I shake my fists in anger at
myself (it's funny to watch).

If I understand you correctly you are saying that the View should know how
to draw the model, calling any GDI or TCanvas (or whatever else) calls
needed. So what I have now is:

TShape = class
public
procedure Draw(Surface: TCanvas);
property Bounds;
property Color;
end;

And what you are proposing is to remove the Draw() method and stick that
functionality inside of the TView, such as:

TView = class
private
FCanvas: TCanvas;
procedure DrawShape(Shape: TShape);
procedure DrawWhatever(Whatever: TWhatever);
public
procedure DrawModel(Model: TModel); // calls all the DrawXXX routines
as needed
end;

The area I was torn was the fact that I use the Draw() method in a) Live
Mode, b) Design Mode, c) Print Preview, d) Actual Printing, and e)
Generation of a PNG thumbnail. Since I draw to so many different views I
wanted a standard place for my render code. How would you handle keeping
the drawing code in the View but also in a centralized place? Off-the-cuff
I see two basic options:

1) Create a base drawing surface, TModelCanvas that knows how to render a
model and views that descend from there, so you'd have:

TModelCanvas
DrawModel(Model: TModel);
end;

TModelView = class(TModelCanvas)
// Add View related methods here, listeners, etc
end;

TLiveView = class(TModelView);
TDesignView = class(TModelView);
TPrintPreviewView = class(TModelView);
TPrintView = class(TModelView);

OR

2) Create a utility drawing class, that is instantiated by the View to draw
the model and knows a bit about which view is requesting the drawing:

TModelRender = class;
DrawModelToCanvas(Canvas: TCanvas; Model: TModel; DrawAspect:
TDrawAspect);
end;

TLiveView = class
DrawModel();
end;

TLivewView.DrawModel(Model: TModel);
begin
ModelRender := TModelRender.Create;
ModelRender.DrawModelToCanvas(Self.Canvas, Model, daLive);
end;

Whew, that's a mouth full.

Shawn



Back to top
Shawn Oster
Guest





PostPosted: Thu Nov 20, 2003 12:10 am    Post subject: Re: How to reflect the state of a View into the Model? Reply with quote

"Marc Rohloff" <marc rohloff at bigfoot dot com> wrote

Quote:
On Wed, 19 Nov 2003 14:29:29 -0700, Shawn Oster said ...

I have a vector drawing application and I need a way to distinguish
between
when I'm rendering the drawing objects in a 'live' mode or a 'design'
mode.
In design mode I ignore visibility factors, draw a dotted box around
images
for a place holder, etc. Think of it like designing a form in the IDE
vs
running the application. To me this is a function of a View, not the
Model.
Even if I split it out into two Views, a Design and a Live, I still have
the
same issue, how do I tell the model which drawing style I want?

I've been casting about for various methods to accomplish this and I see
two
options:

1. Pass the state as a parameter to my Draw() routines.

2. Use a state flag like TComponent.ComponentState to put all my drawing
objects into either a design or live 'state'.


The view would be completely responsible for drawing itself. To do this
it might have to have a set of classes which mirror those of the model
but do the drawing.

I had thought that at first but my rational against that was if I wanted to
make this a plug-in architecture where I can add new custom drawing elements
later it is easier for each element to know how to draw itself. I can then
have a registration mechanism for new drawing elements and they would be
instantly available. I suppose I could have two registration procedures,
one for the model, another for the render view.

Quote:
Since you are describing something like a CAD program this is
probably not appropriate since the drawing is very tightly bound to the
model.

That was my thought on it. Almost all the MVC or MVP examples I see are
fairly 'static'. By that I mean the view is either updating from or
updating to the model, without much of things I need to handle such as
snapping to a grid, multiple element selection, hit-testing, flicker-free
and frequent updates between model and view, view-centric options (turning
off layers in the CAD design), bring to front, send to back, etc, etc. I'm
still looking but anything that starts to approach a full-featured true MVP
seems to have a few shortcuts in it, like suddenly the some view state has
made it's way back to the model.

Quote:
A common alternative is to give each object a way to get a context object
(which would also include the drawing style/design mode and maybe other
things like color). I assume that all you classes derive from a common
base class so this wouldn't be to hard to add. Normally the
'getContext' method would just ask it's container for it's contex,
which would ask it's container, etc, until you get to a class which
definitely knows its context (the root container normally)

Hmm, so very much like TComponent.ComponentState represents the current
context? Or am I still missing something?

Thanks,
Shawn



Back to top
Ritchie
Guest





PostPosted: Thu Nov 20, 2003 2:06 am    Post subject: Re: How to reflect the state of a View into the Model? Reply with quote

In article <3fbc0090 (AT) newsgroups (DOT) borland.com>, [email]soster (AT) moc (DOT) xelf[/email]roloc
says...
Quote:
If I understand you correctly you are saying that the View should know how
to draw the model, calling any GDI or TCanvas (or whatever else) calls
needed. So what I have now is:

TShape = class
public
procedure Draw(Surface: TCanvas);
property Bounds;
property Color;
end;

There's a model-presenter trouble right there Smile I've done the same
thing myself as shortcuts in the past, and regretted it over time, where
I had controls that had their own Print(), etc. etc. The more targets
you go to, the nastier it gets.

Quote:
And what you are proposing is to remove the Draw() method and stick that
functionality inside of the TView, such as:

TView = class
private
FCanvas: TCanvas;
procedure DrawShape(Shape: TShape);
procedure DrawWhatever(Whatever: TWhatever);
public
procedure DrawModel(Model: TModel); // calls all the DrawXXX routines
as needed
end;

That's a simplistic way of doing it, but suffers a lot from putting too
much knowledge in one place. What you likely want to do is not have a
monolithic "view" class for these purposes, but rather, a set of
"Drawer" classes.

TDrawer = class
private
FObject : TObject;
public
constructor Create(AObject: TObject); virtual;
class function AcceptsObject(AObject: TObject): Boolean; virtual;
procedure Draw(AView: TView); virtual;
end;

TShapeDrawer = class(TDrawer)
protected
function GetShape: TShape;
property Shape: TShape read GetShape;
public
class function AcceptsObject(AObject: TObject): Boolean; override;
procedure Draw(AView: TView); override;
end;

// Assuming that Shapes in design mode have more bits on them
TDesignShapeDrawer = class(TShapeDrawer)
public
procedure Draw(AView: TView); override;
end;

// -----

function TShapeDrawer.GetShape: TShape;
begin
// Just for ease of syntax
Result := FObject as TShape;
end;

class function TShapeDrawer.AcceptsObject(AObject: TObject): Boolean;
begin
// Only accepts TShapes to draw
Result := AObject is TShape;
end;

procedure TShapeDrawer.Draw(AView: TView);
begin
Assert(Assigned(AView),'ShapeDrawer::Draw needs a view');
Assert(Assigned(AView.Canvas),'ShapeDrawer::Draw needs a view with '+
'a Canvas');
AView.Canvas.xx;
AView.Canvas.xx;
end;

What you would want to use, then, is a factory for your drawers (hush,
Joanna Smile...

TDrawerClass = class of TDrawer;

TDrawerRegistry = class
private
FDrawerClassList : TList; // or use TClassList in newer Delphis
FModeList : TStringList;
public
constructor Create;
destructor Destroy; override;
procedure Add(AMode: String; ADrawerClass: TDrawerClass);
function NewDrawer(AMode: String; AObject: TObject): TDrawer;
end;

constructor TDrawerRegistry.Create;
begin
inherited;
FDrawerClassList := TList.Create;
FModeList := TStringList.Create;
end;

destructor TDrawerRegistry.Destroy;
begin
FDrawerClassList.Free;
FModeList.Free;
inherited;
end;

procedure TDrawerRegistry.Add(AMode: String;
ADrawerClass: TDrawerClass);
begin
FDrawerClassList.Add(ADrawerClass);
FModeList.Add(AMode);
end;

function TDrawerRegistry.NewDrawer(AMode: String;
AObject: TObject): TDrawer;
var
Index : Integer;
begin
Assert(AObject<>nil,'DrawerRegistry::NewDrawer needs a valid object');
Result := nil;
Index := FDrawerClassList.Count-1;
while (Index>=0) and (Result=nil) do
begin
if (FModeList[Index]=AMode) and
TDrawerClass(FDrawerClassList).
AcceptsObject(AObject) then
Result := TDrawerClass(FDrawerClassList).
Create(AObject);
Dec(Index);
end;
if Result=nil then
raise Exception.CreateFmt('No drawer available for '+
'%s in mode %s',[AObject.ClassName,AMode]);
end;

If you create a global DrawerRegistry object, you can now do things
like:

DrawerRegistry.Add('live',TShapeDrawer);
DrawerRegistry.Add('preview',TShapeDrawer);
DrawerRegistry.Add('design',TDesignShapeDrawer);
DrawerRegistry.Add('live',TWhateverDrawer);
etc.

Then, when it's time to draw said item, you can either create/use/free,
or create and hold onto the drawer objects:

MyDrawer := DrawerRegistry.NewDrawer(CurrentMode,ObjectToDraw);

MyDrawer.Draw(View);

e.g. DrawerRegistry.NewDrawer('design', MyShapeObject) would create a
new TDesignShapeDrawer.

Quote:
The area I was torn was the fact that I use the Draw() method in a) Live
Mode, b) Design Mode, c) Print Preview, d) Actual Printing, and e)
Generation of a PNG thumbnail. Since I draw to so many different views I
wanted a standard place for my render code. How would you handle keeping
the drawing code in the View but also in a centralized place? Off-the-cuff
I see two basic options:

One thing to remember is that when folks talk about "Model-View-
Controller", that the 'View' isn't necessarily one object any more than
the 'Model' is :)

Quote:
1) Create a base drawing surface, TModelCanvas that knows how to render a
model and views that descend from there, so you'd have:

TModelCanvas
DrawModel(Model: TModel);
end;

TModelView = class(TModelCanvas)
// Add View related methods here, listeners, etc
end;

TLiveView = class(TModelView);
TDesignView = class(TModelView);
TPrintPreviewView = class(TModelView);
TPrintView = class(TModelView);

Having the views descend from a common hierarchy probably isn't too bad
(although you should make the base class as abstract as possible, i.e.
don't fill in too much functionality), but it's probably a bad idea to
descend from a TModelCanvas. You can *contain* a ModelCanvas, sure, but
the relationship "ModelView IS-A ModelCanvas" doesn't seem to hold.

Quote:
OR

2) Create a utility drawing class, that is instantiated by the View to draw
the model and knows a bit about which view is requesting the drawing:

TModelRender = class;
DrawModelToCanvas(Canvas: TCanvas; Model: TModel; DrawAspect:
TDrawAspect);
end;

TLiveView = class
DrawModel();
end;

TLiveView.DrawModel(Model: TModel);
begin
ModelRender := TModelRender.Create;
ModelRender.DrawModelToCanvas(Self.Canvas, Model, daLive);
end;

You do gain a little from splitting out the rendering from the view
itself.

However, you probably are feeling a bit "icky" that the functionality
used to be in nice separate classes that knew about themselves, and now
is glommed into one class. That seems counter to OOP principles, and in
many ways, it is.

That's why I suggest the "factory" model I presented above (and you're
more than free to ask questions about it! Smile.

Objects that represent things shouldn't know how to draw themselves,
because it couples the objects to a display, or at least a means of
display. The more different targets you have, the worse that code is
going to get (drawing a bevel for screen purposes probably doesn't look
that great to the printer, so add another case to *all* the objects
drawing code).

On the other hand, no single class should have to know about everything
about each of a continually expanding set of classes; that contributes
to huge/numerous methods, and means that the class has to be constantly
updated whenever objects get changed/deleted/added or new modes get
created.

Having a specific-view class that knows all about a single model class,
and a single mode (or set of modes that behave exactly the same way) is
the ideal way to go.

Try the factory approach and let us know how you make out with it.

Quote:
Whew, that's a mouth full.

You said it! :)

Sorry for the ramble - hopefully there's something that helps in this
mess of the English language I've made :)

Quote:
Shawn

-- Ritchie Annand
Senior Software Architect
http://www.malibugroup.com
http://nimble.nimblebrain.net
http://wiki.nimblebrain.net

Back to top
Harley Pebley
Guest





PostPosted: Thu Nov 20, 2003 2:24 am    Post subject: Re: How to reflect the state of a View into the Model? Reply with quote

Quote:
I have a vector drawing application and I need a way to distinguish between
when I'm rendering the drawing objects in a 'live' mode or a 'design' mode.
In design mode I ignore visibility factors, draw a dotted box around images
for a place holder, etc. Think of it like designing a form in the IDE vs
running the application. To me this is a function of a View, not the Model.
Even if I split it out into two Views, a Design and a Live, I still have the
same issue, how do I tell the model which drawing style I want?

I've been casting about for various methods to accomplish this and I see two
options:

1. Pass the state as a parameter to my Draw() routines.

2. Use a state flag like TComponent.ComponentState to put all my drawing
objects into either a design or live 'state'.

Thoughts or any pattern-based approaches to this issue?

Have you looked at the Decorator pattern?

For example:
TDisplayableItem = class
procedure Draw; virtual;
end;

TShape = class(TDisplayableItem)
procedure Draw; override; // Knows how to draw a TShape
end;

TAnotherShape = class(TDisplayableItem)
procedure Draw; override; // Knows how to draw a TAnotherShape
end;

Add as needed via your plug-in system.

Then:
TRuntimeDecorator = class(TDisplayableItem)
// Knows how to draw an Item and then the additional bits for the
// run-time environment
procedure Draw; override;
property Item: TDisplayableItem read fItem write fItem;
end;

TDesignDecorator = class(TDisplayableItem)
// Knows how to draw an Item and then the additional bits for the
// design-time environment
procedure Draw; override;
property Item: TDisplayableItem read fItem write fItem;
end;

You only have as many decorators as you have environments. Each environment
knows about it's own decorators and creates them as needed to display any
shapes within that environment. Shapes and decorators can be used
interchangably for other areas of your framework which don't care about the
decorator/shape differences. You only have as many shape classes as you
have shapes.

HTH,
Harley Pebley

Back to top
Joanna Carter (TeamB)
Guest





PostPosted: Thu Nov 20, 2003 8:07 am    Post subject: Re: How to reflect the state of a View into the Model? Reply with quote

Shawn Oster wrote:

Quote:
And what you are proposing is to remove the Draw() method and stick
that functionality inside of the TView, such as:

TView = class
private
FCanvas: TCanvas;
procedure DrawShape(Shape: TShape);
procedure DrawWhatever(Whatever: TWhatever);
public
procedure DrawModel(Model: TModel); // calls all the DrawXXX
routines as needed
end;

That's about right.

Quote:
1) Create a base drawing surface, TModelCanvas that knows how to
render a model and views that descend from there, so you'd have:

This is not as flexible as 2

Quote:
2) Create a utility drawing class, that is instantiated by the View
to draw the model and knows a bit about which view is requesting the
drawing:

You almost got this one right. As Ritchie hinted, you need to use a Factory
here...

TModelRender = class;
procedure DrawModelToCanvas(Canvas: TCanvas; Model: TModel);
end;

TLiveModelRender = class(TModelRender)
TDesignModelRender = class(TModelRender)
TPrintPreviewModelRender = class(TModelRender)
TPrintModelRender = class(TModelRender)

TView = class
....
procedure DrawModel(Model: TModel; DrawAspect: TDrawAspect);
....
end;

procedure TView.DrawModel(Model: TModel; DrawAspect: TDrawAspect);
begin
ModelRender := TModelRenderFactory.CreateRender(DrawAspect);
ModelRender.DrawModelToCanvas(Self.Canvas, Model);
end;

Joanna

--
Joanna Carter (TeamB)

Consultant Software Engineer
TeamBUG support for UK-BUG
TeamMM support for ModelMaker



Back to top
Marc Rohloff
Guest





PostPosted: Thu Nov 20, 2003 2:24 pm    Post subject: Re: How to reflect the state of a View into the Model? Reply with quote

Quote:
Hmm, so very much like TComponent.ComponentState represents the current
context? Or am I still missing something?
Sort of. Component State is set by the IDE on every object as created. I

was thinking of something more dynamic but you could go either way.

I think MVP might be overkill if you only intend to have a design-time or
run-time option, however I noticed in another post of yours that you also
talk about printing and creating PNGs. If this is going to affect your
drawing logic then you might want to factor this out from your objects.

You could take Ritchie's idea osf seperating the rendering logic without
going for the MVC/MVP route. Here I give each object type a list of
renderers instead of splitting these off into the view.

TRenderer = class
{Not intended to be instantiated}
class procedure Draw(canvas:TCanvas; object:TBaseShape); virtual;
end;
TRendererClass = class of TRenderer;

TViewType = (vtRuntime, vtDesignTime, vtPrint, vtGraphic);
TRenderers = array[TViewType] of TRendererClass;

TBaseShape = class
protected
function GetRenderer(viewtype:TViewType):TRendererClass;
{Return a useful default if none registered like the
the runtime renderere}
procedure RegisterRenderers(renderers:TRenderers);

public
procedure Draw(canvas:TCanvas);
end;


procedure TBaseShape.Draw;
var r:TRendererClass;
begin
r := GetRenderer(viewtype);
r.Draw(canvas, self);
end;

Marc




Back to top
Shawn Oster
Guest





PostPosted: Fri Nov 21, 2003 6:55 pm    Post subject: Re: How to reflect the state of a View into the Model? Reply with quote


"Ritchie" <ritchieabatbat (AT) spamcop (DOT) netbatbat> wrote

Quote:
In article <3fbc0090 (AT) newsgroups (DOT) borland.com>, [email]soster (AT) moc (DOT) xelf[/email]roloc
says...

That's a simplistic way of doing it, but suffers a lot from putting too
much knowledge in one place. What you likely want to do is not have a
monolithic "view" class for these purposes, but rather, a set of
"Drawer" classes.

What! More work? *grin* Kidding. My first thought was maintence nightmare
but then I look at what I'm doing now with passing around context
information, specialized code that knows way too much about the view and I
see I had my logic turned around.

Quote:
You do gain a little from splitting out the rendering from the view
itself.

However, you probably are feeling a bit "icky" that the functionality
used to be in nice separate classes that knew about themselves, and now
is glommed into one class. That seems counter to OOP principles, and in
many ways, it is.

Exactly how I was feeling *smile*. My formative years in OOD were along the
lines that an object knows how to do everything to itself, drawing,
printing, saving, etc, etc.

Quote:
That's why I suggest the "factory" model I presented above (and you're
more than free to ask questions about it! Smile.

I've used factories in other areas, such as when handling different file
importers but it never occured to me to use them in more of an inter-process
role. What I'm learning is that I tend to apply patterns at a very macro
level instead of thinking of how they could be used in the smaller
interactions inside of my class hierarchy.

Quote:
Try the factory approach and let us know how you make out with it.

I definitely will! Your approach helps me get over the few reservations I
had about creating so many different classes to support what I do now with
basically two. It worked fine when I only had two different view states but
as I'm having to add more it's becoming rather... painful. Thanks for your
advice and especially that huge code snippet.

Shawn



Back to top
Shawn Oster
Guest





PostPosted: Fri Nov 21, 2003 7:07 pm    Post subject: Re: How to reflect the state of a View into the Model? Reply with quote


"Marc Rohloff" <marc rohloff at bigfoot dot com> wrote

Quote:
Hmm, so very much like TComponent.ComponentState represents the current
context? Or am I still missing something?
Sort of. Component State is set by the IDE on every object as created. I
was thinking of something more dynamic but you could go either way.

I think MVP might be overkill if you only intend to have a design-time or
run-time option, however I noticed in another post of yours that you also
talk about printing and creating PNGs. If this is going to affect your
drawing logic then you might want to factor this out from your objects.

I'm still debating on how full an implimentation of MVC/P to impliment. Of
course I also have a few other questions I'm going to hit this newsgroup up
with so that might just change everyone's perception. Also salesmarketing
just added a few more "views" for me.

Quote:
You could take Ritchie's idea osf seperating the rendering logic without
going for the MVC/MVP route. Here I give each object type a list of
renderers instead of splitting these off into the view.

procedure TBaseShape.Draw;
var r:TRendererClass;
begin
r := GetRenderer(viewtype);
r.Draw(canvas, self);
end;

In your example I like how the base class is a wrapper around factory
(GetRenderer) calls. I know this is pseudo-code but in this example where
do you see the viewtype being set? Dreaded global or passed in?

Thanks for all your comments.
Shawn



Back to top
Shawn Oster
Guest





PostPosted: Fri Nov 21, 2003 7:17 pm    Post subject: Re: How to reflect the state of a View into the Model? Reply with quote


"Harley Pebley" <harley_pebley (AT) idahotech (DOT) com> wrote

Quote:

1. Pass the state as a parameter to my Draw() routines.

2. Use a state flag like TComponent.ComponentState to put all my drawing
objects into either a design or live 'state'.

Thoughts or any pattern-based approaches to this issue?

Have you looked at the Decorator pattern?

For example:
TDisplayableItem = class
procedure Draw; virtual;
end;

TShape = class(TDisplayableItem)
procedure Draw; override; // Knows how to draw a TShape
end;

Add as needed via your plug-in system.

Then:
TRuntimeDecorator = class(TDisplayableItem)
// Knows how to draw an Item and then the additional bits for the
// run-time environment
procedure Draw; override;
property Item: TDisplayableItem read fItem write fItem;
end;

If I read this right then each viewenvironment only knows about it's own
decorators, hence the RunTimeView knows about a list of RuntimeDecorators.
My question is where do you put the specific drawing code for a specific
object for a specific view? In your example I see a TRuntimeDecorator but I
need one that will draw a Shape, and another one that will draw a
TAnotherShape, etc, etc. How do you link the concept of a TShape with a
TRuntimeDecorator?

I know I'm probably missing something simple here, thanks for the help.

Shawn



Back to top
Marc Rohloff
Guest





PostPosted: Fri Nov 21, 2003 8:15 pm    Post subject: Re: How to reflect the state of a View into the Model? Reply with quote

Quote:
procedure TBaseShape.Draw;
var r:TRendererClass;
begin
r := GetRenderer(viewtype);
r.Draw(canvas, self);
end;

In your example I like how the base class is a wrapper around factory
(GetRenderer) calls. I know this is pseudo-code but in this example where
do you see the viewtype being set? Dreaded global or passed in?

I know that passing it in is neater but in these sort of architectures
you tend to land up passing it all over the place. I think it depends to
some extent on how often you are going to change a view state also can
you have more than one view available at a time? Can they design in one
window and have a print preview in another while exporting a graphic?

If they can then you probably need to go the more complex MVP route (a
la Ritchie) or pass it in every time. If not I still favor the context
object approach.

Marc

Back to top
Harley Pebley
Guest





PostPosted: Fri Nov 21, 2003 9:35 pm    Post subject: Re: How to reflect the state of a View into the Model? Reply with quote

Quote:
If I read this right then each viewenvironment only knows about it's own
decorators, hence the RunTimeView knows about a list of RuntimeDecorators.

Yes. That list may be a list of one.

Quote:
My question is where do you put the specific drawing code for a specific
object for a specific view?

The code to draw a shape is in the shape item. The code to draw the extra
bits for the environment are in the decorator item.

Quote:
In your example I see a TRuntimeDecorator but I need one that will draw
a Shape, and another one that will draw a TAnotherShape, etc, etc.

No. See below.

Quote:
How do you link the concept of a TShape with a TRuntimeDecorator?

As a property on the decorator.

Quote:
I know I'm probably missing something simple here, thanks for the help.

There is one decorator per environment. The environment creates the shape
and a decorator and assigns the shape to the decorator as a property. The
decorator doesn't know what type of shape, just that it has one. When the
decorator is told to draw, it first tells the shape to draw (whatever that
happens to be) and then draws its own decoration. The number of classes
involved is NumOfDecorators+NumOfShapes, rather than
NumOfDecorators*NumOfShapes.

Does that clear it up?

Harley Pebley

Back to top
Shawn Oster
Guest





PostPosted: Sat Nov 22, 2003 12:09 am    Post subject: Re: How to reflect the state of a View into the Model? Reply with quote


"Marc Rohloff" <dont (AT) mailme (DOT) com> wrote

Quote:
procedure TBaseShape.Draw;
var r:TRendererClass;
begin
r := GetRenderer(viewtype);
r.Draw(canvas, self);
end;

In your example I like how the base class is a wrapper around factory
(GetRenderer) calls. I know this is pseudo-code but in this example
where
do you see the viewtype being set? Dreaded global or passed in?

I know that passing it in is neater but in these sort of architectures
you tend to land up passing it all over the place. I think it depends to
some extent on how often you are going to change a view state also can
you have more than one view available at a time? Can they design in one
window and have a print preview in another while exporting a graphic?

Currently the user can toggle between the two main modes, a design mode
which shows drag handles, image placeholders, a grid to align to, etc. and a
live mode that combines some data-aware aspects and is a simplier view. You
can do a print preview of either mode and also print the live view in a
seperate thread (when printing it does a form of data-merge with a
database).

Currently they can have the two main views, live and design, open in
different windows. Design in one window so you can see it's affects with
live data.

Quote:
If they can then you probably need to go the more complex MVP route (a
la Ritchie) or pass it in every time. If not I still favor the context
object approach.

I had a feeling you'd say that *grin*.

Shawn




Back to top
Display posts from previous:   
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> Delphi OO design All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.