47 #if !defined (USE_FINAL_H) && !defined (COMPILE_FINAL_CUT) 48 #error "Only <final/final.h> can be included directly." 52 #include <unordered_map> 56 #include "final/fwidget.h" 57 #include "final/util/fdata.h" 58 #include "final/widget/fscrollbar.h" 75 template <
typename DT = std::
nullptr_t>
79 auto getClassName()
const ->
FString;
80 auto getText()
const ->
FString;
81 template <
typename DT>
82 auto getData()
const -> clean_fdata_t<DT>&;
86 template <
typename DT>
90 auto isSelected()
const -> bool;
97 using FDataAccessPtr = std::shared_ptr<FDataAccess>;
104 FDataAccessPtr data_pointer{};
105 BracketType brackets{BracketType::None};
106 bool selected{
false};
115 template <
typename DT>
116 inline FListBoxItem::FListBoxItem (
const FString& txt, DT&& data)
117 : text{stringFilter(txt)}
118 , data_pointer{makeFData(std::forward<DT>(data))}
122 inline auto FListBoxItem::getClassName()
const ->
FString 123 {
return "FListBoxItem"; }
126 inline auto FListBoxItem::getText()
const ->
FString 130 template <
typename DT>
131 inline auto FListBoxItem::getData()
const -> clean_fdata_t<DT>&
137 inline void FListBoxItem::setText (
const FString& txt)
139 text.setString(stringFilter(txt));
143 template <
typename DT>
144 inline void FListBoxItem::setData (DT&& data)
146 auto data_obj = makeFData(std::forward<DT>(data));
147 data_pointer = std::move(data_obj);
151 inline auto FListBoxItem::isSelected()
const ->
bool 155 inline void FListBoxItem::clear()
159 inline auto FListBoxItem::stringFilter (
const FString& txt) ->
FString 162 .expandTabs(FVTerm::getFOutput()->getTabstop())
165 .replaceControlCodes();
177 using FWidget::setGeometry;
178 using FListBoxItems = std::vector<FListBoxItem>;
182 template <
typename Iterator
183 ,
typename InsertConverter>
185 template <
typename Container
186 ,
typename LazyConverter>
187 FListBox (Container, LazyConverter&&,
FWidget* =
nullptr);
190 FListBox (
const FListBox&) =
delete;
193 FListBox (FListBox&&) noexcept =
delete;
196 ~FListBox()
override;
199 auto operator = (
const FListBox&) -> FListBox& =
delete;
202 auto operator = (FListBox&&) noexcept -> FListBox& =
delete;
205 auto getClassName()
const ->
FString override;
206 auto getCount()
const -> std::size_t;
208 auto getItem (std::size_t)
const & ->
const FListBoxItem&;
209 auto getItem (FListBoxItems::iterator) & ->
FListBoxItem&;
210 auto getItem (FListBoxItems::const_iterator)
const & ->
const FListBoxItem&;
211 auto currentItem()
const noexcept -> std::size_t;
212 auto getData() & -> FListBoxItems&;
213 auto getData()
const & ->
const FListBoxItems&;
217 void setCurrentItem (std::size_t);
218 void setCurrentItem (FListBoxItems::iterator);
219 void selectItem (std::size_t);
220 void selectItem (FListBoxItems::iterator)
const;
221 void unselectItem (std::size_t);
222 void unselectItem (FListBoxItems::iterator)
const;
223 void showInsideBrackets (
const std::size_t, BracketType);
224 void showNoBrackets (std::size_t);
225 void showNoBrackets (FListBoxItems::iterator)
const;
226 void setSize (
const FSize&,
bool =
true)
override;
227 void setGeometry (
const FPoint&,
const FSize&,
bool =
true)
override;
228 void setMultiSelection (
bool =
true);
229 void unsetMultiSelection ();
230 void setDisable()
override;
234 auto isSelected (std::size_t)
const -> bool;
235 auto isSelected (FListBoxItems::iterator)
const -> bool;
236 auto isMultiSelection()
const -> bool;
237 auto hasBrackets (std::size_t)
const -> bool;
238 auto hasBrackets (FListBoxItems::iterator)
const -> bool;
241 void hide()
override;
242 template <
typename Iterator
243 ,
typename InsertConverter>
244 void insert (Iterator, Iterator,
const InsertConverter&);
245 template <
typename Container
246 ,
typename LazyConverter>
247 void insert (
const Container&, LazyConverter&&);
248 template <
typename Container
249 ,
typename LazyConverter>
250 void insert (Container*, LazyConverter&&);
253 ,
typename DT = std::nullptr_t>
254 void insert (
const std::initializer_list<T>& list
255 , BracketType = BracketType::None
258 template <
typename ItemT
259 ,
typename DT = std::nullptr_t>
260 void insert (
const ItemT&
261 , BracketType = BracketType::None
264 void remove (std::size_t);
265 auto findItem (
const FString&) -> FListBoxItems::iterator;
266 void reserve (std::size_t);
282 void initLayout()
override;
283 void adjustYOffset (std::size_t);
284 void adjustSize()
override;
288 using KeyMap = std::unordered_map<FKey, std::function<void()>,
EnumHash<FKey>>;
289 using KeyMapResult = std::unordered_map<FKey, std::function<bool()>, EnumHash<FKey>>;
290 using LazyInsert = std::function<void(FListBoxItem&, FDataAccess*, std::size_t)>;
291 using FWidgetColorsptr = std::shared_ptr<FWidgetColors>;
295 FListBoxItems itemlist{};
300 KeyMapResult key_map_result{};
303 struct SelectionState
305 std::size_t current{0};
306 int last_current{-1};
307 int select_from_item{-1};
308 bool multi_select{
false};
309 bool mouse_select{
false};
310 bool click_on_list{
false};
313 struct ScrollingState
315 FScrollBarPtr vbar{
nullptr};
316 FScrollBarPtr hbar{
nullptr};
319 int last_yoffset{-1};
328 std::size_t bracket_space{0};
329 std::size_t inc_len{0};
331 std::size_t text_width{0};
332 std::size_t column_width{0};
336 enum class ConvertType : uInt8
344 static auto getString (FListBoxItems::iterator) ->
FString;
347 auto isHorizontallyScrollable()
const -> bool;
348 auto isVerticallyScrollable()
const -> bool;
349 auto isCurrentLine (
int)
const -> bool;
350 auto isDragSelect()
const -> bool;
351 auto canSkipDragScrolling() -> bool;
355 void mapKeyFunctions();
357 void draw()
override;
358 void drawBorder()
override;
359 void drawScrollBars()
const;
361 auto canSkipDrawing()
const -> bool;
362 auto calculateNumberItemsToDraw()
const -> std::size_t;
363 auto canRedrawPartialList()
const -> bool;
364 void updateRedrawParameters (std::size_t&, std::size_t&)
const;
365 void finalizeDrawing();
367 void drawListLine (
int, FListBoxItems::iterator,
bool);
368 void printLeftBracket (BracketType);
369 template<
class UnaryPred>
370 void printLeftBracket_if (BracketType, UnaryPred);
371 void printRightBracket (BracketType);
372 template<
class UnaryPred>
373 void printRightBracket_if (BracketType, ElementData&, UnaryPred);
374 void setCurrentFocusedElementColor()
const;
375 void drawListBracketsLine (
int, FListBoxItems::iterator,
bool);
376 void printElement (
const ElementData&);
377 auto shouldPrintRightBracket (
const ElementData&, std::size_t)
const -> bool;
378 void printLeftCurrentLineArrow (
int);
379 void printRightCurrentLineArrow (
int);
380 void printRemainingSpacesFromPos (std::size_t);
381 void setInitialLineAttributes (
bool)
const;
382 void setCurrentLineAttributes (
int,
bool,
bool,
bool&);
383 void setSelectedCurrentLineAttributes (
int);
384 void setUnselectedCurrentLineAttributes (
int,
bool,
bool&);
385 void setLineAttributes (
int,
bool,
bool,
bool&);
386 auto getMaxWidth()
const -> std::size_t;
387 void unsetAttributes()
const;
388 void updateDrawing (
bool,
bool);
389 void recalculateHorizontalBar (std::size_t,
bool);
390 void recalculateVerticalBar (std::size_t)
const;
391 void multiSelection (std::size_t);
392 void multiSelectionUpTo (std::size_t);
394 void wheelDown (
int);
395 void wheelLeft (
int);
396 void wheelRight (
int);
397 auto dragScrollUp() -> bool;
398 auto dragScrollDown() -> bool;
399 void dragUp (MouseButton);
400 void dragDown (MouseButton);
401 void stopDragScroll();
402 void prevListItem (
int);
403 void nextListItem (
int);
404 void scrollToX (
int);
405 void scrollToY (
int);
406 void scrollLeft (
int);
407 void scrollRight (
int);
416 auto isWithinListBounds (
const FPoint&)
const -> bool;
417 auto skipIncrementalSearch() -> bool;
418 auto isNonSelectMouseButtonPressed (
const FMouseEvent*)
const -> bool;
419 template <
typename MultiSelectionFunction>
420 void handleMouseWithinListBounds (
const FMouseEvent*,
const MultiSelectionFunction&);
422 void acceptSelection();
423 auto spacebarProcessing() -> bool;
424 auto changeSelectionAndPosition() -> bool;
425 auto deletePreviousCharacter() -> bool;
426 auto keyIncSearchInput (FKey) -> bool;
427 void processClick()
const;
428 void processSelect()
const;
429 void processRowChanged()
const;
430 void processChanged()
const;
431 void changeOnResize()
const;
432 void updateScrollBarAfterRemoval (std::size_t);
433 auto getScrollBarMaxHorizontal()
const noexcept -> int;
434 auto getScrollBarMaxVertical()
const noexcept -> int;
435 void recalculateMaximumLineWidth();
436 void lazyConvert (FListBoxItems::iterator, std::size_t);
437 auto index2iterator (std::size_t) -> FListBoxItems::iterator;
438 auto index2iterator (std::size_t index)
const -> FListBoxItems::const_iterator;
439 void handleSelectionChange (
const std::size_t);
440 void handleXOffsetChange (
const int);
441 void handleVerticalScrollBarUpdate (
const FScrollBar::ScrollType,
const int)
const;
442 void handleHorizontalScrollBarUpdate (
const FScrollBar::ScrollType,
const int)
const;
443 auto getVerticalScrollDistance (
const FScrollBar::ScrollType)
const -> int;
444 auto getHorizontalScrollDistance (
const FScrollBar::ScrollType)
const -> int;
447 void cb_vbarChange (
const FWidget*);
448 void cb_hbarChange (
const FWidget*);
451 LazyInsert lazy_inserter{};
454 std::size_t nf_offset{0};
455 std::size_t max_line_width{0};
457 ScrollingState scroll{};
458 SelectionState selection{};
459 ConvertType conv_type{ConvertType::None};
460 DragScrollMode drag_scroll{DragScrollMode::None};
465 namespace flistboxhelper
468 template <
typename Container>
469 constexpr
auto getContainer(
FDataAccess* container) -> clean_fdata_t<Container>&
478 template <
typename Iterator
479 ,
typename InsertConverter>
480 inline FListBox::FListBox ( Iterator first
482 , InsertConverter convert
488 while ( first != last )
490 insert(convert(first), BracketType::None,
false, &(*first));
496 template <
typename Container
497 ,
typename LazyConverter>
498 inline FListBox::FListBox ( Container container
499 , LazyConverter&& convert
504 insert (container, std::forward<LazyConverter>(convert));
508 inline auto FListBox::getClassName()
const ->
FString 509 {
return "FListBox"; }
512 inline auto FListBox::getCount()
const -> std::size_t
513 {
return data.itemlist.size(); }
516 inline auto FListBox::getItem (std::size_t index) & ->
FListBoxItem&
518 auto iter = index2iterator(index - 1);
523 inline auto FListBox::getItem (std::size_t index)
const & ->
const FListBoxItem&
525 auto iter = index2iterator(index - 1);
530 inline auto FListBox::getItem (FListBoxItems::iterator iter) & ->
FListBoxItem&
534 inline auto FListBox::getItem (FListBoxItems::const_iterator iter)
const & ->
const FListBoxItem&
538 inline auto FListBox::currentItem()
const noexcept -> std::size_t
539 {
return selection.current; }
542 inline auto FListBox::getData() & -> FListBoxItems&
543 {
return data.itemlist; }
546 inline auto FListBox::getData()
const & ->
const FListBoxItems&
547 {
return data.itemlist; }
550 inline auto FListBox::getText() & ->
FString&
551 {
return data.text; }
554 inline void FListBox::selectItem (std::size_t index)
555 { index2iterator(index - 1)->selected =
true; }
558 inline void FListBox::selectItem (FListBoxItems::iterator iter)
const 559 { iter->selected =
true; }
562 inline void FListBox::unselectItem (std::size_t index)
563 { index2iterator(index - 1)->selected =
false; }
566 inline void FListBox::unselectItem (FListBoxItems::iterator iter)
const 567 { iter->selected =
false; }
570 inline void FListBox::showNoBrackets (std::size_t index)
571 { index2iterator(index - 1)->brackets = BracketType::None; }
574 inline void FListBox::showNoBrackets (FListBoxItems::iterator iter)
const 575 { iter->brackets = BracketType::None; }
578 inline void FListBox::setMultiSelection (
bool enable)
579 { selection.multi_select = enable; }
582 inline void FListBox::unsetMultiSelection()
583 { setMultiSelection(
false); }
586 inline void FListBox::setDisable()
587 { setEnable(
false); }
590 inline auto FListBox::isSelected (std::size_t index)
const ->
bool 591 {
return index2iterator(index - 1)->selected; }
594 inline auto FListBox::isSelected (FListBoxItems::iterator iter)
const ->
bool 595 {
return iter->selected; }
598 inline auto FListBox::isMultiSelection()
const ->
bool 599 {
return selection.multi_select; }
602 inline auto FListBox::hasBrackets(std::size_t index)
const ->
bool 603 {
return index2iterator(index - 1)->brackets != BracketType::None; }
606 inline auto FListBox::hasBrackets(FListBoxItems::iterator iter)
const ->
bool 607 {
return iter->brackets != BracketType::None; }
610 inline void FListBox::reserve (std::size_t new_cap)
611 { data.itemlist.reserve(new_cap); }
614 template <
typename Iterator
615 ,
typename InsertConverter>
616 inline void FListBox::insert ( Iterator first
618 ,
const InsertConverter& convert )
620 conv_type = ConvertType::Direct;
622 while ( first != last )
624 insert (convert(first), BracketType::None,
false, &(*first));
630 template <
typename Container
631 ,
typename LazyConverter>
632 void FListBox::insert (
const Container& container, LazyConverter&& converter)
634 conv_type = ConvertType::Lazy;
635 data.source_container = makeFData(container).release();
636 lazy_inserter = std::forward<LazyConverter>(converter);
637 const std::size_t size = container.size();
640 data.itemlist.resize(size);
642 recalculateVerticalBar(size);
646 template <
typename Container
647 ,
typename LazyConverter>
648 void FListBox::insert (Container* container, LazyConverter&& converter)
650 insert (*container, std::forward<LazyConverter>(converter));
656 void FListBox::insert (
const std::initializer_list<T>& list
661 for (
const auto& item : list)
664 listItem.brackets = b;
665 listItem.selected = s;
671 template <
typename ItemT
673 void FListBox::insert (
const ItemT& item
679 listItem.brackets = b;
680 listItem.selected = s;
685 inline auto FListBox::isHorizontallyScrollable()
const ->
bool 686 {
return max_line_width + 1 >= getClientWidth(); }
689 inline auto FListBox::isVerticallyScrollable()
const ->
bool 690 {
return getCount() > getClientHeight(); }
693 inline auto FListBox::isCurrentLine (
int y)
const ->
bool 694 {
return y + scroll.yoffset + 1 == int(selection.current); }
697 template<
class UnaryPred>
698 inline void FListBox::printLeftBracket_if ( BracketType bracket_type
702 printLeftBracket(bracket_type);
706 template<
class UnaryPred>
707 inline void FListBox::printRightBracket_if ( BracketType bracket_type
714 if ( elem.search_mark && elem.text.getLength() == elem.inc_len )
715 setCurrentFocusedElementColor();
717 printRightBracket (bracket_type);
722 inline auto FListBox::getMaxWidth()
const -> std::size_t
723 {
return getWidth() - nf_offset - 4; }
727 FListBox::index2iterator (std::size_t index) -> FListBoxItems::iterator
729 auto iter = data.itemlist.begin();
730 using distance_type = FListBoxItems::difference_type;
731 std::advance (iter, distance_type(index));
737 FListBox::index2iterator (std::size_t index)
const -> FListBoxItems::const_iterator
739 auto iter = data.itemlist.begin();
740 using distance_type = FListBoxItems::difference_type;
741 std::advance (iter, distance_type(index));
Definition: flistbox.h:173
Definition: class_template.cpp:25
Definition: flistbox.h:71