~brian-sidebotham/wxwidgets-cmake/wxpython-2.9.4

« back to all changes in this revision

Viewing changes to src/common/filehistorycmn.cpp

  • Committer: Brian Sidebotham
  • Date: 2013-08-03 14:30:08 UTC
  • Revision ID: brian.sidebotham@gmail.com-20130803143008-c7806tkych1tp6fc
Initial import into Bazaar

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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: filehistorycmn.cpp 70503 2012-02-03 17:27:13Z VZ $
 
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
 
 
42
namespace
 
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
 
48
wxString 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
 
 
63
IMPLEMENT_DYNAMIC_CLASS(wxFileHistory, wxObject)
 
64
 
 
65
wxFileHistoryBase::wxFileHistoryBase(size_t maxFiles, wxWindowID idBase)
 
66
{
 
67
    m_fileMaxFiles = maxFiles;
 
68
    m_idBase = idBase;
 
69
}
 
70
 
 
71
/* static */
 
72
wxString wxFileHistoryBase::NormalizeFileName(const wxFileName& fn)
 
73
{
 
74
    // We specifically exclude wxPATH_NORM_LONG here as it can take a long time
 
75
    // (several seconds) for network file paths under MSW, resulting in huge
 
76
    // delays when opening a program using wxFileHistory. We also exclude
 
77
    // wxPATH_NORM_ENV_VARS as the file names here are supposed to be "real"
 
78
    // file names and not have any environment variables in them.
 
79
    wxFileName fnNorm(fn);
 
80
    fnNorm.Normalize(wxPATH_NORM_DOTS |
 
81
                     wxPATH_NORM_TILDE |
 
82
                     wxPATH_NORM_CASE |
 
83
                     wxPATH_NORM_ABSOLUTE);
 
84
    return fnNorm.GetFullPath();
 
85
}
 
86
 
 
87
void wxFileHistoryBase::AddFileToHistory(const wxString& file)
 
88
{
 
89
    // Check if we don't already have this file. Notice that we avoid
 
90
    // wxFileName::operator==(wxString) here as it converts the string to
 
91
    // wxFileName and then normalizes it using all normalizations which is too
 
92
    // slow (see the comment above), so we use our own quick normalization
 
93
    // functions and a string comparison.
 
94
    const wxFileName fnNew(file);
 
95
    const wxString newFile = NormalizeFileName(fnNew);
 
96
    size_t i,
 
97
           numFiles = m_fileHistory.size();
 
98
    for ( i = 0; i < numFiles; i++ )
 
99
    {
 
100
        if ( newFile == NormalizeFileName(m_fileHistory[i]) )
 
101
        {
 
102
            // we do have it, move it to the top of the history
 
103
            RemoveFileFromHistory(i);
 
104
            numFiles--;
 
105
            break;
 
106
        }
 
107
    }
 
108
 
 
109
    // if we already have a full history, delete the one at the end
 
110
    if ( numFiles == m_fileMaxFiles )
 
111
    {
 
112
        RemoveFileFromHistory(--numFiles);
 
113
    }
 
114
 
 
115
    // add a new menu item to all file menus (they will be updated below)
 
116
    for ( wxList::compatibility_iterator node = m_fileMenus.GetFirst();
 
117
        node;
 
118
        node = node->GetNext() )
 
119
    {
 
120
        wxMenu * const menu = (wxMenu *)node->GetData();
 
121
 
 
122
        if ( !numFiles && menu->GetMenuItemCount() )
 
123
            menu->AppendSeparator();
 
124
 
 
125
        // label doesn't matter, it will be set below anyhow, but it can't
 
126
        // be empty (this is supposed to indicate a stock item)
 
127
        menu->Append(m_idBase + numFiles, " ");
 
128
    }
 
129
 
 
130
    // insert the new file in the beginning of the file history
 
131
    m_fileHistory.insert(m_fileHistory.begin(), file);
 
132
    numFiles++;
 
133
 
 
134
    // update the labels in all menus
 
135
    for ( i = 0; i < numFiles; i++ )
 
136
    {
 
137
        // if in same directory just show the filename; otherwise the full path
 
138
        const wxFileName fnOld(m_fileHistory[i]);
 
139
 
 
140
        wxString pathInMenu;
 
141
        if ( fnOld.GetPath() == fnNew.GetPath() )
 
142
        {
 
143
            pathInMenu = fnOld.GetFullName();
 
144
        }
 
145
        else // file in different directory
 
146
        {
 
147
            // absolute path; could also set relative path
 
148
            pathInMenu = m_fileHistory[i];
 
149
        }
 
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
            menu->SetLabel(m_idBase + i, GetMRUEntryLabel(i, pathInMenu));
 
158
        }
 
159
    }
 
160
}
 
161
 
 
162
void wxFileHistoryBase::RemoveFileFromHistory(size_t i)
 
163
{
 
164
    size_t numFiles = m_fileHistory.size();
 
165
    wxCHECK_RET( i < numFiles,
 
166
                 wxT("invalid index in wxFileHistoryBase::RemoveFileFromHistory") );
 
167
 
 
168
    // delete the element from the array
 
169
    m_fileHistory.RemoveAt(i);
 
170
    numFiles--;
 
171
 
 
172
    for ( wxList::compatibility_iterator node = m_fileMenus.GetFirst();
 
173
          node;
 
174
          node = node->GetNext() )
 
175
    {
 
176
        wxMenu * const menu = (wxMenu *) node->GetData();
 
177
 
 
178
        // shift filenames up
 
179
        for ( size_t j = i; j < numFiles; j++ )
 
180
        {
 
181
            menu->SetLabel(m_idBase + j, GetMRUEntryLabel(j, m_fileHistory[j]));
 
182
        }
 
183
 
 
184
        // delete the last menu item which is unused now
 
185
        const wxWindowID lastItemId = m_idBase + numFiles;
 
186
        if ( menu->FindItem(lastItemId) )
 
187
            menu->Delete(lastItemId);
 
188
 
 
189
        // delete the last separator too if no more files are left
 
190
        if ( m_fileHistory.empty() )
 
191
        {
 
192
            const wxMenuItemList::compatibility_iterator
 
193
                nodeLast = menu->GetMenuItems().GetLast();
 
194
            if ( nodeLast )
 
195
            {
 
196
                wxMenuItem * const lastMenuItem = nodeLast->GetData();
 
197
                if ( lastMenuItem->IsSeparator() )
 
198
                    menu->Delete(lastMenuItem);
 
199
            }
 
200
            //else: menu is empty somehow
 
201
        }
 
202
    }
 
203
}
 
204
 
 
205
void wxFileHistoryBase::UseMenu(wxMenu *menu)
 
206
{
 
207
    if ( !m_fileMenus.Member(menu) )
 
208
        m_fileMenus.Append(menu);
 
209
}
 
210
 
 
211
void wxFileHistoryBase::RemoveMenu(wxMenu *menu)
 
212
{
 
213
    m_fileMenus.DeleteObject(menu);
 
214
}
 
215
 
 
216
#if wxUSE_CONFIG
 
217
void wxFileHistoryBase::Load(const wxConfigBase& config)
 
218
{
 
219
    m_fileHistory.Clear();
 
220
 
 
221
    wxString buf;
 
222
    buf.Printf(wxT("file%d"), 1);
 
223
 
 
224
    wxString historyFile;
 
225
    while ((m_fileHistory.GetCount() < m_fileMaxFiles) &&
 
226
           config.Read(buf, &historyFile) && !historyFile.empty())
 
227
    {
 
228
        m_fileHistory.Add(historyFile);
 
229
 
 
230
        buf.Printf(wxT("file%d"), (int)m_fileHistory.GetCount()+1);
 
231
        historyFile = wxEmptyString;
 
232
    }
 
233
 
 
234
    AddFilesToMenu();
 
235
}
 
236
 
 
237
void wxFileHistoryBase::Save(wxConfigBase& config)
 
238
{
 
239
    size_t i;
 
240
    for (i = 0; i < m_fileMaxFiles; i++)
 
241
    {
 
242
        wxString buf;
 
243
        buf.Printf(wxT("file%d"), (int)i+1);
 
244
        if (i < m_fileHistory.GetCount())
 
245
            config.Write(buf, wxString(m_fileHistory[i]));
 
246
        else
 
247
            config.Write(buf, wxEmptyString);
 
248
    }
 
249
}
 
250
#endif // wxUSE_CONFIG
 
251
 
 
252
void wxFileHistoryBase::AddFilesToMenu()
 
253
{
 
254
    if ( m_fileHistory.empty() )
 
255
        return;
 
256
 
 
257
    for ( wxList::compatibility_iterator node = m_fileMenus.GetFirst();
 
258
          node;
 
259
          node = node->GetNext() )
 
260
    {
 
261
        AddFilesToMenu((wxMenu *) node->GetData());
 
262
    }
 
263
}
 
264
 
 
265
void wxFileHistoryBase::AddFilesToMenu(wxMenu* menu)
 
266
{
 
267
    if ( m_fileHistory.empty() )
 
268
        return;
 
269
 
 
270
    if ( menu->GetMenuItemCount() )
 
271
        menu->AppendSeparator();
 
272
 
 
273
    for ( size_t i = 0; i < m_fileHistory.GetCount(); i++ )
 
274
    {
 
275
        menu->Append(m_idBase + i, GetMRUEntryLabel(i, m_fileHistory[i]));
 
276
    }
 
277
}
 
278
 
 
279
#endif // wxUSE_FILE_HISTORY