source: trunk/src/HaliteListViewCtrl.hpp @ 507

Revision 507, 10.5 KB checked in by Eoin, 11 years ago (diff)

Added ListViewIterators?.hpp.

Major find and replace of TorrentDetails? and associated classes to torrent_details.

Line 
1
2//         Copyright Eóin O'Callaghan 2006 - 2007.
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 <boost/array.hpp>
10#include <boost/signals.hpp>
11#include <boost/algorithm/string/split.hpp>
12#include <boost/serialization/vector.hpp>
13#include <boost/serialization/split_free.hpp>
14
15#include "stdAfx.hpp"
16#include "halTorrent.hpp"
17
18template <class TBase>
19class CHaliteListViewCtrl : public ATL::CWindowImpl<TBase, WTL::CListViewCtrl>
20{
21public:
22        typedef CHaliteListViewCtrl<TBase> thisClass;
23       
24protected:
25        template <typename L, typename S=std::string>
26        class selection_manager : 
27                private boost::noncopyable
28        {       
29        public:
30                selection_manager(L& m_list) :
31                        m_list_(m_list)
32                {}
33               
34                typedef const S& param_type;
35               
36                void sync_list(bool list_to_manager, bool signal_change=true)
37                {
38//                      hal::event_log.post(shared_ptr<hal::EventDetail>(new hal::EventDebug(hal::event_logger::info, (wformat(L"%1%, %2% %3%") % hal::from_utf8(selected_) % list_to_manager % signal_change).str().c_str())));
39                        if (list_to_manager)
40                        {       
41                                all_selected_.clear();
42                                int itemPos = m_list_.GetSelectionMark();       
43                       
44                                if (itemPos != -1)
45                                {
46                                        boost::array<wchar_t, MAX_PATH> pathBuffer;
47                                        m_list_.GetItemText(itemPos, 0, pathBuffer.c_array(), pathBuffer.size());       
48                                       
49                                        // Multi-Selected
50                                        int total = m_list_.GetItemCount();
51                                       
52                                        for (int i=0; i<total; ++i)
53                                        {
54                                                UINT flags = m_list_.GetItemState(i, LVIS_SELECTED);
55                                               
56                                                if (flags && LVIS_SELECTED)
57                                                {
58                                                        m_list_.GetItemText(i, 0, pathBuffer.c_array(), pathBuffer.size());     
59                                                        all_selected_.push_back(hal::to_utf8(pathBuffer.data()));
60                                                }
61                                        }
62                                       
63                                        // Single-Selected
64                                        string selected = hal::to_utf8(pathBuffer.data());
65                                       
66                                        if (selected_ != selected)
67                                        {
68                                                selected_ = selected;
69                                                if (signal_change) signal();
70                                        }
71                                }
72                                else
73                                {
74                                        selected_ = "";
75                                        if (signal_change) signal();
76                                }
77                        }
78                        else
79                        {
80                        /*      foreach (string name, all_selected_)
81                                {
82                                        selectMatch(name);
83                                }
84                        */
85                                int itemPos = selectMatch(selected_);                           
86                        //      if (itemPos != -1) m_list_.SetSelectionMark(itemPos);
87                               
88                                if (signal_change) signal();
89                        }
90                }
91               
92                int selectMatch(const string& name)
93                {
94                        LV_FINDINFO findInfo = { sizeof(LV_FINDINFO) }; 
95                        findInfo.flags = LVFI_STRING;
96                       
97                        wstring torrent_name = hal::from_utf8(name);           
98                        findInfo.psz = torrent_name.c_str();
99                       
100                        int itemPos = m_list_.FindItem(&findInfo, -1); 
101                       
102//                      hal::event_log.post(shared_ptr<hal::EventDetail>(new hal::EventDebug(hal::event_logger::info, (wformat(L"%1%, %2%") % torrent_name % itemPos).str().c_str())));
103                       
104                        if (itemPos == -1)
105                                return itemPos;
106                               
107                        UINT flags = m_list_.GetItemState(itemPos, LVIS_SELECTED);
108                       
109                        //if (!flags && LVIS_SELECTED)
110                        {
111                                LVITEM lvi = { LVIF_STATE };
112                                lvi.state = LVIS_SELECTED;
113                                lvi.stateMask = LVIS_SELECTED;
114                                m_list_.SetItemState(itemPos, &lvi);
115                        }
116               
117                        return itemPos;
118                }
119               
120                param_type selected() const { return selected_; }
121               
122                int selectedIndex()
123                {
124                        wstring torrent_name = hal::from_utf8(selected_);       
125                        LV_FINDINFO findInfo = { sizeof(LV_FINDINFO) };         
126                        findInfo.psz = torrent_name.c_str();
127                       
128                        return m_list_.FindItem(&findInfo, -1);         
129                }
130               
131                const std::vector<string>& allSelected() const { return all_selected_; }
132               
133                void setSelected(const string& sel) 
134                {
135                        selected_ = sel;
136                        sync_list(false);
137                }
138               
139                void setSelected(int itemPos)
140                {
141                        LVITEM lvi = { LVIF_STATE };
142                        lvi.state = LVIS_SELECTED;
143                        lvi.stateMask = LVIS_SELECTED;
144                        m_list_.SetItemState(itemPos, &lvi);
145                        m_list_.SetSelectionMark(itemPos);
146                        sync_list(true);
147                }
148               
149                void clear()
150                {
151                        m_list_.DeleteItem(m_list_.GetSelectionMark());
152                       
153                //      m_list_.SelectItem(0);
154                        sync_list(true);       
155                }
156               
157                void clearAllSelected()
158                {
159                        int total = m_list_.GetItemCount();
160                       
161                        for (int i=total-1; i>=0; --i)
162                        {
163                                UINT flags = m_list_.GetItemState(i, LVIS_SELECTED);
164                               
165                                if (flags && LVIS_SELECTED)
166                                        m_list_.DeleteItem(i);
167                        }
168                        all_selected_.clear();
169                       
170                //      m_list_.SelectItem(0);
171                        sync_list(true);       
172                }
173               
174                void clearAll()
175                {
176                        m_list_.DeleteAllItems();
177                        all_selected_.clear();
178                        sync_list(true);               
179                }
180               
181                void attach(boost::function<void (param_type)> fn) { selection_.connect(fn); }
182               
183                void signal() 
184                { 
185                        selection_(selected_); 
186                }
187               
188        private:
189                S selected_;
190                std::vector<S> all_selected_;
191               
192                boost::signal<void (param_type)> selection_;
193                L& m_list_;
194        };
195       
196        class CHaliteHeaderCtrl : public ATL::CWindowImpl<CHaliteHeaderCtrl, WTL::CHeaderCtrl>
197        {
198        public:
199                BEGIN_MSG_MAP(CHaliteHeaderCtrl)
200                        REFLECTED_NOTIFY_CODE_HANDLER(NM_RCLICK, OnRClick)
201                END_MSG_MAP()
202               
203                void Attach(HWND hWndNew)
204                {
205                        ATLASSERT(::IsWindow(hWndNew));
206                        CWindowImpl<CHaliteHeaderCtrl, CHeaderCtrl>::SubclassWindow(hWndNew);
207
208                        menu_.CreatePopupMenu();
209                       
210                        MENUITEMINFO minfo = {sizeof(MENUITEMINFO)};
211                        minfo.fMask = MIIM_STRING|MIIM_ID|MIIM_FTYPE|MIIM_STATE;
212                        minfo.fType = MFT_STRING;
213                        minfo.fState = MFS_CHECKED;
214                        minfo.dwTypeData = L"Hello";
215                       
216                        menu_.InsertMenuItem(0, false, &minfo);
217//                      TBase* pT = static_cast<TBase*>(this);
218//                      pT->OnAttach();
219                }
220               
221                LRESULT OnRClick(int i, LPNMHDR pnmh, BOOL&)
222                {
223                        POINT ptPoint;
224                        GetCursorPos(&ptPoint);
225                        menu_.TrackPopupMenu(0, ptPoint.x, ptPoint.y, m_hWnd);
226
227                        return 0;
228                }
229               
230        private:
231                WTL::CMenu menu_;
232        };
233       
234        template<typename T>
235        class column_type
236        {
237        public:
238                virtual ~column_type() = 0             
239                virtual bool less(cont T&, const T&) = 0
240                virtual std::string str() = 0;
241        };
242       
243        // EG T is a torrent_details, so have array column_types
244
245public:
246        typedef selection_manager<thisClass> selection_manage_class;
247       
248        enum sortDirection
249        {
250                none,
251                ascending,
252                descending
253        };
254       
255        CHaliteListViewCtrl<TBase>() :
256                sortingDirection_(CHaliteListViewCtrl<TBase>::none),
257                sortedColmun_(0),
258                manager_(*this)
259        {
260                if (TBase::LISTVIEW_ID_MENU)
261                {
262                        BOOL menu_created = menu_.LoadMenu(TBase::LISTVIEW_ID_MENU);
263                        assert(menu_created);   
264                }
265
266                wstring column_names = hal::app().res_wstr(TBase::LISTVIEW_ID_COLUMNNAMES);
267                boost::split(names_, column_names, boost::is_any_of(L";"));
268               
269                wstring column_widths = hal::app().res_wstr(TBase::LISTVIEW_ID_COLUMNWIDTHS);
270                std::vector<wstring> widths;
271                boost::split(widths, column_widths, boost::is_any_of(L";"));
272                               
273                listColumnWidth_.reserve(names_.size());       
274                listColumnOrder_.reserve(names_.size());
275               
276                for (size_t i=0; i<names_.size(); ++i)
277                {
278                        listColumnWidth_.push_back(lexical_cast<int>(widths[i]));
279                        listColumnOrder_.push_back(i);
280                }       
281        }
282
283        BEGIN_MSG_MAP_EX(CHaliteListViewCtrl<TBase>)
284                REFLECTED_NOTIFY_CODE_HANDLER(NM_CLICK, OnClick)
285                REFLECTED_NOTIFY_CODE_HANDLER(LVN_ITEMCHANGED, OnItemChanged)
286                REFLECTED_NOTIFY_CODE_HANDLER(NM_RCLICK, OnRClick)
287                REFLECTED_NOTIFY_CODE_HANDLER(LVN_COLUMNCLICK , OnColClick)
288
289                DEFAULT_REFLECTION_HANDLER()
290        END_MSG_MAP()
291
292        void Attach(HWND hWndNew)
293        {
294                ATLASSERT(::IsWindow(hWndNew));
295        CWindowImpl<TBase, CListViewCtrl>::SubclassWindow(hWndNew);
296
297                TBase* pT = static_cast<TBase*>(this);
298                pT->OnAttach();
299        }
300       
301        void SetListViewDetails()
302        {
303                vectorSizePreConditions();
304               
305                header_.Attach(this->GetHeader());
306                header_.ModifyStyle(0, HDS_DRAGDROP|HDS_FULLDRAG);
307                       
308                foreach (wstring name, names_)
309                {
310                        AddColumn(name.c_str(), header_.GetItemCount());
311                }               
312
313                for (unsigned i=0; i<names_.size(); ++i)
314                        SetColumnWidth(i, listColumnWidth_[i]);
315               
316                SetColumnOrderArray(names_.size(), &listColumnOrder_[0]);       
317        }
318       
319        template<std::size_t Size>
320        void SetDefaults(array<int, Size> a)
321        {
322                assert (Size == names_.size());
323                vectorSizePreConditions();
324               
325                for (size_t i=0; i<names_.size(); ++i)
326                {
327                        listColumnWidth_[i] = a[i];
328                        listColumnOrder_[i] = i;
329                }               
330        }
331       
332        // Should probably make this redundant!!
333        void GetListViewDetails()
334        {
335                vectorSizePreConditions();
336               
337                GetColumnOrderArray(names_.size(), &listColumnOrder_[0]);
338               
339                for (size_t i=0; i<names_.size(); ++i)
340                        listColumnWidth_[i] = GetColumnWidth(i);       
341        }
342
343        LRESULT OnClick(int, LPNMHDR pnmh, BOOL&)
344        {
345        //      manager().sync_list(true);
346
347                return 0;
348        }
349
350        LRESULT OnItemChanged(int, LPNMHDR pnmh, BOOL&)
351        {
352                manager().sync_list(true);
353
354                return 0;
355        }
356
357        LRESULT OnRClick(int i, LPNMHDR pnmh, BOOL&)
358        {
359                LPNMITEMACTIVATE pia = (LPNMITEMACTIVATE)pnmh;
360                manager().sync_list(true);
361               
362                if (TBase::LISTVIEW_ID_MENU)
363                {
364                        assert (menu_.IsMenu());
365                        CMenuHandle sMenu = menu_.GetSubMenu(0);
366                        assert (sMenu.IsMenu());
367       
368                        POINT ptPoint;
369                        GetCursorPos(&ptPoint);
370                        sMenu.TrackPopupMenu(0, ptPoint.x, ptPoint.y, m_hWnd);
371                }
372
373                return 0;
374        }
375
376        LRESULT OnColClick(int i, LPNMHDR pnmh, BOOL&)
377        {
378                LPNMLISTVIEW pnlv = (LPNMLISTVIEW)pnmh;
379               
380                MessageBox((lexical_cast<wstring>(pnlv->iSubItem)).c_str(), L"Hi", 0);
381                return 0;
382        }
383       
384        friend class boost::serialization::access;
385    template<class Archive>
386    void serialize(Archive & ar, const unsigned int version)
387    {
388        ar & boost::serialization::make_nvp("width", listColumnWidth_);
389        ar & boost::serialization::make_nvp("order", listColumnOrder_);
390    }
391
392        selection_manager<CHaliteListViewCtrl>& manager() { return manager_; }
393       
394        size_t sortedColmun() { return sortedColmun_; }
395        sortDirection sortingDirection() { return sortingDirection_; }
396       
397        std::vector<int>& listColumnWidth() { return listColumnWidth_; }
398        std::vector<int>& listColumnOrder() { return listColumnOrder_; }
399       
400        const std::vector<int>& listColumnWidth() const { return listColumnWidth_; }
401        const std::vector<int>& listColumnOrder() const { return listColumnOrder_; }
402       
403private:
404        selection_manager<CHaliteListViewCtrl> manager_;
405       
406        void vectorSizePreConditions()
407        {
408                if (listColumnWidth_.size() != names_.size())
409                {
410                        listColumnWidth_.clear();
411                        listColumnWidth_.insert(listColumnWidth_.end(), names_.size(), 50);     
412                }
413               
414                if (listColumnOrder_.size() != names_.size())
415                {               
416                        listColumnOrder_.clear();
417                        listColumnOrder_.insert(listColumnOrder_.end(), names_.size(), 0);
418                }               
419        }
420       
421        sortDirection sortingDirection_;
422        size_t sortedColmun_;
423       
424        WTL::CMenu menu_;
425        CHaliteHeaderCtrl header_;
426        std::vector<wstring> names_;
427        std::vector<int> listColumnWidth_;
428        std::vector<int> listColumnOrder_;
429};
Note: See TracBrowser for help on using the repository browser.