]> git.saurik.com Git - wxWidgets.git/blame - src/common/filehistorycmn.cpp
Merge in from trunk r64802 - r68625
[wxWidgets.git] / src / common / filehistorycmn.cpp
CommitLineData
a0219e45
VS
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/common/filehistorycmn.cpp
3// Purpose: wxFileHistory class
4// Author: Julian Smart, Vaclav Slavik, Vadim Zeitlin
5// Created: 2010-05-03
6// RCS-ID: $Id$
7// Copyright: (c) Julian Smart
8// Licence: wxWindows licence
9/////////////////////////////////////////////////////////////////////////////
10
11// ============================================================================
12// declarations
13// ============================================================================
14
15// ----------------------------------------------------------------------------
16// headers
17// ----------------------------------------------------------------------------
18
19// For compilers that support precompilation, includes "wx.h".
20#include "wx/wxprec.h"
21
22#ifdef __BORLANDC__
23 #pragma hdrstop
24#endif
25
26#include "wx/filehistory.h"
27
28#if wxUSE_FILE_HISTORY
29
30#include "wx/menu.h"
31#include "wx/confbase.h"
32#include "wx/filename.h"
33
34// ============================================================================
35// implementation
36// ============================================================================
37
38// ----------------------------------------------------------------------------
39// private helpers
40// ----------------------------------------------------------------------------
41
42namespace
43{
44
45// return the string used for the MRU list items in the menu
46//
47// NB: the index n is 0-based, as usual, but the strings start from 1
48wxString GetMRUEntryLabel(int n, const wxString& path)
49{
50 // we need to quote '&' characters which are used for mnemonics
51 wxString pathInMenu(path);
52 pathInMenu.Replace("&", "&&");
53
54 return wxString::Format("&%d %s", n + 1, pathInMenu);
55}
56
57} // anonymous namespace
58
59// ----------------------------------------------------------------------------
60// File history (a.k.a. MRU, most recently used, files list)
61// ----------------------------------------------------------------------------
62
63IMPLEMENT_DYNAMIC_CLASS(wxFileHistory, wxObject)
64
690ddfec 65wxFileHistoryBase::wxFileHistoryBase(size_t maxFiles, wxWindowID idBase)
a0219e45
VS
66{
67 m_fileMaxFiles = maxFiles;
68 m_idBase = idBase;
69}
70
690ddfec 71void wxFileHistoryBase::AddFileToHistory(const wxString& file)
a0219e45
VS
72{
73 // check if we don't already have this file
74 const wxFileName fnNew(file);
75 size_t i,
76 numFiles = m_fileHistory.size();
77 for ( i = 0; i < numFiles; i++ )
78 {
79 if ( fnNew == m_fileHistory[i] )
80 {
81 // we do have it, move it to the top of the history
82 RemoveFileFromHistory(i);
83 numFiles--;
84 break;
85 }
86 }
87
88 // if we already have a full history, delete the one at the end
89 if ( numFiles == m_fileMaxFiles )
90 {
91 RemoveFileFromHistory(--numFiles);
92 }
93
94 // add a new menu item to all file menus (they will be updated below)
95 for ( wxList::compatibility_iterator node = m_fileMenus.GetFirst();
96 node;
97 node = node->GetNext() )
98 {
99 wxMenu * const menu = (wxMenu *)node->GetData();
100
101 if ( !numFiles && menu->GetMenuItemCount() )
102 menu->AppendSeparator();
103
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, " ");
107 }
108
109 // insert the new file in the beginning of the file history
110 m_fileHistory.insert(m_fileHistory.begin(), file);
111 numFiles++;
112
113 // update the labels in all menus
114 for ( i = 0; i < numFiles; i++ )
115 {
116 // if in same directory just show the filename; otherwise the full path
117 const wxFileName fnOld(m_fileHistory[i]);
118
119 wxString pathInMenu;
120 if ( fnOld.GetPath() == fnNew.GetPath() )
121 {
122 pathInMenu = fnOld.GetFullName();
123 }
124 else // file in different directory
125 {
126 // absolute path; could also set relative path
127 pathInMenu = m_fileHistory[i];
128 }
129
130 for ( wxList::compatibility_iterator node = m_fileMenus.GetFirst();
131 node;
132 node = node->GetNext() )
133 {
134 wxMenu * const menu = (wxMenu *)node->GetData();
135
136 menu->SetLabel(m_idBase + i, GetMRUEntryLabel(i, pathInMenu));
137 }
138 }
139}
140
690ddfec 141void wxFileHistoryBase::RemoveFileFromHistory(size_t i)
a0219e45
VS
142{
143 size_t numFiles = m_fileHistory.size();
144 wxCHECK_RET( i < numFiles,
690ddfec 145 wxT("invalid index in wxFileHistoryBase::RemoveFileFromHistory") );
a0219e45
VS
146
147 // delete the element from the array
148 m_fileHistory.RemoveAt(i);
149 numFiles--;
150
151 for ( wxList::compatibility_iterator node = m_fileMenus.GetFirst();
152 node;
153 node = node->GetNext() )
154 {
155 wxMenu * const menu = (wxMenu *) node->GetData();
156
157 // shift filenames up
158 for ( size_t j = i; j < numFiles; j++ )
159 {
160 menu->SetLabel(m_idBase + j, GetMRUEntryLabel(j, m_fileHistory[j]));
161 }
162
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);
167
168 // delete the last separator too if no more files are left
169 if ( m_fileHistory.empty() )
170 {
171 const wxMenuItemList::compatibility_iterator
172 nodeLast = menu->GetMenuItems().GetLast();
173 if ( nodeLast )
174 {
175 wxMenuItem * const lastMenuItem = nodeLast->GetData();
176 if ( lastMenuItem->IsSeparator() )
177 menu->Delete(lastMenuItem);
178 }
179 //else: menu is empty somehow
180 }
181 }
182}
183
690ddfec 184void wxFileHistoryBase::UseMenu(wxMenu *menu)
a0219e45
VS
185{
186 if ( !m_fileMenus.Member(menu) )
187 m_fileMenus.Append(menu);
188}
189
690ddfec 190void wxFileHistoryBase::RemoveMenu(wxMenu *menu)
a0219e45
VS
191{
192 m_fileMenus.DeleteObject(menu);
193}
194
195#if wxUSE_CONFIG
690ddfec 196void wxFileHistoryBase::Load(const wxConfigBase& config)
a0219e45
VS
197{
198 m_fileHistory.Clear();
199
200 wxString buf;
201 buf.Printf(wxT("file%d"), 1);
202
203 wxString historyFile;
204 while ((m_fileHistory.GetCount() < m_fileMaxFiles) &&
205 config.Read(buf, &historyFile) && !historyFile.empty())
206 {
207 m_fileHistory.Add(historyFile);
208
209 buf.Printf(wxT("file%d"), (int)m_fileHistory.GetCount()+1);
210 historyFile = wxEmptyString;
211 }
212
213 AddFilesToMenu();
214}
215
690ddfec 216void wxFileHistoryBase::Save(wxConfigBase& config)
a0219e45
VS
217{
218 size_t i;
219 for (i = 0; i < m_fileMaxFiles; i++)
220 {
221 wxString buf;
222 buf.Printf(wxT("file%d"), (int)i+1);
223 if (i < m_fileHistory.GetCount())
224 config.Write(buf, wxString(m_fileHistory[i]));
225 else
226 config.Write(buf, wxEmptyString);
227 }
228}
229#endif // wxUSE_CONFIG
230
690ddfec 231void wxFileHistoryBase::AddFilesToMenu()
a0219e45
VS
232{
233 if ( m_fileHistory.empty() )
234 return;
235
236 for ( wxList::compatibility_iterator node = m_fileMenus.GetFirst();
237 node;
238 node = node->GetNext() )
239 {
240 AddFilesToMenu((wxMenu *) node->GetData());
241 }
242}
243
690ddfec 244void wxFileHistoryBase::AddFilesToMenu(wxMenu* menu)
a0219e45
VS
245{
246 if ( m_fileHistory.empty() )
247 return;
248
249 if ( menu->GetMenuItemCount() )
250 menu->AppendSeparator();
251
252 for ( size_t i = 0; i < m_fileHistory.GetCount(); i++ )
253 {
254 menu->Append(m_idBase + i, GetMRUEntryLabel(i, m_fileHistory[i]));
255 }
256}
257
258#endif // wxUSE_FILE_HISTORY