1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/filehistorycmn.cpp
3 // Purpose: wxFileHistory class
4 // Author: Julian Smart, Vaclav Slavik, Vadim Zeitlin
7 // Copyright: (c) Julian Smart
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 // ============================================================================
13 // ============================================================================
15 // ----------------------------------------------------------------------------
17 // ----------------------------------------------------------------------------
19 // For compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
26 #include "wx/filehistory.h"
28 #if wxUSE_FILE_HISTORY
31 #include "wx/confbase.h"
32 #include "wx/filename.h"
34 // ============================================================================
36 // ============================================================================
38 // ----------------------------------------------------------------------------
40 // ----------------------------------------------------------------------------
45 // return the string used for the MRU list items in the menu
47 // NB: the index n is 0-based, as usual, but the strings start from 1
48 wxString
GetMRUEntryLabel(int n
, const wxString
& path
)
50 // we need to quote '&' characters which are used for mnemonics
51 wxString
pathInMenu(path
);
52 pathInMenu
.Replace("&", "&&");
54 return wxString::Format("&%d %s", n
+ 1, pathInMenu
);
57 } // anonymous namespace
59 // ----------------------------------------------------------------------------
60 // File history (a.k.a. MRU, most recently used, files list)
61 // ----------------------------------------------------------------------------
63 IMPLEMENT_DYNAMIC_CLASS(wxFileHistory
, wxObject
)
65 wxFileHistoryBase::wxFileHistoryBase(size_t maxFiles
, wxWindowID idBase
)
67 m_fileMaxFiles
= maxFiles
;
71 void wxFileHistoryBase::AddFileToHistory(const wxString
& file
)
73 // check if we don't already have this file
74 const wxFileName
fnNew(file
);
76 numFiles
= m_fileHistory
.size();
77 for ( i
= 0; i
< numFiles
; i
++ )
79 if ( fnNew
== m_fileHistory
[i
] )
81 // we do have it, move it to the top of the history
82 RemoveFileFromHistory(i
);
88 // if we already have a full history, delete the one at the end
89 if ( numFiles
== m_fileMaxFiles
)
91 RemoveFileFromHistory(--numFiles
);
94 // add a new menu item to all file menus (they will be updated below)
95 for ( wxList::compatibility_iterator node
= m_fileMenus
.GetFirst();
97 node
= node
->GetNext() )
99 wxMenu
* const menu
= (wxMenu
*)node
->GetData();
101 if ( !numFiles
&& menu
->GetMenuItemCount() )
102 menu
->AppendSeparator();
104 // label doesn't matter, it will be set below anyhow, but it can't
105 // be empty (this is supposed to indicate a stock item)
106 menu
->Append(m_idBase
+ numFiles
, " ");
109 // insert the new file in the beginning of the file history
110 m_fileHistory
.insert(m_fileHistory
.begin(), file
);
113 // update the labels in all menus
114 for ( i
= 0; i
< numFiles
; i
++ )
116 // if in same directory just show the filename; otherwise the full path
117 const wxFileName
fnOld(m_fileHistory
[i
]);
120 if ( fnOld
.GetPath() == fnNew
.GetPath() )
122 pathInMenu
= fnOld
.GetFullName();
124 else // file in different directory
126 // absolute path; could also set relative path
127 pathInMenu
= m_fileHistory
[i
];
130 for ( wxList::compatibility_iterator node
= m_fileMenus
.GetFirst();
132 node
= node
->GetNext() )
134 wxMenu
* const menu
= (wxMenu
*)node
->GetData();
136 menu
->SetLabel(m_idBase
+ i
, GetMRUEntryLabel(i
, pathInMenu
));
141 void wxFileHistoryBase::RemoveFileFromHistory(size_t i
)
143 size_t numFiles
= m_fileHistory
.size();
144 wxCHECK_RET( i
< numFiles
,
145 wxT("invalid index in wxFileHistoryBase::RemoveFileFromHistory") );
147 // delete the element from the array
148 m_fileHistory
.RemoveAt(i
);
151 for ( wxList::compatibility_iterator node
= m_fileMenus
.GetFirst();
153 node
= node
->GetNext() )
155 wxMenu
* const menu
= (wxMenu
*) node
->GetData();
157 // shift filenames up
158 for ( size_t j
= i
; j
< numFiles
; j
++ )
160 menu
->SetLabel(m_idBase
+ j
, GetMRUEntryLabel(j
, m_fileHistory
[j
]));
163 // delete the last menu item which is unused now
164 const wxWindowID lastItemId
= m_idBase
+ numFiles
;
165 if ( menu
->FindItem(lastItemId
) )
166 menu
->Delete(lastItemId
);
168 // delete the last separator too if no more files are left
169 if ( m_fileHistory
.empty() )
171 const wxMenuItemList::compatibility_iterator
172 nodeLast
= menu
->GetMenuItems().GetLast();
175 wxMenuItem
* const lastMenuItem
= nodeLast
->GetData();
176 if ( lastMenuItem
->IsSeparator() )
177 menu
->Delete(lastMenuItem
);
179 //else: menu is empty somehow
184 void wxFileHistoryBase::UseMenu(wxMenu
*menu
)
186 if ( !m_fileMenus
.Member(menu
) )
187 m_fileMenus
.Append(menu
);
190 void wxFileHistoryBase::RemoveMenu(wxMenu
*menu
)
192 m_fileMenus
.DeleteObject(menu
);
196 void wxFileHistoryBase::Load(const wxConfigBase
& config
)
198 m_fileHistory
.Clear();
201 buf
.Printf(wxT("file%d"), 1);
203 wxString historyFile
;
204 while ((m_fileHistory
.GetCount() < m_fileMaxFiles
) &&
205 config
.Read(buf
, &historyFile
) && !historyFile
.empty())
207 m_fileHistory
.Add(historyFile
);
209 buf
.Printf(wxT("file%d"), (int)m_fileHistory
.GetCount()+1);
210 historyFile
= wxEmptyString
;
216 void wxFileHistoryBase::Save(wxConfigBase
& config
)
219 for (i
= 0; i
< m_fileMaxFiles
; i
++)
222 buf
.Printf(wxT("file%d"), (int)i
+1);
223 if (i
< m_fileHistory
.GetCount())
224 config
.Write(buf
, wxString(m_fileHistory
[i
]));
226 config
.Write(buf
, wxEmptyString
);
229 #endif // wxUSE_CONFIG
231 void wxFileHistoryBase::AddFilesToMenu()
233 if ( m_fileHistory
.empty() )
236 for ( wxList::compatibility_iterator node
= m_fileMenus
.GetFirst();
238 node
= node
->GetNext() )
240 AddFilesToMenu((wxMenu
*) node
->GetData());
244 void wxFileHistoryBase::AddFilesToMenu(wxMenu
* menu
)
246 if ( m_fileHistory
.empty() )
249 if ( menu
->GetMenuItemCount() )
250 menu
->AppendSeparator();
252 for ( size_t i
= 0; i
< m_fileHistory
.GetCount(); i
++ )
254 menu
->Append(m_idBase
+ i
, GetMRUEntryLabel(i
, m_fileHistory
[i
]));
258 #endif // wxUSE_FILE_HISTORY