MVC Models
An MVC model encapsulates data that is rendered by viewports and manipulated by controllers. It serves as a computational approximation or abstraction of some real-world process or system. It captures not only the state of a process or system, but also how the system works. This makes it easy to use real-world modeling techniques in defining your models. For example, you might define a model that bridges a computational back-end with a GUI front-end. In this scenario, the model encapsulates the functionality of a computation engine or hardware system and acts as a liaison requesting the real services of the system it models.
All MVC models implement the ISubject interface so they can be observed by one or more viewports. Each type of model defines an interface for manipulating the data it encapsulates. Client code that interacts with the model, such as the controller, can either use the model’s interface directly or execute commands against the model. A command is an object that encapsulates an action to be performed against the model. Commands are the key to supporting undo and redo, which is a feature that can be easily added to MVC models.
The CMvcModel class implements the ISubject interface and is the base class for all MVC models. It maintains an array of IObserver pointers in order to implement the ISubject interface. In addition to the ISubject methods it implements, the CMvcModel class defines some other methods. The IsModified() method returns a Boolean value indicating if the model has been changed since it was last saved. The Reset() method provides a way to clear a model and set it back to its default state. The CMvcModel class is lightweight – its main purpose is to serve as a base class for domain-specific models. The declaration of the CMvcModel class is shown in Example 65.
Example 65 – Declaration of CMvcModel
class CMvcModel : public ISubject
// Constructors/destructor
virtual ~CMvcModel();
// Attributes
ObserverVector m_observers;
// Operations
virtual bool QueryGuid(REFGUID guid, void **ppvObj);
virtual void AddObserver(IObserver* pObserver);
virtual void RemoveObserver(IObserver* pObserver);
virtual void UpdateAllObservers(IObserver* pSender = NULL,
IMessage* pMsg = NULL);
virtual BOOL IsModified() const;
virtual void Reset();
Presentation Models
Frequently, a model contains graphical information that is directly rendered to the viewport. For example, a model might contain visual components that draw themselves onto the viewport. Mixing graphical information with non-graphical information can blur the distinction between the model and viewport. To provide a clear distinction between graphical and non-graphical data, models are classified as either system models or presentation models. A system model is a CMvcModel derived class that represents a non-graphical, real-world system or process. A presentation model is both a model and a visual component that can render itself to a device context. The term visual model can also be used to describe this type of model. System and presentation models can be used exclusively or in combination. Used in combination, a presentation model provides the presentation for a system model, essentially mapping the real-world system into the graphical realm. Figure 11 shows the relationship between the system model and presentation model.
Figure 11 – Relationship between the system model and the presentation model
MvcPresentationModel_T is a template class used to implement presentation models. The template parameter passed to MvcPresentationModel_T is a visual component type, which is declared as a base class. MvcPresentationModel_T also mixes in the CMvcModel class, making the presentation model both a model and a visual component.
A good example of where this idea is useful is in the implementation of a diagramming application. It is natural to implement a diagram class as a presentation model. A diagram would be a kind of presentation model, which manages the graphical symbol data, font choices, pen widths, and so forth. Like a model, it manages data, albeit graphical data, and exports functionality. However, like a visual component, a diagram can draw itself, and it can even be nested as a symbol inside of a parent diagram. Consequently, a diagram is both a model and a visual component.
Because a presentation model can draw itself, the role of the associated viewport changes to some degree. The viewport provides a perspective onto another visual component. The presentation model is essentially a graphics server, serving up whatever rectangular area of the canvas the viewport instructs it to paint.
MFC Specifics
There is an MFC-specific model class that exists primarily for historical reasons. Previous versions of the Stingray MVC library used a slightly different naming convention. The old name is now just an alias for CMvcModel.
typedef CMvcModel MvcModel;