Borland Online And The Cobb Group Present:


December, 1995 - Vol. 2 No. 12

Owl Doc/view Programming - Checking the DirtyFlag in Doc/View applications

by Mark Salsbery

The Borland C++ Document/View architecture (or just Doc/View) provides a powerful mechanism for you to use in designing and implementing applications that display data in more than one form. Within the Doc/View classes, there's a great deal that Borland didn't have the space to adequately address in the user documentation, and the DirtyFlag variable is a good example.

Although the TDocument class member variable DirtyFlag is simply a flag to indicate unsaved changes in a document, the TDocManager class also uses it to control some of the class's default user interface. In addition, you can use the TDocument::DirtyFlag for enabling and disabling standard Doc/View commands, as well as (and perhaps more importantly) for deciding if your application should prompt the user to save changes before closing a document. In this article, we'll look at how TDocument::DirtyFlag affects the user interface and how to use TDocument::DirtyFlag effectively.

How DirtyFlag affects TDocManager's user interface

The only TDocManager command messages that TDocument::DirtyFlag affects are CM_FILESAVE and CM_FILEREVERT. The Doc/View code enables both commands if you set the current document's DirtyFlag data member to TRUE, and it disables them if you set the data member to FALSE.

The TDocManager class's FlushDoc() member function prompts the user to save changes made to a document. The Doc/View code calls the TDocument::CanClose(right arrow function whenever the doc manager closes a document (either while flushing open documents as the application shuts down or in response to a CM_FILECLOSE message) or when the doc manager calls the CanClose() function of a window view such as TWindowView or TListView. In turn, the TDocument::CanClose() function calls TDocManager::FlushDoc(), which checks the document's DirtyFlag data member. If the data member is TRUE, then the FlushDoc() member function prompts the user to save changes. If the user responds by selecting Yes, then FlushDoc() calls the TDocument class's virtual Commit() member function to save the document. If the user selects No, then the FlushDoc() calls the TDocument class's virtual Revert() member function.

Using TDocument::SetDirty( )

The OWL Doc/View base classes make no changes to TDocument::DirtyFlag except for setting it to FALSE at initialization. The responsibility of setting and clearing the variable is left to your Doc/View classes.

If you want to change the value of the DirtyFlag data member from your TDocument-derived document class, you do so by simply using

DirtyFlag = FALSE;

You can make this change because the DirtyFlag data member is part of the TDocument class's protected interface­­it's accessible within the TDocument class and derived classes, but it's not accessible to the rest of the program.

However, a better approach is to use the TDocument::SetDirty() member function to set the DirtyFlag data member, even though the function doesn't do anything else. You'll want to use this function to make sure you take advantage of functional abstraction­­a design technique that encapsulates related activities in a single function call.

Functional abstraction forces your program to behave consistently. Since other parts of the program will have to use the SetDirty() member function to change the DirtyFlag data member, if you use the function call within your document class, you'll know that all the actions related to setting that flag are occurring the same way. Unfortunately, Borland didn't define the SetDirty() member function as virtual, so any part of your application that accesses a document using a TDocument pointer will always call the TDocument::SetDirty() member function, even if you've defined a new version in your TDocument-derived class! To keep the default Doc/View user interface working acceptably, your TDocument-derived classes should at the very least take the following actions:

Even if the application doesn't provide revert capability, the FlushDoc() member function still calls the Revert() function when the user chooses not to save changes made to a document. If we don't set the DirtyFlag variable equal to FALSE in a Revert() function override, then FlushDoc() will repeatedly prompt the user to save changes when closing a document that has multiple window views open­­very annoying!

By the way, if you're deriving your document classes from the OWL-defined TFileDocument class, you don't need to set the DirtyFlag variable yourself­­that is, not as long as you call the TFileDocument::Commit() and TFileDocument::Revert() functions if you override these functions in your derived class. This is because in the FILEDOC.CPP class Borland has already made the correct calls, as shown in Figure A.


Figure A - If you derive your document classes from the TFileDocument class, it will handle setting the DirtyFlag variable in its Commit( ) and Revert( ) functions.

BOOL
TFileDocument::Commit(BOOL force)
{
 if(!TDocument::Commit(force))
    return FALSE;
  SetDirty(FALSE);
  return TRUE;
}

BOOL
TFileDocument::Revert(BOOL clear)
{
  if(!TDocument::Revert(clear))
     return FALSE;
  SetDirty(FALSE);
  return TRUE;
}


Return to the Borland C++ Developer's Journal index

Subscribe to the Borland C++ Developer's Journal


Copyright (c) 1996 The Cobb Group, a division of Ziff-Davis Publishing Company. All rights reserved. Reproduction in whole or in part in any form or medium without express written permission of Ziff-Davis Publishing Company is prohibited. The Cobb Group and The Cobb Group logo are trademarks of Ziff-Davis Publishing Company.