Example #1
0
//
/// Destruct this DocManager. Close all open documents (views close with them),
/// and delete all non-static doc templates
///
/// Destroys a TDocManager object removes attached documents templates. The
/// constructor resets TDocTemplate::DocTemplateStaticHead to point to the head of
/// the static template list.
//
TDocManager::~TDocManager()
{
  // Iterate through document list, closing and deleting each
  //
  TDocument* doc;
  while ((doc = DocList.Next(0)) != 0) {
    if (doc->IsOpen())
      doc->Close();

    // NOTE: deleting the document deletes all attached views, and unlinks
    //       the document from the docmanager's document list
    //
    delete doc;

    // Flush (dispatch) any pending MDI-Child-destroy messages
    //
    GetApplication()->PumpWaitingMessages();
  }

  // Reset the 'Docmanager' pointer of static templates and delete
  // dynamic ones...
  //
  while (TemplateList) {
    TDocTemplate* tpl = TemplateList;
    TemplateList = tpl->GetNextTemplate();
    if (tpl->IsStatic())
      tpl->SetDocManager(0);
    else
      delete tpl;
  }
}
Example #2
0
//
/// Used only after streaming in the doc manager, EvWakeUp allows for the windows to
/// be created after the streaming has occurred.
//
void
TDocManager::EvWakeUp()
{
  TDocument* doc = 0;
  while ((doc = DocList.Next(doc)) != 0)
    doc->ReindexFrames();
}
Example #3
0
//
/// Performs the reverse of Commit() and cancels any changes made to the document
/// since the last commit. If clear is true, data is not reloaded for views. Revert
/// also checks all child documents and cancels any changes if all children return
/// true. When a file is closed, the document manager calls either Commit() or Revert.
/// Returns true if the operation is successful.
//
bool
TDocument::Revert(bool clear)
{
  TDocument* pdoc = 0;
  while ((pdoc = ChildDoc.Next(pdoc)) != 0) {
    if (!pdoc->Revert(clear))
      return false;
  }
  return NotifyViews(vnRevert, clear);
}
Example #4
0
//
/// Checks to see if all child documents can be closed before closing the current
/// document. If any child returns false,  returns false and aborts the process. If
/// all children return true, EvCanClose calls TDocManager::FlushDoc for each
/// document. If FlushDoc finds that the document is dirty, it displays a message
/// asking the user to save the document, discard any changes, or cancel the
/// operation. If the document is not dirty and CanClose returns true, EvCanClose
/// returns true.
//
bool
TDocManager::EvCanClose()
{
  TDocument* doc = 0;
  while ((doc = DocList.Next(doc)) != 0) {
    if (!doc->CanClose())  // normally calls back to FlushDoc()
      return false;
  }
  return true;
}
Example #5
0
//
/// Return pointer to this document or one of its child documents if the spcecified
/// window parameter is a view associated with the document.
/// \note Unlike 'HasFocus', this method allows you to distinguish whether the
/// document with focus is a child document.
//
TDocument*
TDocument::DocWithFocus(HWND hWnd)
{
  TDocument* pdoc = 0;
  while ((pdoc = ChildDoc.Next(pdoc)) != 0)
    if (pdoc->DocWithFocus(hWnd))
      return pdoc;

  return QueryViews(vnIsWindow, (long)hWnd) ? this : 0;
}
Example #6
0
//
/// Checks to see if all child documents can be closed before closing the current
/// document. If any child returns false, CanClose returns false and aborts the
/// process. If all children return true, calls TDocManager::FlushDoc. If FlushDoc
/// finds that the document has been changed but not saved, it displays a message
/// asking the user to either save the document, discard any changes, or cancel the
/// operation. If the document has not been changed and all children's CanClose
/// functions return true, this CanClose function returns true.
//
bool
TDocument::CanClose()
{
  TDocument* pdoc = 0;
  while ((pdoc = ChildDoc.Next(pdoc)) != 0)
    if (!pdoc->CanClose())
      return false;

  return DocManager->FlushDoc(*this);  // do the UI in the doc manager
}
Example #7
0
//
/// Closes the document but does not delete or detach the document. Before closing
/// the document, Close checks any child documents and tries to close them before
/// closing the parent document. Even if you write your own Close function, call
/// TDocument's version to ensure that all child documents are checked before the
/// parent document is closed.
//
bool
TDocument::Close()
{
  TDocument* pdoc = 0;
  while ((pdoc = ChildDoc.Next(pdoc)) != 0)
    if (!pdoc->Close())
      return false;

  return true;
}
Example #8
0
void
TDocManager::FileRevert()
{
  TDocument* doc = GetCurrentDoc();
  if (doc && doc->GetDocPath()) {
    if (!doc->IsDirty()) {
      PostDocError(*doc, IDS_NOTCHANGED);
      return;
    }
    doc->Revert();
  }
}
Example #9
0
//
/// If the document can be closed it is closed.
//
void
TDocManager::FileClose()
{
  TDocument* doc = GetCurrentDoc();
  if (doc && doc->CanClose()) {  // normally calls back to FlushDoc()
    if (!doc->Close())
      PostDocError(*doc, IDS_UNABLECLOSE);
    else
      delete doc;
  }
  WARNX(OwlDocView, !doc, 0, _T("FileClose invoked with no current doc"));
}
Example #10
0
//
/// Saves the current data to storage. When a file is closed, the document manager
/// calls either Commit or Revert. If force is true, all data is written to storage.
/// Commit checks any child documents and commits their changes to storage also.
/// Before the current data is saved, all child documents must return true. If all
/// child documents return true, Commit flushes the views for operations that
/// occurred since the last time the view was checked. After all data for the
/// document is updated and saved, Commit returns true.
//
bool
TDocument::Commit(bool force)
{
  TDocument* pdoc = 0;
  while ((pdoc = ChildDoc.Next(pdoc)) != 0) {
    if (!pdoc->Commit(force))
      return false;
  }

  WARNX(OwlDocView, !DocPath, 0, _T("Commit(): 0 DocPath!"));
  return NotifyViews(vnCommit, force);
}
Example #11
0
//
/// Returns true if the document or one of its views has changed but has not been
/// saved.
//
bool
TDocument::IsDirty()
{
  if (DirtyFlag)
    return true;

  TDocument* pdoc = 0;
  while ((pdoc = ChildDoc.Next(pdoc)) != 0)
    if (pdoc->IsDirty())
      return true;

  return QueryViews(vnIsDirty) != 0;
}
Example #12
0
//
/// SelectAnySave() is called to get a template. Then the Commit() function is called
/// for the current document.
//
void
TDocManager::FileSaveAs()
{
  TDocument* doc = GetCurrentDoc();
  if (doc) {
    TDocTemplate* tpl = SelectAnySave(*doc, true);
    if (tpl) {
      if (tpl != doc->Template)
        doc->SetTemplate(tpl);       // replace existing template
      if (doc->Commit(true))         // force rewrite to new path
        PostEvent(dnRename, *doc); // WM_OWLDOCUMENT
    }
  }
}
Example #13
0
//
/// Returns a pointer to the TDocument object if the specified document
/// is currently opened and manager by the DocManager. Returns 0 otherwise.
//
TDocument*
TDocManager::FindDocument(LPCTSTR path)
{
  TDocument* doc = 0;
  while ((doc = DocList.Next(doc)) != 0)
    if (path) {
      if (doc->GetDocPath() && _tcscmp(doc->GetDocPath(), path) == 0)
        break;
    }
    else {
      if (doc->GetDocPath() == 0)
        break;
    }
  return doc;
}
Example #14
0
void
TDocManager::FileSave()
{
  TDocument* doc = GetCurrentDoc();
  if (doc) {
    if (!doc->GetDocPath()) {
      CmFileSaveAs();
      return;
    }
    if (!(Mode & dmSaveEnable) && !doc->IsDirty()) {
      PostDocError(*doc, IDS_NOTCHANGED);
      return;
    }
    doc->Commit();  // No force of write here since is just to same file
  }
}
Example #15
0
void
TDocument::Streamer::Write(opstream& os) const
{
  TDocument* o = GetObject();

  while (!o->CanClose())   // can't permit cancel here
    ;
  os << o->OpenMode;
  _USES_CONVERSION;
  os.fwriteString(_W2A(o->DocPath));
  os.fwriteString(_W2A(o->Title));
  os << o->Template;       // templates already streamed, must be so if static
  os << o->ParentDoc;
  os << o->ViewList;       // each view streams out the next
  os << TView::NextViewId; // insure that this static var gets set on reload
}
Example #16
0
//
/// Notifies the views of the current document and the views of any child documents
/// of a change. In contrast to QueryViews, NotifyViews sends notification of an
/// event to all views and returns true if all views returned a true result. The
/// event, EV_OWLNOTIFY, is sent with an event code, which is private to the
/// particular document and view class, and a long argument, which can be cast
/// appropriately to the actual type passed in the argument of the response
/// function.
//
bool
TDocument::NotifyViews(int event, long item, TView* exclude)
{
  bool answer = true;

  TDocument* pdoc = 0;
  while ((pdoc = ChildDoc.Next(pdoc)) != 0)
    answer = (answer && pdoc->NotifyViews(event, item, exclude));

  TEventHandler::TEventInfo eventInfo(WM_OWLNOTIFY, event);
  for (TView* view = ViewList; view != 0; view = view->NextView)
    if (view != exclude && view->Find(eventInfo))
      answer = (answer && (view->Dispatch(eventInfo, 0, item) != 0));

  return answer;
}
Example #17
0
//
/// Overrideable method invoked just before the DocumentManager creates a new
/// document. The default behaviour is to close and delete the current
/// document if we're in SDI mode.
//
bool
TDocManager::CreatingDoc(TDocTemplate* /*tpl*/)
{
  if (Mode & dmSDI) {
    TDocument* doc = DocList.Next(0);
    if (doc) {
      if (!doc->CanClose())
        return false;
      if (!doc->Close()) {
        PostDocError(*doc, IDS_UNABLECLOSE);
        return false;
      }
      delete doc;
    }
  }
  return true;
}
Example #18
0
//
/// Displays FileSave dialog prompting the user to select a file name for savinng the document.
/// Filters out read-only files.
//
bool
TDocManager::SelectSave(TDocument& doc)
{
  TDocTemplate* tpl = doc.GetTemplate();

  if (!tpl || !tpl->GetFileFilter())
    return false;

  tchar filepath[_MAX_PATH];
  if (doc.GetDocPath())
    ::_tcscpy(filepath, doc.GetDocPath());
  else
    filepath[0] = 0;    // no initial file path

  int index = SelectDocPath(&tpl, 1, filepath, COUNTOF(filepath), 0, true, &doc);
  return index ? doc.SetDocPath(filepath) : false;
}
Example #19
0
//
/// Queries the views of the current document and the views of any child documents
/// about a specified event, but stops at the first view that returns true. In
/// contrast to NotifyViews(), QueryViews returns a pointer to the first view that
/// responded to an event with a true result. The event, EV_OWLNOTIFY, is sent with
/// an event code (which is private to the particular document and view class) and a
/// long argument (which can be cast appropriately to the actual type passed in the
/// argument of the response function).
//
TView*
TDocument::QueryViews(int event, long item, TView* exclude)
{
  TView* view;
  TDocument* pdoc = 0;
  while ((pdoc = ChildDoc.Next(pdoc)) != 0)
    if ((view = pdoc->QueryViews(event, item, exclude)) != 0)
      return view;

  TEventHandler::TEventInfo eventInfo(WM_OWLNOTIFY, event);
  for (view = ViewList; view != 0; view = view->NextView) {
    if (view != exclude) {
      if (view->Find(eventInfo)) {
        if (view->Dispatch(eventInfo, 0, item)) {
          return view;            // Return first acknowledger
        }
      }
    }
  }
  return 0;
}
Example #20
0
//
/// CreateDoc creates a document based on the directory path and the specified
/// template. The flags parameter contains one of the document template constants
/// that determines how the document is created.
//
TDocument*
TDocManager::CreateDoc(TDocTemplate* tpl, LPCTSTR path,
                       TDocument* parent, long flags)
{
  if (!tpl) {
    TRACEX(OwlDocView, 0, _T("CreateDoc(): NULL template specified!"));
    return 0;
  }

  // Creation step 0: Inform docmanager that we're about to create a document
  // and allow docmanager to veto
  //
  if (!CreatingDoc(tpl)) {
    TRACEX(OwlDocView, 1, _T("CreateDoc(): Creation vetoed."));
    return 0;
  }

  // Creation step 1: Construct the document, passing in the parent document
  // Put together a dummy parent document if no parent doc was specified in
  // order to allow us to pass in the DocManager pointer hidden in the parent
  // doc
  //
  TDocument* doc;
  if (!parent){
    TDocument td(this);
     doc = tpl->ConstructDoc(&td);
  }
  else
    doc = tpl->ConstructDoc(parent);

  if (!doc) {
    TRACEX(OwlDocView, 0, _T("CreateDoc(): ConstructDoc call failed"));
    return 0;
  }

  // Creation step2: Initialize the document
  //
  doc->SetTemplate(tpl);
  return InitDoc(doc, path, flags);
}
Example #21
0
//
/// Calls TWindow::GetFocus() to determine the window with the focus. Searches the
/// list of documents and returns the document that contains the view with the
/// focus. Returns 0 if no document has a view with focus.
//
TDocument*
TDocManager::GetCurrentDoc()
{
  PRECONDITION(GetApplication());
  PRECONDITION(GetApplication()->GetMainWindow());

  HWND hWnd = GetApplication()->GetMainWindow()->GetCommandTarget();
  TDocument* doc = 0;

#if defined(OLD_DOCVIEW)
  // !BB This older implementation of GetCurrentDoc relies on the
  // !BB document's HasFocus method which does not allow 'GetCurrentDoc'
  // !BB to return child documents....
  // !BB
  // !BB This obviously causes some problems (for example, closing a view
  // !BB associated with a child document closes the whole document and
  // !BB all their associated views!).
  // !BB
  // !BB However is there code that relies on this behaviour - Investigate
  // !BB

  if (hWnd && ::IsWindow(hWnd)) {
    while ((doc = DocList.Next(doc)) != 0 && !doc->HasFocus(hWnd))
      ;
  }

#else
  if (hWnd && ::IsWindow(hWnd)) {
    while ((doc = DocList.Next(doc)) != 0 ) {
      TDocument* childDoc = doc->DocWithFocus(hWnd);
      if (childDoc) {
        doc = childDoc;
        break;
      }
    }
  }
#endif
  return doc;
}
Example #22
0
int
TDocManager::GetViewTemplates(TDocTemplate** tplList, int size,
                              TDocument& doc)
#endif
{
  // Check for no registered templates
  //
  if (!TemplateList) {
    TRACEX(OwlDocView, 0, _T("GetViewTemplates(): No registered templates!"));
    return 0;
  }

  // Grab a list of templates for creating views
  //
  int tplCount = 0;
  for (TDocTemplate* tpl = TemplateList; tpl; tpl = tpl->GetNextTemplate()) {
    if (tpl->IsMyKindOfDoc(doc)) {

      // Don't grab the same view more than once
      //
      LPCTSTR viewName = tpl->GetViewName();
      int index;
      for (index = 0; index < tplCount; index++) {
        if (tplList[index]->GetViewName() == viewName)
          break;
      }

      // Skip a view if the document already has one and the template
      // specifies 'SingleView'.
      //
      if (tpl->IsFlagSet(dtSingleView)) {
        TView* pview = 0;
        while ((pview = doc.NextView(pview)) != 0)
          if (tpl->IsMyKindOfView(*pview))
            index = -1;
      }

      // Store the template if we have a match...
      //
      if (index == tplCount) {

        CHECK(tplList);
        CHECK(tplCount < size);

        tplList[tplCount++] = tpl;
      }
    }
  }
  return tplCount;
}
Example #23
0
//
/// Displays a message box with the error message passed as a string resource ID in
/// sid. By default, the message box contains either an OK push button or a question
/// mark icon. If an error message can't be found, PostDocError displays a "Message
/// not found" message. choice can be one or more of the MB_Xxxx message  style
/// constants. This function can be overridden.
///
/// Returns an integer
/// identifying the MessageBox option (push-button) selected by the user.
//
uint
TDocManager::PostDocError(TDocument& doc, uint sid, uint choice)
{
  PRECONDITION(GetApplication());
  PRECONDITION(GetApplication()->GetMainWindow());

  tchar buf[256];
  if (GetApplication()->LoadString(sid, buf, sizeof(buf) / sizeof(tchar)) == 0)
#if BI_MSG_LANGUAGE == 0x0411
    _stprintf(buf, "エラー: 文字列 ID %u が見つかりません", sid);
#else
    _stprintf(buf, _T("Error: Message [string ID %u] not found"), sid);
#endif

  if (choice != MB_OK)
    choice |= MB_ICONQUESTION;
  return GetApplication()->GetMainWindow()->MessageBox(buf, doc.GetTitle(), choice);
}
Example #24
0
//
/// Given a list of templates, prompts the user to select one of the templates to use for the file to be
/// opened. Returns the template index used for the selection, or 0 if unsuccessful.
/// For a file open operation, save is false. For a file save operation, save is
/// true. This function can be overridden to provide a customized user interface.
///
/// \note This is Windows-specific, using the system-provided file open dialog box
//
int
TDocManager::SelectDocPath(TDocTemplate** tpllist, int tplcount,
                           LPTSTR path, int buflen, long flags,
                           bool save, TDocument* doc)
{
  // Compute length of description(s) and filter(s)
  //
  int len = GetTemplateDescription(tpllist, tplcount);

  // Put together a string of description and filters
  //
  TAPointer<tchar> filtbuf(new tchar[++len]);
  GetTemplateDescription(tpllist, tplcount, filtbuf, len);

  // Find the (default) template to select
  //
  int index, count;
  TDocument* curDoc = save ? (doc ? doc : GetCurrentDoc()) : 0;
  CHECK(!save || curDoc);
  if (save) {
    for (index = count = 0; count < tplcount; count++) {
      if (tpllist[count] == curDoc->GetTemplate()) {
        index = count;
        break;
      }
    }
  }
  else {
    for (index = count = 0; count < tplcount; count++) {
      if (tpllist[count]->IsFlagSet(dtSelected)) {
        index = count;
        break;
      }
    }
  }

  // Initialize data structure used for launching Common Dialog
  //
  flags = (tpllist[index]->GetFlags() | flags);
  flags &= 0x000FFFFF; // Clear Doc/View related flags.
  flags |= AdditionalFileDialogFlags; // Add extended flags, e.g. OFN_ENABLESIZING.
  flags &= ~dtProhibited; // Clear unsupported flags, e.g. OFN_ENABLETEMPLATE.
  TDvOpenSaveData data(flags,                             // flags
                       filtbuf,                           // filter
     CONST_CAST(LPTSTR, tpllist[index]->GetDirectory()),  // initDir.
     CONST_CAST(LPTSTR, tpllist[index]->GetDefaultExt()), // defExt.
                       index ? index+1 : 0,               // filterIndex
                       tpllist,                           // template list
                       tplcount);                         // template count

  //--- Sirma (Krasi)
  {
    LPCTSTR fName = path && *path ? path : (doc ? doc->GetTitle() : 0);
    if (fName && *fName)
      _tcsncpy(data.FileName, fName, buflen);
  }
  //--- Sirma (Krasi) ---

  // Execute dialog
  //
  int result;
  TWindow* parent = GetApplication()->GetMainWindow();
  if (save)
    result = TDvFileSaveDialog(parent, data).Execute();
  else
    result = TDvFileOpenDialog(parent, data).Execute();

  // Dialog was cancelled!
  //
  if (result != IDOK) {
    WARNX(OwlDocView, data.Error != 0, 0, _T("Common dialog error: ") << \
                      data.Error << _T(" in SelectDocPath()") );
    return 0;
  }
  // !BB
  // Here, there's a major dilemma! How, do we know the user did not
  // mislead us? For example, the user may have selected the *wrong*
  // template for saving a particular document... This is crucial when
  // saving documents!!!
  //

  // Update templates to 'remember' the template last used
  //
  for (count = 0; count < tplcount; count++) {
    if (count == index-1)
      tpllist[count]->SetFlag(dtSelected);
    else
      tpllist[count]->ClearFlag(dtSelected);
  }

  // Update selected template with directory
  //
  // // !BB Yeah! Where's the meat?


  // Copy file name over
  //
  CHECK(path);
  if (data.FileName && data.FileName[0]) {
    WARNX(OwlDocView, ::_tcslen(data.FileName) < (size_t)buflen, 0,
          _T("SelectDocPath: Specified buffer is too small"));
    _tcsncpy(path, data.FileName, buflen);
  }
  else
    *path = 0;

  // Return index [1-based] of selected template
  //
  CHECK(data.FilterIndex >= 1);
  CHECK(data.FilterIndex <= tplcount);
  return data.FilterIndex;
}
Example #25
0
//
/// Command enabler for CmFileSave.
//
void
TDocManager::CeFileSave(TCommandEnabler& ce)
{
  TDocument* doc = GetCurrentDoc();
  ce.Enable(doc && (doc->IsDirty() || (Mode & dmSaveEnable)));
}
Example #26
0
//
/// Command enabler for CmFileRevert.
//
void
TDocManager::CeFileRevert(TCommandEnabler& ce)
{
  TDocument* doc = GetCurrentDoc();
  ce.Enable(doc && doc->IsDirty() && doc->GetDocPath());
}
Example #27
0
//
/// Method invoked when specified document is about to be closed.
/// Updates the document with any changes and prompts the user for confirmation of
/// updates.
/// Returns 'true' if DocManager should proceed with the closing
/// stages of the document, or 'false' otherwise.
//
bool
TDocManager::FlushDoc(TDocument& doc)
{
  while (doc.IsDirty()) {
    int saveOrNot = doc.IsEmbedded() ?
                      IDYES :
                      PostDocError(doc, IDS_DOCCHANGED, MB_YESNOCANCEL);

    switch (saveOrNot) {
      case IDYES:
        // Prompt the user for filename in save-as situation
        //
        if (!doc.IsEmbedded() && doc.GetDocPath() == 0) {

        // !BB
        // !BB It does not make sense to invoke SelectAnySave
        // !BB with false here... This would allow the user
        // !BB to switch to any available template when saving the
        // !BB document. In other words, a user would be allowed to
        // !BB save a .TXT file as a .PTS file although they are
        // !BB not related whatsoever...
        // !BB
        // !BB I'm switching this to use true - let me know if you
        // !BB know of a reason for the prior behaviour.
        // !BB

#if defined(OLD_DOCVIEW)
          TDocTemplate* tpl = SelectAnySave(doc, false);
#else
          TDocTemplate* tpl = SelectAnySave(doc, true);
#endif
          if (!tpl)
            continue;

          // !BB
          // !BB The following is suspicious: Is there a reason
          // !BB to allow the user to switch the template in the first
          // !BB place?? OK, if everyone agrees that same TDocument-derived
          // !BB type implies compatible document, that would be OK.
          // !BB However, that's not what we've encouraged. Our own
          // !BB examples use the same TFileDocument for incompatible
          // !BB document types. Hence, if an app. has a
          // !BB TBitmapView/TFileDocument and a TTextView/TFileDocument pair,
          // !BB the following would allow the user to save a text file as a .BMP
          // !BB Ack!!
          // !BB If the following is really the intent, then DV users must be
          // !BB conscious that they will more often than not be using TFileDocument-
          // !BB derived documents as a method to specify compatible and incompatible
          // !BB document types.
          //
          if (tpl != doc.Template)
            doc.SetTemplate(tpl);
        }
        if (doc.Commit())
          return true;
        continue;

      case IDNO:
        if (doc.Revert(true))
          return true;
        return false;

      case IDCANCEL:
        return false;
    }
  }
  return true;
}