// Modified by:
// Created: 01/02/97
// RCS-ID: $Id$
-// Copyright: (c) Julian Smart and Markus Holzem
+// Copyright: (c) Julian Smart
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#include "wx/filedlg.h"
#include "wx/intl.h"
#include "wx/log.h"
- #include "wx/ffile.h"
#endif
+#include "wx/ffile.h"
+
#ifdef __WXMAC__
#include "wx/filename.h"
#endif
// ----------------------------------------------------------------------------
static inline wxString FindExtension(const wxChar *path);
+static wxWindow* wxFindSuitableParent(void);
// ----------------------------------------------------------------------------
// local constants
SetFilename(fileName);
SetTitle(wxFileNameFromPath(fileName));
- GetDocumentManager()->AddFileToHistory(fileName);
-
// Notify the views that the filename has changed
wxNode *node = m_documentViews.GetFirst();
while (node)
node = node->GetNext();
}
- return OnSaveDocument(m_documentFile);
+ // Files that were not saved correctly are not added to the FileHistory.
+ if (!OnSaveDocument(m_documentFile))
+ return FALSE;
+
+ // A file that doesn't use the default extension of its document template cannot be opened
+ // via the FileHistory, so we do not add it.
+ if (docTemplate->FileMatchesTemplate(fileName))
+ {
+ GetDocumentManager()->AddFileToHistory(fileName);
+ }
+ else
+ {
+ // The user will probably not be able to open the file again, so
+ // we could warn about the wrong file-extension here.
+ }
+ return TRUE;
}
bool wxDocument::OnSaveDocument(const wxString& file)
sm_docManager = (wxDocManager*) NULL;
}
+// closes the specified document
+bool wxDocManager::CloseDocument(wxDocument* doc, bool force)
+{
+ if (doc->Close() || force)
+ {
+ // Implicitly deletes the document when
+ // the last view is deleted
+ doc->DeleteAllViews();
+
+ // Check we're really deleted
+ if (m_docs.Member(doc))
+ delete doc;
+
+ return TRUE;
+ }
+ return FALSE;
+}
+
bool wxDocManager::CloseDocuments(bool force)
{
wxNode *node = m_docs.GetFirst();
{
wxDocument *doc = (wxDocument *)node->GetData();
wxNode *next = node->GetNext();
-
- if (!doc->Close() && !force)
+
+ if (!CloseDocument(doc, force))
return FALSE;
- // Implicitly deletes the document when the last
- // view is removed (deleted)
- doc->DeleteAllViews();
-
- // Check document is deleted
- if (m_docs.Member(doc))
- delete doc;
-
// This assumes that documents are not connected in
// any way, i.e. deleting one document does NOT
// delete another.
#endif // wxUSE_PRINTING_ARCHITECTURE
}
-void wxDocManager::OnUndo(wxCommandEvent& WXUNUSED(event))
+void wxDocManager::OnUndo(wxCommandEvent& event)
{
wxDocument *doc = GetCurrentDocument();
if (!doc)
return;
if (doc->GetCommandProcessor())
doc->GetCommandProcessor()->Undo();
+ else
+ event.Skip();
}
-void wxDocManager::OnRedo(wxCommandEvent& WXUNUSED(event))
+void wxDocManager::OnRedo(wxCommandEvent& event)
{
wxDocument *doc = GetCurrentDocument();
if (!doc)
return;
if (doc->GetCommandProcessor())
doc->GetCommandProcessor()->Redo();
+ else
+ event.Skip();
}
// Handlers for UI update commands
void wxDocManager::OnUpdateUndo(wxUpdateUIEvent& event)
{
wxDocument *doc = GetCurrentDocument();
- event.Enable( (doc && doc->GetCommandProcessor() && doc->GetCommandProcessor()->CanUndo()) );
- if (doc && doc->GetCommandProcessor())
+ if (!doc)
+ event.Enable(FALSE);
+ else if (!doc->GetCommandProcessor())
+ event.Skip();
+ else
+ {
+ event.Enable( doc->GetCommandProcessor()->CanUndo() );
doc->GetCommandProcessor()->SetMenuStrings();
+ }
}
void wxDocManager::OnUpdateRedo(wxUpdateUIEvent& event)
{
wxDocument *doc = GetCurrentDocument();
- event.Enable( (doc && doc->GetCommandProcessor() && doc->GetCommandProcessor()->CanRedo()) );
- if (doc && doc->GetCommandProcessor())
+ if (!doc)
+ event.Enable(FALSE);
+ else if (!doc->GetCommandProcessor())
+ event.Skip();
+ else
+ {
+ event.Enable( doc->GetCommandProcessor()->CanRedo() );
doc->GetCommandProcessor()->SetMenuStrings();
+ }
}
void wxDocManager::OnUpdatePrint(wxUpdateUIEvent& event)
delete[] templates;
return (wxDocument *) NULL;
}
+
+ wxDocument* docToClose = NULL;
// If we've reached the max number of docs, close the
// first one.
if ( (int)GetDocuments().GetCount() >= m_maxDocsOpen )
{
wxDocument *doc = (wxDocument *)GetDocuments().GetFirst()->GetData();
- if (doc->Close())
- {
- // Implicitly deletes the document when
- // the last view is deleted
- doc->DeleteAllViews();
-
- // Check we're really deleted
- if (m_docs.Member(doc))
- delete doc;
- }
- else
- {
- delete[] templates;
- return (wxDocument *) NULL;
- }
+ docToClose = doc;
}
// New document: user chooses a template, unless there's only one.
{
if (n == 1)
{
+ if (docToClose)
+ {
+ if (!CloseDocument(docToClose, FALSE))
+ {
+ delete[] templates;
+ return NULL;
+ }
+ }
+
wxDocTemplate *temp = templates[0];
delete[] templates;
wxDocument *newDoc = temp->CreateDocument(path, flags);
+
if (newDoc)
{
newDoc->SetDocumentName(temp->GetDocumentName());
delete[] templates;
if (temp)
{
+ if (docToClose)
+ {
+ if (!CloseDocument(docToClose, FALSE))
+ {
+ return NULL;
+ }
+ }
+
wxDocument *newDoc = temp->CreateDocument(path, flags);
+
if (newDoc)
{
newDoc->SetDocumentName(temp->GetDocumentName());
path2 = path;
if (flags & wxDOC_SILENT)
+ {
temp = FindTemplateForPath(path2);
+ if (!temp)
+ {
+ // Since we do not add files with non-default extensions to the FileHistory this
+ // can only happen if the application changes the allowed templates in runtime.
+ (void)wxMessageBox(_("Sorry, the format for this file is unknown."),
+ _("Open File"),
+ wxOK | wxICON_EXCLAMATION, wxFindSuitableParent());
+ }
+ }
else
temp = SelectDocumentPath(templates, n, path2, flags);
if (temp)
{
+ if (docToClose)
+ {
+ if (!CloseDocument(docToClose, FALSE))
+ {
+ return NULL;
+ }
+ }
+
wxDocument *newDoc = temp->CreateDocument(path2, flags);
if (newDoc)
{
// delete newDoc; // Implicitly deleted by DeleteAllViews
return (wxDocument *) NULL;
}
- AddFileToHistory(path2);
+ // A file that doesn't use the default extension of its document
+ // template cannot be opened via the FileHistory, so we do not
+ // add it.
+ if (temp->FileMatchesTemplate(path2))
+ AddFileToHistory(path2);
}
return newDoc;
}
m_fileHistory->AddFileToHistory(file);
}
-void wxDocManager::RemoveFileFromHistory(int i)
+void wxDocManager::RemoveFileFromHistory(size_t i)
{
if (m_fileHistory)
m_fileHistory->RemoveFileFromHistory(i);
}
-wxString wxDocManager::GetHistoryFile(int i) const
+wxString wxDocManager::GetHistoryFile(size_t i) const
{
wxString histFile;
m_fileHistory->AddFilesToMenu();
}
-int wxDocManager::GetNoHistoryFiles() const
+size_t wxDocManager::GetHistoryFilesCount() const
{
- if (m_fileHistory)
- return m_fileHistory->GetNoHistoryFiles();
- else
- return 0;
+ return m_fileHistory ? m_fileHistory->GetCount() : 0;
}
}
// Prompts user to open a file, using file specs in templates.
-// How to implement in wxWindows? Must extend the file selector
-// dialog or implement own; OR match the extension to the
-// template extension.
+// Must extend the file selector dialog or implement own; OR
+// match the extension to the template extension.
wxDocTemplate *wxDocManager::SelectDocumentPath(wxDocTemplate **templates,
#if defined(__WXMSW__) || defined(__WXGTK__) || defined(__WXMAC__)
theTemplate = templates[FilterIndex];
if ( !theTemplate )
theTemplate = FindTemplateForPath(path);
+ if ( !theTemplate )
+ {
+ // Since we do not add files with non-default extensions to the FileHistory this
+ // can only happen if the application changes the allowed templates in runtime.
+ (void)wxMessageBox(_("Sorry, the format for this file is unknown."),
+ _("Open File"),
+ wxOK | wxICON_EXCLAMATION, wxFindSuitableParent());
+ }
}
else
{
if ( wxFile::Exists(filename) )
{
// try to open it
- (void)m_docManager->CreateDocument(filename, wxDOC_SILENT);
+ if (!m_docManager->CreateDocument(filename, wxDOC_SILENT))
+ {
+ // remove the file from the MRU list. The user should already be notified.
+ m_docManager->RemoveFileFromHistory(n);
+
+ wxLogError(_("The file '%s' couldn't be opened.\nIt has been removed from the most recently used files list."),
+ filename.c_str());
+ }
}
else
{
// File history processor
// ----------------------------------------------------------------------------
-wxFileHistory::wxFileHistory(int maxFiles)
+static inline wxChar* MYcopystring(const wxString& s)
+{
+ wxChar* copy = new wxChar[s.length() + 1];
+ return wxStrcpy(copy, s.c_str());
+}
+
+static inline wxChar* MYcopystring(const wxChar* s)
+{
+ wxChar* copy = new wxChar[wxStrlen(s) + 1];
+ return wxStrcpy(copy, s);
+}
+
+wxFileHistory::wxFileHistory(size_t maxFiles, wxWindowID idBase)
{
m_fileMaxFiles = maxFiles;
+ m_idBase = idBase;
m_fileHistoryN = 0;
m_fileHistory = new wxChar *[m_fileMaxFiles];
}
wxFileHistory::~wxFileHistory()
{
- int i;
+ size_t i;
for (i = 0; i < m_fileHistoryN; i++)
delete[] m_fileHistory[i];
delete[] m_fileHistory;
// File history management
void wxFileHistory::AddFileToHistory(const wxString& file)
{
- int i;
+ size_t i;
// Check we don't already have this file
for (i = 0; i < m_fileHistoryN; i++)
{
- if ( m_fileHistory[i] && (file == m_fileHistory[i]) )
+#if defined( __WXMSW__ ) // Add any other OSes with case insensitive file names
+ wxString testString;
+ if ( m_fileHistory[i] )
+ testString = m_fileHistory[i];
+ if ( m_fileHistory[i] && ( file.Lower() == testString.Lower() ) )
+#else
+ if ( m_fileHistory[i] && ( file == m_fileHistory[i] ) )
+#endif
{
// we do have it, move it to the top of the history
RemoveFileFromHistory (i);
{
menu->AppendSeparator();
}
- menu->Append(wxID_FILE1+m_fileHistoryN, _("[EMPTY]"));
+ menu->Append(m_idBase+m_fileHistoryN, _("[EMPTY]"));
node = node->GetNext();
}
m_fileHistoryN ++;
{
m_fileHistory[i] = m_fileHistory[i-1];
}
- m_fileHistory[0] = copystring(file);
+ m_fileHistory[0] = MYcopystring(file);
// this is the directory of the last opened file
wxString pathCurrent;
while (node)
{
wxMenu* menu = (wxMenu*) node->GetData();
- menu->SetLabel(wxID_FILE1 + i, buf);
+ menu->SetLabel(m_idBase + i, buf);
node = node->GetNext();
}
}
}
}
-void wxFileHistory::RemoveFileFromHistory(int i)
+void wxFileHistory::RemoveFileFromHistory(size_t i)
{
wxCHECK_RET( i < m_fileHistoryN,
wxT("invalid index in wxFileHistory::RemoveFileFromHistory") );
- // delete the element from the array (could use memmove() too...)
- delete [] m_fileHistory[i];
+ // delete the element from the array (could use memmove() too...)
+ delete [] m_fileHistory[i];
- int j;
- for ( j = i; j < m_fileHistoryN - 1; j++ )
- {
- m_fileHistory[j] = m_fileHistory[j + 1];
- }
+ size_t j;
+ for ( j = i; j < m_fileHistoryN - 1; j++ )
+ {
+ m_fileHistory[j] = m_fileHistory[j + 1];
+ }
wxNode* node = m_fileMenus.GetFirst();
while ( node )
{
- wxMenu* menu = (wxMenu*) node->GetData();
-
+ wxMenu* menu = (wxMenu*) node->GetData();
- // shuffle filenames up
- wxString buf;
- for ( j = i; j < m_fileHistoryN - 1; j++ )
- {
- buf.Printf(s_MRUEntryFormat, j + 1, m_fileHistory[j]);
- menu->SetLabel(wxID_FILE1 + j, buf);
- }
+ // shuffle filenames up
+ wxString buf;
+ for ( j = i; j < m_fileHistoryN - 1; j++ )
+ {
+ buf.Printf(s_MRUEntryFormat, j + 1, m_fileHistory[j]);
+ menu->SetLabel(m_idBase + j, buf);
+ }
- node = node->GetNext();
+ node = node->GetNext();
// delete the last menu item which is unused now
- if (menu->FindItem(wxID_FILE1 + m_fileHistoryN - 1))
- menu->Delete(wxID_FILE1 + m_fileHistoryN - 1);
+ wxWindowID lastItemId = m_idBase + m_fileHistoryN - 1;
+ if (menu->FindItem(lastItemId))
+ {
+ menu->Delete(lastItemId);
+ }
// delete the last separator too if no more files are left
if ( m_fileHistoryN == 1 )
m_fileHistoryN--;
}
-wxString wxFileHistory::GetHistoryFile(int i) const
+wxString wxFileHistory::GetHistoryFile(size_t i) const
{
wxString s;
if ( i < m_fileHistoryN )
{
m_fileHistoryN = 0;
wxString buf;
- buf.Printf(wxT("file%d"), m_fileHistoryN+1);
+ buf.Printf(wxT("file%d"), (int)m_fileHistoryN+1);
wxString historyFile;
while ((m_fileHistoryN < m_fileMaxFiles) && config.Read(buf, &historyFile) && (historyFile != wxT("")))
{
- m_fileHistory[m_fileHistoryN] = copystring((const wxChar*) historyFile);
+ m_fileHistory[m_fileHistoryN] = MYcopystring((const wxChar*) historyFile);
m_fileHistoryN ++;
- buf.Printf(wxT("file%d"), m_fileHistoryN+1);
+ buf.Printf(wxT("file%d"), (int)m_fileHistoryN+1);
historyFile = wxT("");
}
AddFilesToMenu();
void wxFileHistory::Save(wxConfigBase& config)
{
- int i;
- for (i = 0; i < m_fileHistoryN; i++)
+ size_t i;
+ for (i = 0; i < m_fileMaxFiles; i++)
{
wxString buf;
- buf.Printf(wxT("file%d"), i+1);
- config.Write(buf, wxString(m_fileHistory[i]));
+ buf.Printf(wxT("file%d"), (int)i+1);
+ if (i < m_fileHistoryN)
+ config.Write(buf, wxString(m_fileHistory[i]));
+ else
+ config.Write(buf, wxEmptyString);
}
}
#endif // wxUSE_CONFIG
menu->AppendSeparator();
}
- int i;
+ size_t i;
for (i = 0; i < m_fileHistoryN; i++)
{
if (m_fileHistory[i])
{
wxString buf;
buf.Printf(s_MRUEntryFormat, i+1, m_fileHistory[i]);
- menu->Append(wxID_FILE1+i, buf);
+ menu->Append(m_idBase+i, buf);
}
}
node = node->GetNext();
menu->AppendSeparator();
}
- int i;
+ size_t i;
for (i = 0; i < m_fileHistoryN; i++)
{
if (m_fileHistory[i])
{
wxString buf;
buf.Printf(s_MRUEntryFormat, i+1, m_fileHistory[i]);
- menu->Append(wxID_FILE1+i, buf);
+ menu->Append(m_idBase+i, buf);
}
}
}