source: trunk/src/HaliteSortListViewCtrl.hpp @ 730

Revision 730, 20.2 KB checked in by Eoin, 11 years ago (diff)
Line 
1
2//         Copyright Eóin O'Callaghan 2006 - 2009.
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
11#include <functional>
12
13#include <boost/array.hpp>
14#include <boost/signals.hpp>
15#include <boost/algorithm/string/split.hpp>
16#include <boost/ptr_container/ptr_map.hpp>
17
18#include <boost/detail/iterator.hpp>
19#include <boost/multi_index_container.hpp>
20#include <boost/multi_index/identity.hpp>
21#include <boost/multi_index/ordered_index.hpp>
22#include <boost/multi_index/member.hpp>
23#include <boost/multi_index/random_access_index.hpp>
24
25#include <winstl/controls/listview_sequence.hpp>
26
27#include "Halite.hpp"
28#include "halTorrent.hpp"
29#include "halEvent.hpp"
30#include "WinAPIWaitableTimer.hpp"
31
32#include "UxthemeWrapper.hpp"
33
34#define LVS_EX_DOUBLEBUFFER     0x00010000
35
36#include "WTLx/SelectionManager.hpp"
37#include "WTLx/ListViewIterators.hpp"
38#include "WTLx/ListViewSortMixin.hpp"
39#include "HaliteUpdateLock.hpp"
40
41template <class TBase, typename DataType=void*>
42class CHaliteSortListViewCtrl : 
43        public ATL::CWindowImpl<TBase, WTL::CListViewCtrl>,
44        public WTLx::ListViewIterators<CHaliteSortListViewCtrl<TBase, DataType> >,
45        public WTLx::ListViewSortMixin<CHaliteSortListViewCtrl<TBase, DataType> >
46{
47public:
48        typedef CHaliteSortListViewCtrl<TBase, DataType> thisClass;
49        typedef ATL::CWindowImpl<TBase, WTL::CListViewCtrl> parentClass;
50        typedef WTLx::ListViewSortMixin<thisClass> listClass;
51       
52        class CHaliteHeaderCtrl : public CWindowImpl<CHaliteHeaderCtrl, WTL::CHeaderCtrl>
53        {
54        public:
55                enum { COL_MENU_NAMES = 123, COL_MAX_NAMES = 256 };
56
57                CHaliteHeaderCtrl(thisClass& listView) :
58                        listView_(listView)
59                {}
60
61                BEGIN_MSG_MAP(CHaliteHeaderCtrl)
62                        REFLECTED_NOTIFY_CODE_HANDLER(NM_RCLICK, OnRClick)
63                        COMMAND_RANGE_HANDLER(COL_MENU_NAMES, COL_MENU_NAMES+COL_MAX_NAMES, OnMenuNames)
64
65                        DEFAULT_REFLECTION_HANDLER()
66                END_MSG_MAP()
67               
68                void Attach(HWND hWndNew)
69                {
70                        ATLASSERT(::IsWindow(hWndNew));
71                        CWindowImpl<CHaliteHeaderCtrl, WTL::CHeaderCtrl>::SubclassWindow(hWndNew);
72                }
73               
74                LRESULT OnRClick(int i, LPNMHDR pnmh, BOOL&)
75                {
76                        POINT ptPoint;
77                        GetCursorPos(&ptPoint);
78                        menu_.TrackPopupMenu(0, ptPoint.x, ptPoint.y, m_hWnd);
79
80                        return 0;
81                }
82
83                LRESULT OnMenuNames(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
84                {               
85                        ATLASSERT(wID-COL_MENU_NAMES <= GetItemCount());
86
87                        bool visible = listView_.OnNameChecked(wID-COL_MENU_NAMES);
88
89                        return 0;
90                }
91
92                WTL::CMenu& Menu()
93                {
94                        return menu_;
95                }
96               
97        private:
98                WTL::CMenu menu_;
99                thisClass& listView_;
100        };
101       
102public:
103        typedef WTLx::selection_manager<thisClass, std::wstring> SelectionManager;
104        typedef SelectionManager selection_manage_class;
105       
106        thisClass() :
107                header_(*this),
108                update_lock_(0),
109                auto_sort_(false),
110                descending_(false),
111                sortCol_(-1)
112        {               
113                if (TBase::LISTVIEW_ID_MENU)
114                {
115                        WTL::CMenuHandle menu;
116                        BOOL menu_created = menu.LoadMenu(TBase::LISTVIEW_ID_MENU);
117                        assert(menu_created);   
118                       
119                        menu_.Attach(menu.GetSubMenu(0));
120                }
121        }
122
123        BEGIN_MSG_MAP_EX(thisClass)
124                COMMAND_ID_HANDLER(ID_LVM_AUTOSORT, OnAutoSort)
125               
126                REFLECTED_NOTIFY_CODE_HANDLER(NM_RCLICK, OnRClick)
127                REFLECTED_NOTIFY_CODE_HANDLER(LVN_ITEMCHANGED, OnItemChanged)
128
129                CHAIN_MSG_MAP(listClass)
130                DEFAULT_REFLECTION_HANDLER()
131        END_MSG_MAP()
132
133        void Attach(HWND hWndNew)
134        {
135                ATLASSERT(::IsWindow(hWndNew));
136                parentClass::SubclassWindow(hWndNew);
137
138                TBase* pT = static_cast<TBase*>(this);
139                pT->OnAttach();
140        }
141
142        HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
143                DWORD dwStyle = 0, DWORD dwExStyle = 0,
144                ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
145        {
146                HWND hwnd = parentClass::Create(hWndParent, 
147                        (RECT &)rect.m_lpRect, szWindowName, dwStyle, dwExStyle, (UINT)MenuOrID.m_hMenu, lpCreateParam);
148                       
149                SetExtendedListViewStyle(WS_EX_CLIENTEDGE|LVS_EX_FULLROWSELECT|LVS_EX_HEADERDRAGDROP|LVS_EX_DOUBLEBUFFER|LVS_EX_SUBITEMIMAGES);
150                SetListViewSortMixinExtendedStyle(SORTLV_USESHELLBITMAPS, SORTLV_USESHELLBITMAPS);
151               
152                return hwnd;
153        }
154       
155        bool SubclassWindow(HWND hwnd)
156        {
157                if(!parentClass::SubclassWindow(hwnd))
158                        return false;
159                       
160                SetExtendedListViewStyle(WS_EX_CLIENTEDGE|LVS_EX_FULLROWSELECT|LVS_EX_HEADERDRAGDROP|LVS_EX_DOUBLEBUFFER);
161                SetListViewSortMixinExtendedStyle(SORTLV_USESHELLBITMAPS, SORTLV_USESHELLBITMAPS);
162               
163                return true;
164        }               
165       
166        void SafeLoadFromIni()
167        {
168                std::vector<wstring> listNames;
169                std::vector<int> listWidths;
170                std::vector<int> listOrder;
171                std::vector<bool> listVisible;
172
173                listNames.assign(list_names_.begin(), list_names_.end());
174                listWidths.assign(list_widths_.begin(), list_widths_.end());
175                listOrder.assign(list_order_.begin(), list_order_.end());
176                listVisible.assign(list_visible_.begin(), list_visible_.end());
177
178                TBase* pT = static_cast<TBase*>(this);
179                if (!pT->load_from_ini() || !vector_size_pre_conditions())
180                {
181                        list_names_.assign(listNames.begin(), listNames.end());
182                        list_widths_.assign(listWidths.begin(), listWidths.end());
183                        list_order_.assign(listOrder.begin(), listOrder.end());
184                        list_visible_.assign(listVisible.begin(), listVisible.end());
185                }               
186        }
187
188        void InitialSetup(WTL::CMenuHandle menu=WTL::CMenuHandle())
189        {
190                SetExtendedListViewStyle(LVS_EX_HEADERDRAGDROP|LVS_EX_DOUBLEBUFFER);
191                SetSortListViewExtendedStyle(SORTLV_USESHELLBITMAPS,SORTLV_USESHELLBITMAPS);
192
193                MENUITEMINFO minfo = {sizeof(MENUITEMINFO)};
194               
195                if (!menu)
196                {
197                        menu_.CreatePopupMenu();
198                }
199                else
200                {               
201                        menu_.Attach(menu.GetSubMenu(0));
202
203                        minfo.fMask = MIIM_SUBMENU;
204                        minfo.fType = MFT_SEPARATOR;
205                       
206                        menu_.InsertMenuItem(menu_.GetMenuItemCount(), true, &minfo);           
207                }
208
209                minfo.fMask = MIIM_STRING|MIIM_ID|MIIM_FTYPE|MIIM_STATE;
210                minfo.fType = MFT_STRING;
211                minfo.fState = auto_sort_ ? MFS_CHECKED : MFS_UNCHECKED;
212                minfo.wID = ID_LVM_AUTOSORT;
213               
214                std::wstring autoarrange = hal::app().res_wstr(HAL_AUTOSORT);
215                minfo.dwTypeData = (LPWSTR)autoarrange.c_str();
216               
217                menu_.InsertMenuItem(menu_.GetMenuItemCount(), true, &minfo);
218
219                header_.SubclassWindow(this->GetHeader());
220                header_.ModifyStyle(0, HDS_DRAGDROP|HDS_FULLDRAG);
221                if (header_.Menu().IsNull()) 
222                        header_.Menu().CreatePopupMenu();
223        }
224       
225        void GetListViewDetails()
226        {
227                vector_size_pre_conditions();           
228               
229                for (size_t i=0; i<list_names_.size(); ++i)
230                {
231                        if (list_visible_[i])
232                                list_widths_[i] = GetColumnWidth(i);
233                }
234               
235                GetColumnOrderArray(list_names_.size(), &list_order_[0]);
236               
237                sortCol_ = GetSortColumn();
238                descending_ = IsSortDescending();       
239        }
240       
241        LRESULT OnAutoSort(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
242        {
243                auto_sort_ = !auto_sort_;
244               
245                MENUITEMINFO minfo = {sizeof(MENUITEMINFO)};
246               
247                minfo.fMask = MIIM_STATE;
248                minfo.fState = auto_sort_ ? MFS_CHECKED : MFS_UNCHECKED;
249               
250                menu_.SetMenuItemInfo(ID_LVM_AUTOSORT, false, &minfo);
251               
252                return 0;
253        }
254
255        bool OnNameChecked(int i)
256        {
257                if (!list_visible_[i])
258                {               
259                        GetColumnOrderArray(list_names_.size(), &list_order_[0]);
260                        SetColumnWidth(i, list_widths_[i]);
261
262                        list_order_.erase(std::find(list_order_.begin(), list_order_.end(), i));
263                       
264                        int index = i + std::count(list_visible_.begin()+i, list_visible_.end(), false) - 1;
265                        list_order_.insert(list_order_.begin()+index, i);
266
267                        SetColumnOrderArray(list_names_.size(), &list_order_[0]);
268                        list_visible_[i] = true;
269                }
270                else
271                {
272                        list_widths_[i] = GetColumnWidth(i);   
273                        GetColumnOrderArray(list_names_.size(), &list_order_[0]);
274
275                        SetColumnWidth(i, 0);
276
277                        list_order_.erase(std::find(list_order_.begin(), list_order_.end(), i));
278                        list_order_.insert(list_order_.begin(), i);
279
280                        SetColumnOrderArray(list_names_.size(), &list_order_[0]);
281                        list_visible_[i] = false;
282                }
283               
284                MENUITEMINFO minfo = {sizeof(MENUITEMINFO)};   
285                minfo.fMask = MIIM_STATE;
286                minfo.fState = list_visible_[i] ? MFS_CHECKED : MFS_UNCHECKED; 
287                header_.Menu().SetMenuItemInfo(CHaliteHeaderCtrl::COL_MENU_NAMES+i, false, &minfo);
288       
289                InvalidateRect(NULL, true);
290                return list_visible_[i];
291        }
292
293        LRESULT OnClick(int, LPNMHDR pnmh, BOOL&)
294        {
295                return 0;
296        }
297
298        LRESULT OnItemChanged(int, LPNMHDR pnmh, BOOL&)
299        {               
300                hal::try_update_lock<thisClass> lock(*this);
301               
302//              if (lock) manager_.sync_list(true, true);
303               
304                return 0;
305        }
306
307        LRESULT OnRClick(int i, LPNMHDR pnmh, BOOL&)
308        {
309                LPNMITEMACTIVATE pia = (LPNMITEMACTIVATE)pnmh;
310        //      manager_.sync_list(true);
311               
312                if (menu_)
313                {
314                        assert (menu_.IsMenu());
315       
316                        POINT ptPoint;
317                        GetCursorPos(&ptPoint);
318                        menu_.TrackPopupMenu(0, ptPoint.x, ptPoint.y, m_hWnd);
319                }
320
321                return 0;
322        }
323
324        LRESULT OnColClick(int i, LPNMHDR pnmh, BOOL&)
325        {
326                LPNMLISTVIEW pnlv = (LPNMLISTVIEW)pnmh;
327               
328                MessageBox((lexical_cast<wstring>(pnlv->iSubItem)).c_str(), L"Hi", 0);
329                return 0;
330        }
331
332        bool DoSortItemsExternal(int iCol, bool bDescending = false)
333        {
334                HAL_DEV_SORT_MSG(hal::wform(L"sort_once_ = %1%") % sort_once_);
335
336                sort_once_ = true;
337
338                return true;
339        }
340       
341        bool IsSortOnce(bool mod_value =  true) 
342        { 
343                if (!sort_once_)
344                        return false; 
345
346                if (mod_value) sort_once_ = false;
347                        return true;
348        }
349
350        int AddColumn(LPCTSTR strItem, int nItem, bool visible, int width=-1)
351        {
352                return AddColumn(strItem, nItem, -1,
353                        LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM,
354                        LVCFMT_LEFT, visible, width);
355        }
356
357        int AddColumn(LPCTSTR strItem, int nItem, int nSubItem = -1,
358                int nMask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM,
359                int nFmt = LVCFMT_LEFT, bool visible=true, int width=-1)
360        {
361                int i = parentClass::AddColumn(strItem, nItem, nSubItem, nMask, nFmt);
362
363                if (i == -1) return i;
364
365                if (width != -1) SetColumnWidth(i, width);
366
367                if (header_.Menu().IsNull()) 
368                        header_.Menu().CreatePopupMenu();
369
370                WTL::CMenuHandle menu = header_.Menu();
371
372                MENUITEMINFO minfo = {sizeof(MENUITEMINFO)};
373                minfo.fMask = MIIM_STRING|MIIM_ID|MIIM_FTYPE|MIIM_STATE;
374                minfo.fType = MFT_STRING;
375                minfo.dwTypeData = (LPTSTR)strItem;
376                minfo.wID = CHaliteHeaderCtrl::COL_MENU_NAMES+i;
377
378                if (visible)
379                        minfo.fState = MFS_CHECKED;
380                else
381                {
382                        minfo.fState = MFS_UNCHECKED;
383                        SetColumnWidth(i, 0);
384                }
385
386                int w = GetColumnWidth(i);
387
388                list_names_.push_back(strItem);
389                list_visible_.push_back(visible);
390                list_widths_.push_back(w);
391                list_order_.push_back(i);
392
393                menu.InsertMenuItem(menu.GetMenuItemCount(), false, &minfo);
394                return i;
395        }
396
397        void SetColumnSortType(int iCol, WORD wType, void* colAdapter=NULL)
398        {
399                listClass::SetColumnSortType(iCol, wType);
400               
401        //      if (WTL::LVCOLSORT_CUSTOM == wType)
402        //              regColumnAdapter(iCol, colAdapter);
403        }
404
405        void SetColumnOrderState()
406        {
407                while ((int)list_order_.size() < header_.GetItemCount())
408                        list_order_.push_back(header_.GetItemCount());
409
410                GetColumnOrderArray(list_order_.size(), &list_order_[0]);
411        }
412
413        void SetSortState()
414        {
415                MENUITEMINFO minfo = {sizeof(MENUITEMINFO)};
416               
417                minfo.fMask = MIIM_STATE;
418                minfo.fState = auto_sort_ ? MFS_CHECKED : MFS_UNCHECKED;
419               
420                menu_.SetMenuItemInfo(ID_LVM_AUTOSORT, false, &minfo);
421
422                if (sortCol_ >= 0 && sortCol_ < m_arrColSortType.GetSize())
423                        SetSortColumn(sortCol_);
424        }
425
426        friend class boost::serialization::access;
427        template<class Archive>
428        void save(Archive & ar, const unsigned int version) const
429        {
430                for (size_t i=0; i<list_widths_.size(); ++i)
431                {
432                        if (list_visible_[i])
433                                list_widths_[i] = GetColumnWidth(i);
434                }
435
436                GetColumnOrderArray(list_order_.size(), &list_order_[0]);
437                sortCol_ = GetSortColumn();
438                descending_ = IsSortDescending();       
439
440                using boost::serialization::make_nvp;
441
442                ar & make_nvp("width", list_widths_);
443                ar & make_nvp("order", list_order_);
444                ar & make_nvp("visible", list_visible_);
445                ar & make_nvp("autoSort", auto_sort_);
446
447                ar & make_nvp("descending", descending_);
448                ar & make_nvp("sortCol", sortCol_);
449
450                ar & make_nvp("secondary_descending", listClass::bSecondaryDescending);
451                ar & make_nvp("secondary_sort_column", listClass::iSecondarySort);             
452        }
453
454        template<class Archive>
455        void load(Archive & ar, const unsigned int version)
456        {
457                using boost::serialization::make_nvp;
458
459                ar & make_nvp("width", list_widths_);
460                ar & make_nvp("order", list_order_);
461                ar & make_nvp("visible", list_visible_);
462                ar & make_nvp("autoSort", auto_sort_);
463
464                ar & make_nvp("descending", descending_);
465                ar & make_nvp("sortCol", sortCol_);
466
467                ar & make_nvp("secondary_descending", listClass::bSecondaryDescending);
468                ar & make_nvp("secondary_sort_column", listClass::iSecondarySort);             
469               
470                SetColumnOrderArray(list_order_.size(), &list_order_[0]);
471
472                m_bSortDescending = descending_;
473                if (sortCol_ >= 0 && sortCol_ < m_arrColSortType.GetSize())
474                        SetSortColumn(sortCol_);
475
476                for (size_t i=0; i<list_widths_.size(); ++i)
477                {
478                        SetColumnWidth(i, list_widths_[i]);
479                        if (!list_visible_[i])
480                        {
481                                list_visible_[i] = true;
482                                OnNameChecked(i);
483                        }
484                }
485
486                SetColumnOrderState();
487                SetSortState();
488        }
489
490        BOOST_SERIALIZATION_SPLIT_MEMBER()
491               
492        std::vector<int>& ListColumnWidth() { return listColumnWidth_; }
493        std::vector<int>& ListColumnOrder() { return listColumnOrder_; }
494       
495        const std::vector<int>& ListColumnWidth() const { return listColumnWidth_; }
496        const std::vector<int>& ListColumnOrder() const { return listColumnOrder_; }
497       
498        bool CanUpdate() const { return updateLock_ == 0; }
499       
500        bool AutoSort() { return auto_sort_; }
501       
502        static bool is_selected (const winstl::listview_sequence::sequence_value_type& v) 
503        { 
504                return (v.state() & LVIS_SELECTED) != 0; 
505        }
506
507protected:             
508        mutable int update_lock_;
509        mutable hal::mutex_t mutex_;
510
511        friend class hal::mutex_update_lock<thisClass>; 
512        friend class hal::try_update_lock<thisClass>;   
513
514        WTL::CMenu menu_;
515        CHaliteHeaderCtrl header_;     
516
517        template<typename T>
518        class implicit_reference_wrapper : public boost::reference_wrapper<T>
519        {
520        private:
521                typedef boost::reference_wrapper<T> super;
522
523        public:
524                implicit_reference_wrapper(T& t) : super(t) {}
525        };
526
527        template <typename T>
528        bool implicit_comparison(const implicit_reference_wrapper<T>& l, const implicit_reference_wrapper<T>& r, size_t index, bool ascending) 
529        {
530                TBase* pT = static_cast<TBase*>(this);
531
532                return pT->less(static_cast<T>(l).second, static_cast<T>(r).second, index, ascending);
533        }
534
535        struct by_key {};
536
537        template <typename T>
538        struct first_mutable_pair
539        {
540                first_mutable_pair(const bool& f, const T& s) :
541                        first(f),
542                        second(s)
543                {}
544
545                mutable bool first;
546                T second;
547        };
548        typedef first_mutable_pair<DataType> list_pair_t;
549
550        typedef boost::multi_index_container<
551                list_pair_t,
552                boost::multi_index::indexed_by<
553                        boost::multi_index::random_access<>,
554                        boost::multi_index::ordered_unique<
555                                boost::multi_index::tag<by_key>, 
556                                boost::multi_index::member<list_pair_t, DataType, &list_pair_t::second> >
557                >
558        > pair_container;
559
560        typedef typename pair_container::index_iterator<by_key>::type key_iterator;
561
562        int set_key(DataType key)
563        {
564                LVITEM lvItem = { 0 };
565                lvItem.mask = LVIF_STATE;
566                lvItem.stateMask = LVIS_SELECTED;
567                lvItem.state = 0;
568                lvItem.iSubItem = 0;
569
570                return set_key_item(key, &lvItem);
571        }
572
573        template<typename T>
574        void set_keys(T s)
575        {
576                foreach (const DataType& key, s)
577                {
578                        set_key(key);
579                }
580        }
581
582        int set_key_item(DataType key, LVITEM* pItem)
583        {
584                ATLASSERT(::IsWindow(m_hWnd));
585
586                key_iterator i = pair_container_.get<by_key>().find(key);
587                boost::optional<size_t> index = index_from_key(key);
588
589                if (index)
590                {
591                        HAL_DEV_SORT_MSG(hal::wform(L"Existing index %1%, key %3%, selected %2%") % *index % (*i).first % key);
592
593                        if ((*i).first)
594                                SetItemState(*index, LVIS_SELECTED, LVIS_SELECTED);
595                        else
596                                SetItemState(*index, 0, LVIS_SELECTED);
597
598                        return *index;
599                }
600                else
601                {
602                        int list_item_index = pair_container_.size();
603
604                        bool selected = (pItem->stateMask & LVIS_SELECTED) && (pItem->state & LVIS_SELECTED);
605                        list_pair_t lp = list_pair_t(selected, key);
606
607                        pair_container_.push_back(lp);
608
609                        SetItemCountEx(pair_container_.size(), LVSICF_NOSCROLL);
610                        SetItemState(list_item_index, 0, LVIS_SELECTED);
611
612                        HAL_DEV_SORT_MSG(hal::wform(L"New index %1%, key %3%, selected %2%") % list_item_index % false % key);
613
614                        return list_item_index;
615                }
616        }
617
618        bool data_type_comparison(list_pair_t r, list_pair_t l, size_t index, bool ascending)
619        {
620                TBase* pT = static_cast<TBase*>(this);
621
622                return pT->sort_list_comparison((l).second, (r).second, index, ascending);
623        }
624
625        void selection_from_listview()
626        {
627                foreach(const list_value_type val, std::make_pair(const_begin(), const_end()))
628                {
629                        const list_pair_t& i_pos = pair_container_.get<0>()[val.index()];
630
631                        if (val.state() & LVIS_SELECTED)
632                                i_pos.first = true;
633                        else
634                                i_pos.first = false;
635
636                       
637                        HAL_DEV_SORT_MSG(hal::wform(L" Name %1%, index %2%, selected %3%") % key_from_index(val.index()) % val.index() % i_pos.first);
638                }
639               
640                HAL_DEV_SORT_MSG(hal::wform(L" -----"));
641        }
642
643        void sort(size_t index, bool ascending)
644        {       
645                std::vector<implicit_reference_wrapper<const list_pair_t> > sv;
646
647                std::copy(pair_container_.begin(), pair_container_.end(), std::back_inserter(sv));
648
649                std::stable_sort(sv.begin(), sv.end(), 
650                        bind(&thisClass::data_type_comparison, this, _1, _2, index, ascending));
651
652                pair_container_.rearrange(sv.begin());
653        }
654
655        DataType key_from_index(size_t index)
656        {
657                list_pair_t pi = pair_container_[index];
658
659                return pi.second;
660        }
661
662        boost::optional<size_t> index_from_key(const DataType& key)
663        {
664                key_iterator i = pair_container_.get<by_key>().find(key);       
665               
666                if (i != pair_container_.get<by_key>().end())
667                {
668                        pair_container::iterator i_pos = pair_container_.project<0>(i); 
669                        return std::distance(pair_container_.begin(), i_pos);
670                }
671                else
672                        return boost::optional<size_t>();
673        }
674
675        void erase_from_list(const list_value_type& val)
676        {
677                erase_from_list(val.index());
678        }
679
680        void erase_from_list(size_t index)
681        {
682                pair_container_.erase(pair_container_.begin() + index);
683                DeleteItem(index);
684        }
685       
686        void erase_from_list(const DataType& str)
687        {
688                key_iterator i = pair_container_.get<by_key>().find(str);
689                pair_container::iterator i_pos = pair_container_.project<0>(i);
690
691                if (i != pair_container_.get<by_key>().end())
692                {
693                        DeleteItem(std::distance(pair_container_.begin(), i_pos));
694                        pair_container_.erase(i_pos);
695                }
696        }
697
698        void erase_based_on_set(const std::set<DataType>& s, bool within=true)
699        {
700                for (pair_container::const_iterator i=pair_container_.begin(), e=pair_container_.end(); i!=e; /**/)
701                {                       
702                        HAL_DEV_SORT_MSG(hal::wform(L" Checking %1%,") % (*i).second);
703
704                        if ((s.find((*i).second) != s.end()) ^ within)
705                        {                               
706                                HAL_DEV_SORT_MSG(hal::wform(L" Erasing,"));
707                               
708                                DeleteItem(std::distance(pair_container_.begin(), i));
709                                i  = pair_container_.erase(i);
710                        }
711                        else
712                        {
713                                ++i;
714                        }
715                }
716        }
717
718        void erase_all_from_list()
719        {
720                pair_container_.clear();
721                DeleteAllItems();
722        }
723       
724private:
725        mutable pair_container pair_container_;
726
727        bool vector_size_pre_conditions()
728        {
729                bool ret = (list_names_.size() == list_widths_.size()) &&
730                        (list_names_.size() == list_order_.size()) &&
731                        (list_names_.size() == list_visible_.size());
732
733                return ret;
734        }       
735       
736        mutable std::vector<wstring> list_names_;
737        mutable std::vector<int> list_widths_;
738        mutable std::vector<int> list_order_;
739        mutable std::vector<bool> list_visible_;
740
741        mutable bool auto_sort_;
742        mutable bool sort_once_;
743        mutable bool descending_;
744        mutable int sortCol_;
745};
746
747template<>
748inline const std::wstring hal::to_wstr_shim<const winstl::listview_sequence::sequence_value_type>
749        (const winstl::listview_sequence::sequence_value_type& v)
750{
751        return std::wstring(v.text().c_str());
752}
753
754template<>
755inline const std::wstring hal::to_wstr_shim<winstl::listview_sequence::sequence_value_type>
756        (winstl::listview_sequence::sequence_value_type& v)
757{
758        return std::wstring(v.text().c_str());
759}
760
761namespace boost {
762namespace serialization {
763        template <class TBase, typename AdapterTypeI>
764        struct version< CHaliteSortListViewCtrl<TBase, AdapterTypeI> >
765        {
766                typedef mpl::int_<2> type;
767                typedef mpl::integral_c_tag tag;
768                BOOST_STATIC_CONSTANT(unsigned int, value = version::type::value);                                                             
769        };
770}
771}
Note: See TracBrowser for help on using the repository browser.