00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00029 #ifndef _GG_ListBox_h_
00030 #define _GG_ListBox_h_
00031
00032 #include <GG/AlignmentFlags.h>
00033 #include <GG/ClrConstants.h>
00034 #include <GG/Control.h>
00035 #include <GG/Timer.h>
00036
00037 #include <set>
00038
00039 #include <boost/serialization/version.hpp>
00040
00041
00042 namespace GG {
00043
00044 class Font;
00045 class Scroll;
00046 class SubTexture;
00047 class WndEvent;
00048
00050 GG_FLAG_TYPE(ListBoxStyle);
00051 extern GG_API const ListBoxStyle LIST_NONE;
00052 extern GG_API const ListBoxStyle LIST_VCENTER;
00053 extern GG_API const ListBoxStyle LIST_TOP;
00054 extern GG_API const ListBoxStyle LIST_BOTTOM;
00055 extern GG_API const ListBoxStyle LIST_CENTER;
00056 extern GG_API const ListBoxStyle LIST_LEFT;
00057 extern GG_API const ListBoxStyle LIST_RIGHT;
00058 extern GG_API const ListBoxStyle LIST_NOSORT;
00059 extern GG_API const ListBoxStyle LIST_SORTDESCENDING;
00060 extern GG_API const ListBoxStyle LIST_NOSEL;
00061 extern GG_API const ListBoxStyle LIST_SINGLESEL;
00062 extern GG_API const ListBoxStyle LIST_QUICKSEL;
00063 extern GG_API const ListBoxStyle LIST_USERDELETE;
00064 extern GG_API const ListBoxStyle LIST_BROWSEUPDATES;
00065
00066
00102 class GG_API ListBox : public Control
00103 {
00104 public:
00113 template <class Cont>
00114 struct RowPtrIteratorLess
00115 {
00116 typedef typename Cont::iterator Iter;
00117 RowPtrIteratorLess();
00118 RowPtrIteratorLess(Cont* c);
00119 bool operator()(Iter lhs, Iter rhs) const;
00120 static bool LessThan(Iter lhs, Iter rhs, Iter end);
00121 private:
00122 Cont* m_container;
00123 };
00124
00149 struct GG_API Row : public Control
00150 {
00156 struct DeferAdjustLayout
00157 {
00158 DeferAdjustLayout(Row* row);
00159 ~DeferAdjustLayout();
00160 Row* const m_row;
00161 };
00162
00164 typedef std::string SortKeyType;
00165
00167 Row();
00168 Row(X w, Y h, const std::string& drag_drop_data_type, Alignment align = ALIGN_VCENTER, unsigned int margin = 2);
00169 virtual ~Row();
00171
00173 SortKeyType SortKey(std::size_t column) const;
00174 std::size_t size() const;
00175 bool empty() const;
00176
00177 Control* operator[](std::size_t n) const;
00178 Control* at(std::size_t n) const;
00179
00180 Alignment RowAlignment() const;
00181 Alignment ColAlignment(std::size_t n) const;
00182 X ColWidth(std::size_t n) const;
00183 unsigned int Margin() const;
00184
00185 Control* CreateControl(const std::string& str, const boost::shared_ptr<Font>& font, Clr color) const;
00186 Control* CreateControl(const SubTexture& st) const;
00187
00188
00190 virtual void Render();
00191
00192 void push_back(Control* c);
00193 void push_back(const std::string& str, const boost::shared_ptr<Font>& font, Clr color = CLR_BLACK);
00194 void push_back(const std::string& str, const std::string& font_filename, unsigned int pts, Clr color = CLR_BLACK);
00195 void push_back(const SubTexture& st);
00196 void clear();
00197 void resize(std::size_t n);
00198
00199 void SetCell(std::size_t n, Control* c);
00200 Control* RemoveCell(std::size_t n);
00201 void SetRowAlignment(Alignment align);
00202 void SetColAlignment(std::size_t n, Alignment align);
00203 void SetColWidth(std::size_t n, X width);
00204 void SetColAlignments(const std::vector<Alignment>& aligns);
00205 void SetColWidths(const std::vector<X>& widths);
00206 void SetMargin(unsigned int margin);
00207
00208
00209 private:
00210 void AdjustLayout(bool adjust_for_push_back = false);
00211
00212 std::vector<Control*> m_cells;
00213 Alignment m_row_alignment;
00214 std::vector<Alignment> m_col_alignments;
00215 std::vector<X> m_col_widths;
00216 unsigned int m_margin;
00217
00218 bool m_ignore_adjust_layout;
00219
00220 friend class DeferAdjustLayout;
00221
00222 friend class boost::serialization::access;
00223 template <class Archive>
00224 void serialize(Archive& ar, const unsigned int version);
00225 };
00226
00227 typedef std::list<Row*>::iterator iterator;
00228 typedef std::list<Row*>::const_iterator const_iterator;
00229 typedef std::list<Row*>::reverse_iterator reverse_iterator;
00230 typedef std::list<Row*>::const_reverse_iterator const_reverse_iterator;
00231
00232 typedef std::set<iterator, RowPtrIteratorLess<std::list<Row*> > > SelectionSet;
00233
00235 typedef boost::signal<void ()> ClearedSignalType;
00236 typedef boost::signal<void (const SelectionSet&)> SelChangedSignalType;
00237 typedef boost::signal<void (iterator)> RowSignalType;
00238 typedef boost::signal<void (const_iterator)> ConstRowSignalType;
00239 typedef boost::signal<void (iterator, const Pt&)> RowClickSignalType;
00240
00241 typedef RowSignalType InsertedSignalType;
00242 typedef RowSignalType DroppedSignalType;
00243 typedef ConstRowSignalType DropAcceptableSignalType;
00244 typedef RowClickSignalType LeftClickedSignalType;
00245 typedef RowClickSignalType RightClickedSignalType;
00246 typedef RowSignalType DoubleClickedSignalType;
00247 typedef RowSignalType ErasedSignalType;
00248 typedef RowSignalType BrowsedSignalType;
00249
00250
00252
00253 ListBox(X x, Y y, X w, Y h, Clr color, Clr interior = CLR_ZERO, Flags<WndFlag> flags = INTERACTIVE);
00254
00255 virtual ~ListBox();
00256
00257
00259 virtual void DropsAcceptable(DropsAcceptableIter first,
00260 DropsAcceptableIter last,
00261 const Pt& pt) const;
00262
00263 virtual Pt MinUsableSize() const;
00264 virtual Pt ClientUpperLeft() const;
00265 virtual Pt ClientLowerRight() const;
00266
00267 bool Empty() const;
00268 const_iterator begin() const;
00269 const_iterator end() const;
00270 const_reverse_iterator
00271 rbegin() const;
00272 const_reverse_iterator
00273 rend() const;
00274 const Row& GetRow(std::size_t n) const;
00275 iterator Caret() const;
00276 const SelectionSet&
00277 Selections() const;
00278 bool Selected(iterator it) const;
00279 Clr InteriorColor() const;
00280 Clr HiliteColor() const;
00281
00283 Flags<ListBoxStyle> Style() const;
00284
00285 const Row& ColHeaders() const;
00286 iterator FirstRowShown() const;
00287 std::size_t FirstColShown() const;
00288
00289 iterator LastVisibleRow() const;
00290 std::size_t LastVisibleCol() const;
00291
00292 std::size_t NumRows() const;
00293 std::size_t NumCols() const;
00294
00296 bool KeepColWidths() const;
00297
00301 std::size_t SortCol() const;
00302
00303 X ColWidth(std::size_t n) const;
00304 Alignment ColAlignment(std::size_t n) const;
00305 Alignment RowAlignment(iterator it) const;
00306
00310 const std::set<std::string>& AllowedDropTypes() const;
00311
00314 bool AutoScrollDuringDragDrops() const;
00315
00318 unsigned int AutoScrollMargin() const;
00319
00322 unsigned int AutoScrollInterval() const;
00323
00328 mutable ClearedSignalType ClearedSignal;
00329
00334 mutable InsertedSignalType InsertedSignal;
00335
00336 mutable SelChangedSignalType SelChangedSignal;
00337 mutable DroppedSignalType DroppedSignal;
00338 mutable DropAcceptableSignalType DropAcceptableSignal;
00339 mutable LeftClickedSignalType LeftClickedSignal;
00340 mutable RightClickedSignalType RightClickedSignal;
00341 mutable DoubleClickedSignalType DoubleClickedSignal;
00342 mutable ErasedSignalType ErasedSignal;
00343 mutable BrowsedSignalType BrowsedSignal;
00344
00345
00347 virtual void StartingChildDragDrop(const Wnd* wnd, const GG::Pt& offset);
00348 virtual void AcceptDrops(const std::vector<Wnd*>& wnds, const Pt& pt);
00349 virtual void ChildrenDraggedAway(const std::vector<Wnd*>& wnds, const Wnd* destination);
00350 virtual void Render();
00351
00352 virtual void SizeMove(const Pt& ul, const Pt& lr);
00353
00354 virtual void Disable(bool b = true);
00355 virtual void SetColor(Clr c);
00356
00360 iterator Insert(Row* row, iterator it);
00361
00365 iterator Insert(Row* row);
00366
00367 Row* Erase(iterator it);
00368 void Clear();
00369 void SelectRow(iterator it);
00370 void DeselectRow(iterator it);
00371 void SelectAll();
00372 void DeselectAll();
00373 iterator begin();
00374 iterator end();
00375 reverse_iterator
00376 rbegin();
00377 reverse_iterator
00378 rend();
00379 Row& GetRow(std::size_t n);
00380
00381 void SetSelections(const SelectionSet& s);
00382 void SetCaret(iterator it);
00383 void BringRowIntoView(iterator it);
00384
00385 void SetInteriorColor(Clr c);
00386 void SetHiliteColor(Clr c);
00387
00389 void SetStyle(Flags<ListBoxStyle> s);
00390
00391 void SetColHeaders(Row* r);
00392 void RemoveColHeaders();
00393
00394 void SetColWidth(std::size_t n, X w);
00395 void SetNumCols(std::size_t n);
00396 void SetSortCol(std::size_t n);
00397
00402 void SetSortCmp(const boost::function<bool (const Row&, const Row&, std::size_t)>& sort_cmp);
00403
00408 void LockColWidths();
00409
00412 void UnLockColWidths();
00413
00415 void SetColAlignment(std::size_t n, Alignment align);
00416
00418 void SetRowAlignment(iterator it, Alignment align);
00419
00422 void AllowDropType(const std::string& str);
00423
00428 void DisallowDropType(const std::string& str);
00429
00433 void AutoScrollDuringDragDrops(bool auto_scroll);
00434
00438 void SetAutoScrollMargin(unsigned int margin);
00439
00442 void SetAutoScrollInterval(unsigned int interval);
00443
00444 virtual void DefineAttributes(WndEditor* editor);
00446
00452 template <class RowType>
00453 struct DefaultRowCmp
00454 {
00456 bool operator()(const Row& lhs, const Row& rhs, std::size_t column) const;
00457 };
00458
00459 static const unsigned int BORDER_THICK;
00460
00462
00463 GG_ABSTRACT_EXCEPTION(Exception);
00464
00468 GG_CONCRETE_EXCEPTION(DontAcceptDrop, GG::ListBox, Exception);
00470
00471 protected:
00473 ListBox();
00474
00475
00477 X RightMargin() const;
00478 Y BottomMargin() const;
00479 unsigned int CellMargin() const;
00480
00481 iterator RowUnderPt(const Pt& pt) const;
00482
00483 iterator OldSelRow() const;
00484 iterator OldRDownRow() const;
00485 iterator LClickRow() const;
00486 iterator RClickRow() const;
00487
00488 bool AutoScrollingUp() const;
00489 bool AutoScrollingDown() const;
00490 bool AutoScrollingLeft() const;
00491 bool AutoScrollingRight() const;
00492
00493
00495 virtual void KeyPress(Key key, boost::uint32_t key_code_point, Flags<ModKey> mod_keys);
00496 virtual void MouseWheel(const Pt& pt, int move, Flags<ModKey> mod_keys);
00497 virtual void DragDropEnter(const Pt& pt, const std::map<Wnd*, Pt>& drag_drop_wnds, Flags<ModKey> mod_keys);
00498 virtual void DragDropHere(const Pt& pt, const std::map<Wnd*, Pt>& drag_drop_wnds, Flags<ModKey> mod_keys);
00499 virtual void DragDropLeave();
00500 virtual void TimerFiring(unsigned int ticks, Timer* timer);
00501
00502 virtual bool EventFilter(Wnd* w, const WndEvent& event);
00503
00504 iterator Insert(Row* row, iterator it, bool dropped);
00505 Row* Erase(iterator it, bool removing_duplicate, bool signal);
00506 void BringCaretIntoView();
00507 void RecreateScrolls();
00508 void ResetAutoScrollVars();
00509 void Resort();
00510
00511
00512 private:
00513 void ConnectSignals();
00514 void ValidateStyle();
00515 void AdjustScrolls(bool adjust_for_resize);
00516 void VScrolled(int tab_low, int tab_high, int low, int high);
00517 void HScrolled(int tab_low, int tab_high, int low, int high);
00518 void ClickAtRow(iterator it, Flags<ModKey> mod_keys);
00519 void NormalizeRow(Row* row);
00520 iterator FirstRowShownWhenBottomIs(iterator bottom_row, Y client_height);
00521 std::size_t FirstColShownWhenRightIs(std::size_t right_col, X client_width);
00522
00523 std::list<Row*> m_rows;
00524
00525 Scroll* m_vscroll;
00526 Scroll* m_hscroll;
00527 iterator m_caret;
00528 SelectionSet m_selections;
00529 iterator m_old_sel_row;
00530 bool m_old_sel_row_selected;
00531 iterator m_old_rdown_row;
00532 iterator m_lclick_row;
00533 iterator m_rclick_row;
00534 iterator m_last_row_browsed;
00535
00536 iterator m_first_row_shown;
00537 std::size_t m_first_col_shown;
00538 std::vector<X> m_col_widths;
00539 std::vector<Alignment>
00540 m_col_alignments;
00541 unsigned int m_cell_margin;
00542
00543 Clr m_int_color;
00544 Clr m_hilite_color;
00545 Flags<ListBoxStyle>
00546 m_style;
00547
00548 Row* m_header_row;
00549 bool m_keep_col_widths;
00550 bool m_clip_cells;
00551 std::size_t m_sort_col;
00552 boost::function<bool (const Row&, const Row&, std::size_t)>
00553 m_sort_cmp;
00554 std::set<std::string>
00555 m_allowed_drop_types;
00556
00557 bool m_auto_scroll_during_drag_drops;
00558 unsigned int m_auto_scroll_margin;
00559 bool m_auto_scrolling_up;
00560 bool m_auto_scrolling_down;
00561 bool m_auto_scrolling_left;
00562 bool m_auto_scrolling_right;
00563 Timer m_auto_scroll_timer;
00564
00565 iterator* m_iterator_being_erased;
00566
00567 friend class DropDownList;
00568
00569 friend class boost::serialization::access;
00570 template <class Archive>
00571 void serialize(Archive& ar, const unsigned int version);
00572 };
00573
00574 }
00575
00576
00577
00578 template <class Cont>
00579 GG::ListBox::RowPtrIteratorLess<Cont>::RowPtrIteratorLess() :
00580 m_container()
00581 { assert(m_container); }
00582
00583 template <class Cont>
00584 GG::ListBox::RowPtrIteratorLess<Cont>::RowPtrIteratorLess(Cont* c) :
00585 m_container(c)
00586 { assert(m_container); }
00587
00588 template <class Cont>
00589 bool GG::ListBox::RowPtrIteratorLess<Cont>::operator()(Iter lhs, Iter rhs) const
00590 {
00591
00592
00593
00594 BOOST_MPL_ASSERT((boost::is_same<typename Iter::value_type, ::GG::ListBox::Row*>));
00595 return LessThan(lhs, rhs, m_container->end());
00596 }
00597
00598 template <class Cont>
00599 bool GG::ListBox::RowPtrIteratorLess<Cont>::LessThan(Iter lhs, Iter rhs, Iter end)
00600 {
00601 return lhs == end ?
00602 false :
00603 (rhs == end ?
00604 true : (*lhs)->UpperLeft().y < (*rhs)->UpperLeft().y);
00605 }
00606
00607 template <class Archive>
00608 void GG::ListBox::Row::serialize(Archive& ar, const unsigned int version)
00609 {
00610 ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Control)
00611 & BOOST_SERIALIZATION_NVP(m_cells)
00612 & BOOST_SERIALIZATION_NVP(m_row_alignment)
00613 & BOOST_SERIALIZATION_NVP(m_col_alignments)
00614 & BOOST_SERIALIZATION_NVP(m_col_widths)
00615 & BOOST_SERIALIZATION_NVP(m_margin);
00616 }
00617
00618 template <class RowType>
00619 bool GG::ListBox::DefaultRowCmp<RowType>::operator()(const GG::ListBox::Row& lhs, const GG::ListBox::Row& rhs, std::size_t column) const
00620 {
00621 return static_cast<const RowType&>(lhs).SortKey(column) < static_cast<const RowType&>(rhs).SortKey(column);
00622 }
00623
00624 template <class Archive>
00625 void GG::ListBox::serialize(Archive& ar, const unsigned int version)
00626 {
00627 std::size_t caret_index = std::distance(m_rows.begin(), m_caret);
00628 std::size_t old_sel_row_index = std::distance(m_rows.begin(), m_old_sel_row);
00629 std::size_t old_rdown_row_index = std::distance(m_rows.begin(), m_old_rdown_row);
00630 std::size_t lclick_row_index = std::distance(m_rows.begin(), m_lclick_row);
00631 std::size_t rclick_row_index = std::distance(m_rows.begin(), m_rclick_row);
00632 std::size_t last_row_browsed_index = std::distance(m_rows.begin(), m_last_row_browsed);
00633 std::size_t first_row_shown_index = std::distance(m_rows.begin(), m_first_row_shown);
00634 std::set<std::size_t> selection_indices;
00635
00636 if (Archive::is_saving::value) {
00637 for (SelectionSet::iterator it = m_selections.begin(); it != m_selections.end(); ++it) {
00638 selection_indices.insert(std::distance(m_rows.begin(), *it));
00639 }
00640 }
00641
00642 ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Control)
00643 & BOOST_SERIALIZATION_NVP(m_rows)
00644 & BOOST_SERIALIZATION_NVP(m_vscroll)
00645 & BOOST_SERIALIZATION_NVP(m_hscroll)
00646 & BOOST_SERIALIZATION_NVP(caret_index)
00647 & BOOST_SERIALIZATION_NVP(selection_indices)
00648 & BOOST_SERIALIZATION_NVP(old_sel_row_index)
00649 & BOOST_SERIALIZATION_NVP(m_old_sel_row_selected)
00650 & BOOST_SERIALIZATION_NVP(old_rdown_row_index)
00651 & BOOST_SERIALIZATION_NVP(lclick_row_index)
00652 & BOOST_SERIALIZATION_NVP(rclick_row_index)
00653 & BOOST_SERIALIZATION_NVP(last_row_browsed_index)
00654 & BOOST_SERIALIZATION_NVP(first_row_shown_index)
00655 & BOOST_SERIALIZATION_NVP(m_first_col_shown)
00656 & BOOST_SERIALIZATION_NVP(m_col_widths)
00657 & BOOST_SERIALIZATION_NVP(m_col_alignments)
00658 & BOOST_SERIALIZATION_NVP(m_cell_margin)
00659 & BOOST_SERIALIZATION_NVP(m_int_color)
00660 & BOOST_SERIALIZATION_NVP(m_hilite_color)
00661 & BOOST_SERIALIZATION_NVP(m_style)
00662 & BOOST_SERIALIZATION_NVP(m_header_row)
00663 & BOOST_SERIALIZATION_NVP(m_keep_col_widths)
00664 & BOOST_SERIALIZATION_NVP(m_clip_cells)
00665 & BOOST_SERIALIZATION_NVP(m_sort_col)
00666 & BOOST_SERIALIZATION_NVP(m_allowed_drop_types)
00667 & BOOST_SERIALIZATION_NVP(m_auto_scroll_during_drag_drops)
00668 & BOOST_SERIALIZATION_NVP(m_auto_scroll_margin)
00669 & BOOST_SERIALIZATION_NVP(m_auto_scrolling_up)
00670 & BOOST_SERIALIZATION_NVP(m_auto_scrolling_down)
00671 & BOOST_SERIALIZATION_NVP(m_auto_scrolling_left)
00672 & BOOST_SERIALIZATION_NVP(m_auto_scrolling_right)
00673 & BOOST_SERIALIZATION_NVP(m_auto_scroll_timer);
00674
00675 if (Archive::is_loading::value) {
00676 m_caret = boost::next(m_rows.begin(), caret_index);
00677 m_old_sel_row = boost::next(m_rows.begin(), old_sel_row_index);
00678 m_old_rdown_row = boost::next(m_rows.begin(), old_rdown_row_index);
00679 m_lclick_row = boost::next(m_rows.begin(), lclick_row_index);
00680 m_rclick_row = boost::next(m_rows.begin(), rclick_row_index);
00681 m_last_row_browsed = boost::next(m_rows.begin(), last_row_browsed_index);
00682 m_first_row_shown = boost::next(m_rows.begin(), first_row_shown_index);
00683
00684 for (std::set<std::size_t>::iterator it = selection_indices.begin(); it != selection_indices.end(); ++it) {
00685 m_selections.insert(boost::next(m_rows.begin(), *it));
00686 }
00687
00688 ValidateStyle();
00689 ConnectSignals();
00690 }
00691 }
00692
00693 #endif // _GG_ListBox_h_