source: trunk/src/advtabs/Files.hpp @ 663

Revision 663, 9.2 KB checked in by Eoin, 11 years ago (diff)

File sorting works! ...again

Line 
1
2//         Copyright Eóin O'Callaghan 2006 - 2008.
3// Distributed under the Boost Software License, Version 1.0.
4//    (See accompanying file LICENSE_1_0.txt or copy at
5//          http://www.boost.org/LICENSE_1_0.txt)
6
7#pragma once
8
9#include "stdAfx.hpp"
10#include "Halite.hpp"
11
12#include "DdxEx.hpp"
13#include "global/string_conv.hpp"
14
15#include "../HaliteTabPage.hpp"
16#include "../HaliteListManager.hpp"
17#include "../HaliteDialogBase.hpp"
18#include "../halIni.hpp"
19#include "../HaliteListViewCtrl.hpp"
20
21#include "../HaliteUpdateLock.hpp"
22
23struct FileLink
24{
25        FileLink(const boost::filesystem::wpath& b, size_t o=0) :
26                branch(b),
27                filename(L""),
28                order_(o)
29        {}
30
31        FileLink(const wstring& f, size_t o=0) :
32                branch(L""),
33                filename(f),
34                order_(o)
35        {}
36
37        FileLink(const hal::file_details& f) :
38                branch(f.branch),
39                filename(f.filename),
40                order_(f.order())
41        {}
42       
43        bool operator==(const FileLink& f) const
44        {
45                return (branch == f.branch);
46        }
47       
48        bool operator<(const FileLink& f) const
49        {
50                return (branch < f.branch);
51        }
52       
53        enum FileType
54        {
55                folder,
56                file
57        };
58       
59        size_t order() { return order_; }
60       
61        boost::filesystem::wpath branch;
62        wstring filename;
63        unsigned type;
64       
65private:
66        size_t order_;
67};
68
69
70inline bool FileLinkNamesEqual(const FileLink& l, const FileLink& r)
71{
72        return l.filename == r.filename;
73}
74
75inline bool FileLinkNamesLess(const FileLink& l, const FileLink& r)
76{
77        return l.filename < r.filename;
78}
79
80class FileListView :
81        public CHaliteSortListViewCtrl<FileListView, const hal::file_details>,
82        public hal::IniBase<FileListView>,
83        private boost::noncopyable
84{
85public:
86        typedef FileListView thisClass;
87        typedef const hal::file_details dataClass;
88        typedef CHaliteSortListViewCtrl<thisClass, dataClass> listClass;
89        typedef hal::IniBase<thisClass> iniClass;
90       
91        typedef boost::function<void ()> do_ui_update_fn;
92
93        friend class listClass;
94
95public: 
96        class scoped_files
97        {
98
99        public:
100                scoped_files(hal::mutex_t& m, hal::file_details_vec* f) :
101                        l_(m),
102                        f_(f)
103                {}
104
105                hal::file_details_vec* operator->() const { return f_; }
106
107                hal::file_details_vec& operator*() const { return *f_; }
108
109        private:
110                hal::mutex_t::scoped_lock l_;
111                hal::file_details_vec* f_;
112        };
113
114
115        enum { 
116                LISTVIEW_ID_MENU = HAL_FILESLISTVIEW_MENU,
117                LISTVIEW_ID_COLUMNNAMES = HAL_DIALOGFILE_LISTVIEW_ADV,
118                LISTVIEW_ID_COLUMNWIDTHS = 0
119        };
120       
121        BEGIN_MSG_MAP_EX(thisClass)
122                MSG_WM_DESTROY(OnDestroy)
123
124                COMMAND_RANGE_HANDLER_EX(ID_HAL_FILE_PRIORITY_0, ID_HAL_FILE_PRIORITY_7, OnMenuPriority)
125
126                REFLECTED_NOTIFY_CODE_HANDLER(LVN_GETDISPINFO, OnGetDispInfo)
127                REFLECTED_NOTIFY_CODE_HANDLER(SLVN_SORTCHANGED, OnSortChanged)
128
129                CHAIN_MSG_MAP(listClass)
130                DEFAULT_REFLECTION_HANDLER()
131        END_MSG_MAP()
132
133        FileListView(do_ui_update_fn uiu);
134       
135        void saveSettings()
136        {
137                GetListViewDetails();
138                save_to_ini();
139        }
140       
141        HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
142                DWORD dwStyle = 0, DWORD dwExStyle = 0,
143                ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL);
144       
145        void OnDestroy()
146        {
147                saveSettings();
148        }
149       
150        void OnMenuPriority(UINT, int, HWND);
151       
152        friend class boost::serialization::access;
153        template<class Archive>
154        void serialize(Archive& ar, const unsigned int version)
155        {
156                ar & boost::serialization::make_nvp("listview", 
157                        boost::serialization::base_object<listClass>(*this));
158        }
159
160       
161        void setFocused(const hal::torrent_details_ptr& f) { focused_ = f; }
162        const hal::torrent_details_ptr focused() { return focused_; }
163
164        scoped_files files() { return scoped_files(listClass::mutex_, &files_); }
165
166protected:     
167        LRESULT OnGetDispInfo(int, LPNMHDR pnmh, BOOL&);
168        LRESULT OnSortChanged(int, LPNMHDR pnmh, BOOL&);
169
170private:
171        //mutable hal::mutex_t mutex_;
172
173        do_ui_update_fn do_ui_update_;
174        hal::file_details_vec files_;
175        hal::torrent_details_ptr focused_;
176};
177
178class FileTreeView :
179        public ATL::CWindowImpl<FileTreeView, WTL::CTreeViewCtrlEx>,
180        public hal::IniBase<FileTreeView>,
181        private boost::noncopyable
182{
183protected:
184        typedef FileTreeView thisClass;
185        typedef ATL::CWindowImpl<thisClass, WTL::CTreeViewCtrlEx> treeClass;
186        typedef hal::IniBase<thisClass> iniClass;
187
188        friend class treeClass;
189       
190public: 
191        thisClass() :
192                iniClass("treeviews/advFiles", "FileTreeView"),
193                update_lock_(0)
194        {}
195       
196        BEGIN_MSG_MAP_EX(thisClass)
197                MSG_WM_DESTROY(OnDestroy)
198
199                REFLECTED_NOTIFY_CODE_HANDLER(NM_RCLICK, OnRClick)
200                REFLECTED_NOTIFY_CODE_HANDLER(TVN_SELCHANGED, OnSelChanged)
201               
202                COMMAND_RANGE_HANDLER_EX(ID_HAL_FILE_PRIORITY_0, ID_HAL_FILE_PRIORITY_7, OnMenuPriority)
203                DEFAULT_REFLECTION_HANDLER()
204        END_MSG_MAP()
205       
206        HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
207                DWORD dwStyle = 0, DWORD dwExStyle = 0,
208                ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL);
209       
210        LRESULT OnRClick(int i, LPNMHDR pnmh, BOOL&);
211        void OnMenuPriority(UINT, int, HWND);
212       
213        wpath focused() { return focused_; }
214       
215        void attach(boost::function<void ()> fn) const { selection_.connect(fn); }
216       
217        void signal() { selection_(); }
218       
219        void determineFocused();
220       
221protected:
222        void OnDestroy()
223        {
224        //      saveSettings();
225        }
226       
227        LRESULT OnSelChanged(int, LPNMHDR pnmh, BOOL&);
228       
229        mutable int update_lock_;
230        mutable hal::mutex_t mutex_;
231
232        friend class hal::mutex_update_lock<thisClass>; 
233        friend class hal::try_update_lock<thisClass>;           
234       
235        mutable boost::signal<void ()> selection_;
236        wpath focused_;
237
238private:
239        WTL::CMenu menu_;
240};
241
242template<typename T>
243class TreeViewManager
244{
245public:
246        TreeViewManager(T& t) :
247                tree_(t)
248        {}
249       
250        struct ValidTreeItem
251        {
252                ValidTreeItem() 
253                {}
254
255                ValidTreeItem(WTL::CTreeItem& t) :
256                        valid(true),
257                        treeItem(t)
258                {}
259               
260                bool valid;
261                WTL::CTreeItem treeItem;
262        };
263       
264        typedef std::map<wpath, ValidTreeItem> MapType;
265       
266        void EnsureValid(wpath p)
267        {               
268                wpath branchPath = p;
269               
270                MapType::iterator i = map_.find(branchPath);           
271                if (i == map_.end())
272                {
273                        WTL::CTreeItem ti = tree_.GetRootItem();
274                       
275                        wpath branch;
276                        foreach (wstring b, branchPath)
277                        {
278                                branch /= b;                           
279                                MapType::iterator j = map_.find(branch);
280                               
281                                if (j == map_.end())
282                                {
283                                        WTL::CTreeItem tmp = ti.AddTail(b.c_str(), -1);
284                                        ti.Expand();
285                                        ti = tmp;
286                                        map_[branch] = ValidTreeItem(ti);
287                                }
288                                else
289                                {
290                                        (*j).second.valid = true;
291                                        ti = (*j).second.treeItem;
292                                }                               
293                        }
294                }
295                else
296                {
297                        if (!(*i).second.valid)
298                        {
299                                (*i).second.valid = true;
300                                EnsureValid(branchPath.parent_path());
301                        }
302                }
303        }
304       
305        void InvalidateAll()
306        {
307                for(MapType::iterator i=map_.begin(), e=map_.end(); i!=e; ++i)
308                {
309                        (*i).second.valid = false;
310                }
311        }
312       
313        void ClearInvalid()
314        {
315                for(MapType::iterator i=map_.begin(), e=map_.end(); i!=e; /**/)
316                {
317                        if ((*i).second.valid)
318                        {
319                                ++i;
320                        }
321                        else
322                        {
323                                (*i).second.treeItem.Delete();
324                                map_.erase(i++);
325                        }
326                }       
327        }
328       
329private:
330        T& tree_;
331        MapType map_;
332};
333
334class FileStatic :
335        public ATL::CWindowImpl<FileStatic, WTL::CStatic>
336{       
337public:
338        BEGIN_MSG_MAP_EX(FileStatic)
339                REFLECT_NOTIFICATIONS()
340        END_MSG_MAP()
341};
342
343class AdvFilesDialog :
344        public CHalTabPageImpl<AdvFilesDialog>,
345        public WTL::CDialogResize<AdvFilesDialog>,
346        public CHaliteDialogBase<AdvFilesDialog>,
347        public CWinDataExchangeEx<AdvFilesDialog>,
348        public hal::IniBase<AdvFilesDialog>,
349        private boost::noncopyable
350{
351protected:
352        typedef AdvFilesDialog thisClass;
353        typedef CHalTabPageImpl<thisClass> baseClass;
354        typedef WTL::CDialogResize<thisClass> resizeClass;
355        typedef CHaliteDialogBase<thisClass> dialogBaseClass;
356        typedef hal::IniBase<thisClass> iniClass;
357
358public:
359        enum { IDD = HAL_ADVFILES };
360
361        AdvFilesDialog(HaliteWindow& halWindow);
362       
363        ~AdvFilesDialog() {}
364       
365        BOOL PreTranslateMessage(MSG* pMsg)
366        {
367                return this->IsDialogMessage(pMsg);
368        }
369
370        BEGIN_MSG_MAP_EX(thisClass)
371                MSG_WM_INITDIALOG(onInitDialog)
372                MSG_WM_CLOSE(onClose)
373                MSG_WM_DESTROY(OnDestroy)
374               
375                if (uMsg == WM_FORWARDMSG)
376                        if (PreTranslateMessage((LPMSG)lParam)) return TRUE;
377               
378                CHAIN_MSG_MAP(dialogBaseClass)
379                CHAIN_MSG_MAP(resizeClass)
380                CHAIN_MSG_MAP(baseClass)
381                REFLECT_NOTIFICATIONS()
382        END_MSG_MAP()
383
384        BEGIN_DLGRESIZE_MAP(thisClass)
385                DLGRESIZE_CONTROL(HAL_CONTAINER, DLSZ_SIZE_X|DLSZ_SIZE_Y|DLSZ_REPAINT)
386        END_DLGRESIZE_MAP()
387
388    friend class boost::serialization::access;
389    template<class Archive>
390    void serialize(Archive& ar, const unsigned int version)
391        {
392                ar & BOOST_SERIALIZATION_NVP(splitterPos);
393        }
394
395        LRESULT onInitDialog(HWND, LPARAM);
396        void onClose();
397        LRESULT OnGetDispInfo(int, LPNMHDR pnmh, BOOL&);
398       
399        void DlgResize_UpdateLayout(int cxWidth, int cyHeight);
400        void doUiUpdate();
401        void uiUpdate(const hal::torrent_details_manager& tD);
402        void focusChanged(const hal::torrent_details_ptr pT);
403        void OnDestroy();
404
405protected:
406        WTL::CSplitterWindow splitter_;
407        unsigned int splitterPos;
408       
409        FileStatic static_;
410        FileTreeView tree_;
411        FileListView list_;
412       
413        std::map<wpath, WTL::CTreeItem> fileTreeMap_;
414        TreeViewManager<FileTreeView> treeManager_;
415       
416        std::vector<FileLink> fileLinks_;
417       
418        hal::file_details_vec file_details_;
419        std::pair<std::vector<FileLink>::iterator, std::vector<FileLink>::iterator> range_;
420};
Note: See TracBrowser for help on using the repository browser.