JUCE-7.0.12-0-g4f43011b96 JUCE-7.0.12-0-g4f43011b96
JUCE — C++ application framework with suport for VST, VST3, LV2 audio plug-ins

« « « Anklang Documentation
Loading...
Searching...
No Matches
juce_ListBox.cpp
Go to the documentation of this file.
1 /*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 By using JUCE, you agree to the terms of both the JUCE 7 End-User License
11 Agreement and JUCE Privacy Policy.
12
13 End User License Agreement: www.juce.com/juce-7-licence
14 Privacy Policy: www.juce.com/juce-privacy-policy
15
16 Or: You may also use this code under the terms of the GPL v3 (see
17 www.gnu.org/licenses).
18
19 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
20 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
21 DISCLAIMED.
22
23 ==============================================================================
24*/
25
26namespace juce
27{
28
29template <typename RowComponentType>
30static AccessibilityActions getListRowAccessibilityActions (RowComponentType& rowComponent)
31{
32 auto onFocus = [&rowComponent]
33 {
34 rowComponent.getOwner().scrollToEnsureRowIsOnscreen (rowComponent.getRow());
35 rowComponent.getOwner().selectRow (rowComponent.getRow());
36 };
37
38 auto onPress = [&rowComponent, onFocus]
39 {
40 onFocus();
41 rowComponent.getOwner().keyPressed (KeyPress (KeyPress::returnKey));
42 };
43
44 auto onToggle = [&rowComponent]
45 {
46 rowComponent.getOwner().flipRowSelection (rowComponent.getRow());
47 };
48
49 return AccessibilityActions().addAction (AccessibilityActionType::focus, std::move (onFocus))
50 .addAction (AccessibilityActionType::press, std::move (onPress))
51 .addAction (AccessibilityActionType::toggle, std::move (onToggle));
52}
53
54void ListBox::checkModelPtrIsValid() const
55{
56 #if ! JUCE_DISABLE_ASSERTIONS
57 // If this is hit, the model was destroyed while the ListBox was still using it.
58 // You should ensure that the model remains alive for as long as the ListBox holds a pointer to it.
59 // If this assertion is hit in the destructor of a ListBox instance, do one of the following:
60 // - Adjust the order in which your destructors run, so that the ListBox destructor runs
61 // before the destructor of your ListBoxModel, or
62 // - Call ListBox::setModel (nullptr) before destroying your ListBoxModel.
63 jassert ((model == nullptr) == (weakModelPtr.lock() == nullptr));
64 #endif
65}
66
67//==============================================================================
68/* The ListBox and TableListBox rows both have similar mouse behaviours, which are implemented here. */
69template <typename Base>
71{
72 auto& getOwner() const { return asBase().getOwner(); }
73
74public:
75 void updateRowAndSelection (const int newRow, const bool nowSelected)
76 {
77 const auto rowChanged = std::exchange (row, newRow) != newRow;
78 const auto selectionChanged = std::exchange (selected, nowSelected) != nowSelected;
79
80 if (rowChanged || selectionChanged)
81 repaint();
82 }
83
84 void mouseDown (const MouseEvent& e) override
85 {
86 isDragging = false;
87 isDraggingToScroll = false;
88 selectRowOnMouseUp = false;
89
90 if (! asBase().isEnabled())
91 return;
92
93 const auto select = getOwner().getRowSelectedOnMouseDown()
94 && ! selected
95 && ! detail::ViewportHelpers::wouldScrollOnEvent (getOwner().getViewport(), e.source) ;
96 if (select)
97 asBase().performSelection (e, false);
98 else
99 selectRowOnMouseUp = true;
100 }
101
102 void mouseUp (const MouseEvent& e) override
103 {
104 if (asBase().isEnabled() && selectRowOnMouseUp && ! (isDragging || isDraggingToScroll))
105 asBase().performSelection (e, true);
106 }
107
108 void mouseDrag (const MouseEvent& e) override
109 {
110 if (auto* m = getModel (getOwner()))
111 {
112 if (asBase().isEnabled() && e.mouseWasDraggedSinceMouseDown() && ! isDragging)
113 {
115
116 if (getOwner().getRowSelectedOnMouseDown() || getOwner().isRowSelected (row))
117 rowsToDrag = getOwner().getSelectedRows();
118 else
119 rowsToDrag.addRange (Range<int>::withStartAndLength (row, 1));
120
121 if (! rowsToDrag.isEmpty())
122 {
123 auto dragDescription = m->getDragSourceDescription (rowsToDrag);
124
125 if (! (dragDescription.isVoid() || (dragDescription.isString() && dragDescription.toString().isEmpty())))
126 {
127 isDragging = true;
128 getOwner().startDragAndDrop (e, rowsToDrag, dragDescription, m->mayDragToExternalWindows());
129 }
130 }
131 }
132 }
133
134 if (! isDraggingToScroll)
135 if (auto* vp = getOwner().getViewport())
136 isDraggingToScroll = vp->isCurrentlyScrollingOnDrag();
137 }
138
139 int getRow() const { return row; }
140 bool isSelected() const { return selected; }
141
142private:
143 const Base& asBase() const { return *static_cast<const Base*> (this); }
144 Base& asBase() { return *static_cast< Base*> (this); }
145
146 static TableListBoxModel* getModel (TableListBox& x) { return x.getTableListBoxModel(); }
147 static ListBoxModel* getModel (ListBox& x) { return x.getListBoxModel(); }
148
149 int row = -1;
150 bool selected = false, isDragging = false, isDraggingToScroll = false, selectRowOnMouseUp = false;
151};
152
153//==============================================================================
155 public ComponentWithListRowMouseBehaviours<RowComponent>
156{
157public:
158 explicit RowComponent (ListBox& lb) : owner (lb) {}
159
160 void paint (Graphics& g) override
161 {
162 if (auto* m = owner.getListBoxModel())
163 m->paintListBoxItem (getRow(), g, getWidth(), getHeight(), isSelected());
164 }
165
166 void update (const int newRow, const bool nowSelected)
167 {
168 updateRowAndSelection (newRow, nowSelected);
169
170 if (auto* m = owner.getListBoxModel())
171 {
172 setMouseCursor (m->getMouseCursorForRow (getRow()));
173
174 customComponent.reset (m->refreshComponentForRow (newRow, nowSelected, customComponent.release()));
175
176 if (customComponent != nullptr)
177 {
178 addAndMakeVisible (customComponent.get());
179 customComponent->setBounds (getLocalBounds());
180
182 }
183 else
184 {
186 }
187 }
188 }
189
190 void performSelection (const MouseEvent& e, bool isMouseUp)
191 {
192 owner.selectRowsBasedOnModifierKeys (getRow(), e.mods, isMouseUp);
193
194 if (auto* m = owner.getListBoxModel())
195 m->listBoxItemClicked (getRow(), e);
196 }
197
198 void mouseDoubleClick (const MouseEvent& e) override
199 {
200 if (isEnabled())
201 if (auto* m = owner.getListBoxModel())
202 m->listBoxItemDoubleClicked (getRow(), e);
203 }
204
205 void resized() override
206 {
207 if (customComponent != nullptr)
208 customComponent->setBounds (getLocalBounds());
209 }
210
212 {
213 if (auto* m = owner.getListBoxModel())
214 return m->getTooltipForRow (getRow());
215
216 return {};
217 }
218
220 {
221 return std::make_unique<RowAccessibilityHandler> (*this);
222 }
223
224 ListBox& getOwner() const { return owner; }
225
226 Component* getCustomComponent() const { return customComponent.get(); }
227
228private:
229 //==============================================================================
230 class RowAccessibilityHandler final : public AccessibilityHandler
231 {
232 public:
233 explicit RowAccessibilityHandler (RowComponent& rowComponentToWrap)
234 : AccessibilityHandler (rowComponentToWrap,
235 AccessibilityRole::listItem,
236 getListRowAccessibilityActions (rowComponentToWrap),
237 { std::make_unique<RowCellInterface> (*this) }),
238 rowComponent (rowComponentToWrap)
239 {
240 }
241
242 String getTitle() const override
243 {
244 if (auto* m = rowComponent.owner.getListBoxModel())
245 return m->getNameForRow (rowComponent.getRow());
246
247 return {};
248 }
249
250 String getHelp() const override { return rowComponent.getTooltip(); }
251
252 AccessibleState getCurrentState() const override
253 {
254 if (auto* m = rowComponent.owner.getListBoxModel())
255 if (rowComponent.getRow() >= m->getNumRows())
256 return AccessibleState().withIgnored();
257
259
260 if (rowComponent.owner.multipleSelection)
261 state = state.withMultiSelectable();
262 else
263 state = state.withSelectable();
264
265 if (rowComponent.isSelected())
266 state = state.withSelected();
267
268 return state;
269 }
270
271 private:
272 class RowCellInterface final : public AccessibilityCellInterface
273 {
274 public:
275 explicit RowCellInterface (RowAccessibilityHandler& h) : handler (h) {}
276
277 int getDisclosureLevel() const override { return 0; }
278
279 const AccessibilityHandler* getTableHandler() const override
280 {
281 return handler.rowComponent.owner.getAccessibilityHandler();
282 }
283
284 private:
285 RowAccessibilityHandler& handler;
286 };
287
288 RowComponent& rowComponent;
289 };
290
291 //==============================================================================
292 ListBox& owner;
293 std::unique_ptr<Component> customComponent;
294
296};
297
298
299//==============================================================================
301 private Timer
302{
303public:
304 ListViewport (ListBox& lb) : owner (lb)
305 {
306 setWantsKeyboardFocus (false);
307
308 struct IgnoredComponent final : public Component
309 {
310 std::unique_ptr<AccessibilityHandler> createAccessibilityHandler() override
311 {
312 return createIgnoredAccessibilityHandler (*this);
313 }
314 };
315
316 auto content = std::make_unique<IgnoredComponent>();
317 content->setWantsKeyboardFocus (false);
318
319 setViewedComponent (content.release());
320 }
321
322 int getIndexOfFirstVisibleRow() const { return jmax (0, firstIndex - 1); }
323
324 RowComponent* getComponentForRowIfOnscreen (int row) const noexcept
325 {
326 const auto startIndex = getIndexOfFirstVisibleRow();
327
328 return (startIndex <= row && row < startIndex + (int) rows.size())
329 ? rows[(size_t) (row % jmax (1, (int) rows.size()))].get()
330 : nullptr;
331 }
332
333 int getRowNumberOfComponent (const Component* const rowComponent) const noexcept
334 {
335 const auto iter = std::find_if (rows.begin(), rows.end(), [=] (auto& ptr) { return ptr.get() == rowComponent; });
336
337 if (iter == rows.end())
338 return -1;
339
340 const auto index = (int) std::distance (rows.begin(), iter);
341 const auto mod = jmax (1, (int) rows.size());
342 const auto startIndex = getIndexOfFirstVisibleRow();
343
344 return index + mod * ((startIndex / mod) + (index < (startIndex % mod) ? 1 : 0));
345 }
346
347 void visibleAreaChanged (const Rectangle<int>&) override
348 {
349 updateVisibleArea (true);
350
351 if (auto* m = owner.getListBoxModel())
352 m->listWasScrolled();
353
354 startTimer (50);
355 }
356
357 void updateVisibleArea (const bool makeSureItUpdatesContent)
358 {
359 hasUpdated = false;
360
361 auto& content = *getViewedComponent();
362 auto newX = content.getX();
363 auto newY = content.getY();
364 auto newW = jmax (owner.minimumRowWidth, getMaximumVisibleWidth());
365 auto newH = owner.totalItems * owner.getRowHeight();
366
369
370 content.setBounds (newX, newY, newW, newH);
371
372 if (makeSureItUpdatesContent && ! hasUpdated)
373 updateContents();
374 }
375
376 void updateContents()
377 {
378 hasUpdated = true;
379 auto rowH = owner.getRowHeight();
380 auto& content = *getViewedComponent();
381
382 if (rowH > 0)
383 {
384 auto y = getViewPositionY();
385 auto w = content.getWidth();
386
387 const auto numNeeded = (size_t) (4 + getMaximumVisibleHeight() / rowH);
388 rows.resize (jmin (numNeeded, rows.size()));
389
390 while (numNeeded > rows.size())
391 {
392 rows.emplace_back (new RowComponent (owner));
393 content.addAndMakeVisible (*rows.back());
394 }
395
396 firstIndex = y / rowH;
397 firstWholeIndex = (y + rowH - 1) / rowH;
398 lastWholeIndex = (y + getMaximumVisibleHeight() - 1) / rowH;
399
400 const auto startIndex = getIndexOfFirstVisibleRow();
401 const auto lastIndex = startIndex + (int) rows.size();
402
403 for (auto row = startIndex; row < lastIndex; ++row)
404 {
405 if (auto* rowComp = getComponentForRowIfOnscreen (row))
406 {
407 rowComp->setBounds (0, row * rowH, w, rowH);
408 rowComp->update (row, owner.isRowSelected (row));
409 }
410 else
411 {
413 }
414 }
415 }
416
417 if (owner.headerComponent != nullptr)
418 owner.headerComponent->setBounds (owner.outlineThickness + content.getX(),
419 owner.outlineThickness,
420 jmax (owner.getWidth() - owner.outlineThickness * 2,
421 content.getWidth()),
422 owner.headerComponent->getHeight());
423 }
424
425 void selectRow (const int row, const int rowH, const bool dontScroll,
426 const int lastSelectedRow, const int totalRows, const bool isMouseClick)
427 {
428 hasUpdated = false;
429
430 if (row < firstWholeIndex && ! dontScroll)
431 {
433 }
434 else if (row >= lastWholeIndex && ! dontScroll)
435 {
436 const int rowsOnScreen = lastWholeIndex - firstWholeIndex;
437
438 if (row >= lastSelectedRow + rowsOnScreen
439 && rowsOnScreen < totalRows - 1
440 && ! isMouseClick)
441 {
443 jlimit (0, jmax (0, totalRows - rowsOnScreen), row) * rowH);
444 }
445 else
446 {
448 jmax (0, (row + 1) * rowH - getMaximumVisibleHeight()));
449 }
450 }
451
452 if (! hasUpdated)
453 updateContents();
454 }
455
456 void scrollToEnsureRowIsOnscreen (const int row, const int rowH)
457 {
458 if (row < firstWholeIndex)
459 {
461 }
462 else if (row >= lastWholeIndex)
463 {
465 jmax (0, (row + 1) * rowH - getMaximumVisibleHeight()));
466 }
467 }
468
469 void paint (Graphics& g) override
470 {
471 if (isOpaque())
473 }
474
475 bool keyPressed (const KeyPress& key) override
476 {
477 if (Viewport::respondsToKey (key))
478 {
479 const int allowableMods = owner.multipleSelection ? ModifierKeys::shiftModifier : 0;
480
481 if ((key.getModifiers().getRawFlags() & ~allowableMods) == 0)
482 {
483 // we want to avoid these keypresses going to the viewport, and instead allow
484 // them to pass up to our listbox..
485 return false;
486 }
487 }
488
489 return Viewport::keyPressed (key);
490 }
491
492private:
493 std::unique_ptr<AccessibilityHandler> createAccessibilityHandler() override
494 {
496 }
497
498 void timerCallback() override
499 {
500 stopTimer();
501
502 if (auto* handler = owner.getAccessibilityHandler())
503 handler->notifyAccessibilityEvent (AccessibilityEvent::structureChanged);
504 }
505
506 ListBox& owner;
508 int firstIndex = 0, firstWholeIndex = 0, lastWholeIndex = 0;
509 bool hasUpdated = false;
510
512};
513
514//==============================================================================
516{
518 {
519 owner.addMouseListener (this, true);
520 }
521
523 {
524 owner.removeMouseListener (this);
525 }
526
527 void mouseMove (const MouseEvent& e) override
528 {
529 auto pos = e.getEventRelativeTo (&owner).position.toInt();
530 owner.selectRow (owner.getRowContainingPosition (pos.x, pos.y), true);
531 }
532
533 void mouseExit (const MouseEvent& e) override
534 {
535 mouseMove (e);
536 }
537
538 ListBox& owner;
540};
541
542
543//==============================================================================
544ListBox::ListBox (const String& name, ListBoxModel* const m)
545 : Component (name)
546{
547 viewport.reset (new ListViewport (*this));
548 addAndMakeVisible (viewport.get());
549
553
554 assignModelPtr (m);
555}
556
558{
559 headerComponent.reset();
560 viewport.reset();
561}
562
563void ListBox::assignModelPtr (ListBoxModel* const newModel)
564{
565 model = newModel;
566
567 #if ! JUCE_DISABLE_ASSERTIONS
568 weakModelPtr = model != nullptr ? model->sharedState : nullptr;
569 #endif
570}
571
573{
574 if (model != newModel)
575 {
576 assignModelPtr (newModel);
577 repaint();
579 }
580}
581
582void ListBox::setMultipleSelectionEnabled (bool b) noexcept { multipleSelection = b; }
583void ListBox::setClickingTogglesRowSelection (bool b) noexcept { alwaysFlipSelection = b; }
584void ListBox::setRowSelectedOnMouseDown (bool b) noexcept { selectOnMouseDown = b; }
585
587{
588 if (b)
589 {
590 if (mouseMoveSelector == nullptr)
591 mouseMoveSelector.reset (new ListBoxMouseMoveSelector (*this));
592 }
593 else
594 {
595 mouseMoveSelector.reset();
596 }
597}
598
599//==============================================================================
601{
602 if (! hasDoneInitialUpdate)
604
606}
607
609{
610 if (outlineThickness > 0)
611 {
613 g.drawRect (getLocalBounds(), outlineThickness);
614 }
615}
616
618{
619 viewport->setBoundsInset (BorderSize<int> (outlineThickness + (headerComponent != nullptr ? headerComponent->getHeight() : 0),
620 outlineThickness, outlineThickness, outlineThickness));
621
622 viewport->setSingleStepSizes (20, getRowHeight());
623
624 viewport->updateVisibleArea (false);
625}
626
628{
629 viewport->updateVisibleArea (true);
630}
631
633{
634 return viewport.get();
635}
636
637//==============================================================================
639{
640 checkModelPtrIsValid();
641 hasDoneInitialUpdate = true;
642 totalItems = (model != nullptr) ? model->getNumRows() : 0;
643
644 bool selectionChanged = false;
645
646 if (selected.size() > 0 && selected [selected.size() - 1] >= totalItems)
647 {
648 selected.removeRange ({ totalItems, std::numeric_limits<int>::max() });
649 lastRowSelected = getSelectedRow (0);
650 selectionChanged = true;
651 }
652
653 viewport->updateVisibleArea (isVisible());
654 viewport->resized();
655
656 if (selectionChanged)
657 {
658 if (model != nullptr)
659 model->selectedRowsChanged (lastRowSelected);
660
661 if (auto* handler = getAccessibilityHandler())
662 handler->notifyAccessibilityEvent (AccessibilityEvent::rowSelectionChanged);
663 }
664}
665
666//==============================================================================
668{
669 selectRowInternal (row, dontScroll, deselectOthersFirst, false);
670}
671
672void ListBox::selectRowInternal (const int row,
673 bool dontScroll,
675 bool isMouseClick)
676{
677 checkModelPtrIsValid();
678
679 if (! multipleSelection)
680 deselectOthersFirst = true;
681
682 if ((! isRowSelected (row))
684 {
685 if (isPositiveAndBelow (row, totalItems))
686 {
688 selected.clear();
689
690 selected.addRange ({ row, row + 1 });
691
692 if (getHeight() == 0 || getWidth() == 0)
693 dontScroll = true;
694
695 viewport->selectRow (row, getRowHeight(), dontScroll,
696 lastRowSelected, totalItems, isMouseClick);
697
698 lastRowSelected = row;
699 model->selectedRowsChanged (row);
700
701 if (auto* handler = getAccessibilityHandler())
702 handler->notifyAccessibilityEvent (AccessibilityEvent::rowSelectionChanged);
703 }
704 else
705 {
708 }
709 }
710}
711
712void ListBox::deselectRow (const int row)
713{
714 checkModelPtrIsValid();
715
716 if (selected.contains (row))
717 {
718 selected.removeRange ({ row, row + 1 });
719
720 if (row == lastRowSelected)
721 lastRowSelected = getSelectedRow (0);
722
723 viewport->updateContents();
724 model->selectedRowsChanged (lastRowSelected);
725
726 if (auto* handler = getAccessibilityHandler())
727 handler->notifyAccessibilityEvent (AccessibilityEvent::rowSelectionChanged);
728 }
729}
730
733{
734 checkModelPtrIsValid();
735
736 selected = setOfRowsToBeSelected;
737 selected.removeRange ({ totalItems, std::numeric_limits<int>::max() });
738
739 if (! isRowSelected (lastRowSelected))
740 lastRowSelected = getSelectedRow (0);
741
742 viewport->updateContents();
743
744 if (model != nullptr && sendNotificationEventToModel == sendNotification)
745 model->selectedRowsChanged (lastRowSelected);
746
747 if (auto* handler = getAccessibilityHandler())
748 handler->notifyAccessibilityEvent (AccessibilityEvent::rowSelectionChanged);
749}
750
752{
753 return selected;
754}
755
757{
758 if (multipleSelection && (firstRow != lastRow))
759 {
760 const int numRows = totalItems - 1;
761 firstRow = jlimit (0, jmax (0, numRows), firstRow);
762 lastRow = jlimit (0, jmax (0, numRows), lastRow);
763
764 selected.addRange ({ jmin (firstRow, lastRow),
765 jmax (firstRow, lastRow) + 1 });
766
767 selected.removeRange ({ lastRow, lastRow + 1 });
768 }
769
770 selectRowInternal (lastRow, dontScrollToShowThisRange, false, true);
771}
772
773void ListBox::flipRowSelection (const int row)
774{
775 if (isRowSelected (row))
776 deselectRow (row);
777 else
778 selectRowInternal (row, false, false, true);
779}
780
782{
783 checkModelPtrIsValid();
784
785 if (! selected.isEmpty())
786 {
787 selected.clear();
788 lastRowSelected = -1;
789
790 viewport->updateContents();
791
792 if (model != nullptr)
793 model->selectedRowsChanged (lastRowSelected);
794
795 if (auto* handler = getAccessibilityHandler())
796 handler->notifyAccessibilityEvent (AccessibilityEvent::rowSelectionChanged);
797 }
798}
799
801 ModifierKeys mods,
802 const bool isMouseUpEvent)
803{
804 if (multipleSelection && (mods.isCommandDown() || alwaysFlipSelection))
805 {
806 flipRowSelection (row);
807 }
808 else if (multipleSelection && mods.isShiftDown() && lastRowSelected >= 0)
809 {
810 selectRangeOfRows (lastRowSelected, row);
811 }
812 else if ((! mods.isPopupMenu()) || ! isRowSelected (row))
813 {
814 selectRowInternal (row, false, ! (multipleSelection && (! isMouseUpEvent) && isRowSelected (row)), true);
815 }
816}
817
819{
820 return selected.size();
821}
822
823int ListBox::getSelectedRow (const int index) const
824{
825 return (isPositiveAndBelow (index, selected.size()))
826 ? selected [index] : -1;
827}
828
829bool ListBox::isRowSelected (const int row) const
830{
831 return selected.contains (row);
832}
833
835{
836 return isRowSelected (lastRowSelected) ? lastRowSelected : -1;
837}
838
839//==============================================================================
840int ListBox::getRowContainingPosition (const int x, const int y) const noexcept
841{
842 if (isPositiveAndBelow (x, getWidth()))
843 {
844 const int row = (viewport->getViewPositionY() + y - viewport->getY()) / rowHeight;
845
846 if (isPositiveAndBelow (row, totalItems))
847 return row;
848 }
849
850 return -1;
851}
852
853int ListBox::getInsertionIndexForPosition (const int x, const int y) const noexcept
854{
855 if (isPositiveAndBelow (x, getWidth()))
856 return jlimit (0, totalItems, (viewport->getViewPositionY() + y + rowHeight / 2 - viewport->getY()) / rowHeight);
857
858 return -1;
859}
860
861Component* ListBox::getComponentForRowNumber (const int row) const noexcept
862{
863 if (auto* listRowComp = viewport->getComponentForRowIfOnscreen (row))
864 return listRowComp->getCustomComponent();
865
866 return nullptr;
867}
868
869int ListBox::getRowNumberOfComponent (const Component* const rowComponent) const noexcept
870{
871 return viewport->getRowNumberOfComponent (rowComponent);
872}
873
875{
876 auto y = viewport->getY() + rowHeight * rowNumber;
877
879 y -= viewport->getViewPositionY();
880
881 return { viewport->getX(), y,
882 viewport->getViewedComponent()->getWidth(), rowHeight };
883}
884
886{
887 auto offscreen = viewport->getViewedComponent()->getHeight() - viewport->getHeight();
888
889 viewport->setViewPosition (viewport->getViewPositionX(),
891}
892
894{
895 auto offscreen = viewport->getViewedComponent()->getHeight() - viewport->getHeight();
896
897 return offscreen > 0 ? viewport->getViewPositionY() / (double) offscreen
898 : 0;
899}
900
902{
903 return viewport->getViewWidth();
904}
905
907{
908 viewport->scrollToEnsureRowIsOnscreen (row, getRowHeight());
909}
910
911//==============================================================================
913{
914 checkModelPtrIsValid();
915
916 const int numVisibleRows = viewport->getHeight() / getRowHeight();
917
918 const bool multiple = multipleSelection
919 && lastRowSelected >= 0
920 && key.getModifiers().isShiftDown();
921
922 if (key.isKeyCode (KeyPress::upKey))
923 {
924 if (multiple)
925 selectRangeOfRows (lastRowSelected, lastRowSelected - 1);
926 else
927 selectRow (jmax (0, lastRowSelected - 1));
928 }
929 else if (key.isKeyCode (KeyPress::downKey))
930 {
931 if (multiple)
932 selectRangeOfRows (lastRowSelected, lastRowSelected + 1);
933 else
934 selectRow (jmin (totalItems - 1, jmax (0, lastRowSelected + 1)));
935 }
936 else if (key.isKeyCode (KeyPress::pageUpKey))
937 {
938 if (multiple)
939 selectRangeOfRows (lastRowSelected, lastRowSelected - numVisibleRows);
940 else
941 selectRow (jmax (0, jmax (0, lastRowSelected) - numVisibleRows));
942 }
943 else if (key.isKeyCode (KeyPress::pageDownKey))
944 {
945 if (multiple)
946 selectRangeOfRows (lastRowSelected, lastRowSelected + numVisibleRows);
947 else
948 selectRow (jmin (totalItems - 1, jmax (0, lastRowSelected) + numVisibleRows));
949 }
950 else if (key.isKeyCode (KeyPress::homeKey))
951 {
952 if (multiple)
953 selectRangeOfRows (lastRowSelected, 0);
954 else
955 selectRow (0);
956 }
957 else if (key.isKeyCode (KeyPress::endKey))
958 {
959 if (multiple)
960 selectRangeOfRows (lastRowSelected, totalItems - 1);
961 else
962 selectRow (totalItems - 1);
963 }
964 else if (key.isKeyCode (KeyPress::returnKey) && isRowSelected (lastRowSelected))
965 {
966 if (model != nullptr)
967 model->returnKeyPressed (lastRowSelected);
968 }
970 && isRowSelected (lastRowSelected))
971 {
972 if (model != nullptr)
973 model->deleteKeyPressed (lastRowSelected);
974 }
975 else if (multipleSelection && key == KeyPress ('a', ModifierKeys::commandModifier, 0))
976 {
978 }
979 else
980 {
981 return false;
982 }
983
984 return true;
985}
986
998
1000{
1001 bool eventWasUsed = false;
1002
1003 if (! approximatelyEqual (wheel.deltaX, 0.0f) && getHorizontalScrollBar().isVisible())
1004 {
1005 eventWasUsed = true;
1007 }
1008
1009 if (! approximatelyEqual (wheel.deltaY, 0.0f) && getVerticalScrollBar().isVisible())
1010 {
1011 eventWasUsed = true;
1013 }
1014
1015 if (! eventWasUsed)
1017}
1018
1020{
1021 checkModelPtrIsValid();
1022
1023 if (e.mouseWasClicked() && model != nullptr)
1024 model->backgroundClicked (e);
1025}
1026
1027//==============================================================================
1029{
1030 rowHeight = jmax (1, newHeight);
1031 viewport->setSingleStepSizes (20, rowHeight);
1032 updateContent();
1033}
1034
1036{
1037 return viewport->getMaximumVisibleHeight() / rowHeight;
1038}
1039
1041{
1042 minimumRowWidth = newMinimumWidth;
1043 updateContent();
1044}
1045
1046int ListBox::getVisibleContentWidth() const noexcept { return viewport->getMaximumVisibleWidth(); }
1047
1048ScrollBar& ListBox::getVerticalScrollBar() const noexcept { return viewport->getVerticalScrollBar(); }
1049ScrollBar& ListBox::getHorizontalScrollBar() const noexcept { return viewport->getHorizontalScrollBar(); }
1050
1052{
1054 viewport->setOpaque (isOpaque());
1055 repaint();
1056}
1057
1062
1064{
1065 outlineThickness = newThickness;
1066 resized();
1067}
1068
1070{
1071 headerComponent = std::move (newHeaderComponent);
1072 addAndMakeVisible (headerComponent.get());
1075}
1076
1077bool ListBox::hasAccessibleHeaderComponent() const
1078{
1079 return headerComponent != nullptr
1080 && headerComponent->getAccessibilityHandler() != nullptr;
1081}
1082
1083void ListBox::repaintRow (const int rowNumber) noexcept
1084{
1085 repaint (getRowPosition (rowNumber, true));
1086}
1087
1089{
1091 auto firstRow = getRowContainingPosition (0, viewport->getY());
1092
1093 for (int i = getNumRowsOnScreen() + 2; --i >= 0;)
1094 {
1095 if (rows.contains (firstRow + i))
1096 {
1097 if (auto* rowComp = viewport->getComponentForRowIfOnscreen (firstRow + i))
1098 {
1099 auto pos = getLocalPoint (rowComp, Point<int>());
1100
1101 imageArea = imageArea.getUnion ({ pos.x, pos.y, rowComp->getWidth(), rowComp->getHeight() });
1102 }
1103 }
1104 }
1105
1106 imageArea = imageArea.getIntersection (getLocalBounds());
1107 imageX = imageArea.getX();
1108 imageY = imageArea.getY();
1109
1110 const auto additionalScale = 2.0f;
1113 roundToInt ((float) imageArea.getWidth() * listScale),
1114 roundToInt ((float) imageArea.getHeight() * listScale),
1115 true);
1116
1117 for (int i = getNumRowsOnScreen() + 2; --i >= 0;)
1118 {
1119 if (rows.contains (firstRow + i))
1120 {
1121 if (auto* rowComp = viewport->getComponentForRowIfOnscreen (firstRow + i))
1122 {
1123 Graphics g (snapshot);
1125
1127
1128 if (g.reduceClipRegion (rowComp->getLocalBounds() * rowScale))
1129 {
1130 g.beginTransparencyLayer (0.6f);
1132 rowComp->paintEntireComponent (g, false);
1134 }
1135 }
1136 }
1137 }
1138
1139 return { snapshot, additionalScale };
1140}
1141
1142void ListBox::startDragAndDrop (const MouseEvent& e, const SparseSet<int>& rowsToDrag, const var& dragDescription, bool allowDraggingToOtherWindows)
1143{
1145 {
1146 int x, y;
1148
1149 auto p = Point<int> (x, y) - e.getEventRelativeTo (this).position.toInt();
1151 }
1152 else
1153 {
1154 // to be able to do a drag-and-drop operation, the listbox needs to
1155 // be inside a component which is also a DragAndDropContainer.
1157 }
1158}
1159
1161{
1163 {
1164 public:
1165 explicit TableInterface (ListBox& listBoxToWrap)
1166 : listBox (listBoxToWrap)
1167 {
1168 }
1169
1170 int getNumRows() const override
1171 {
1172 listBox.checkModelPtrIsValid();
1173
1174 return listBox.model != nullptr ? listBox.model->getNumRows()
1175 : 0;
1176 }
1177
1178 int getNumColumns() const override
1179 {
1180 return 1;
1181 }
1182
1183 const AccessibilityHandler* getHeaderHandler() const override
1184 {
1185 if (listBox.hasAccessibleHeaderComponent())
1186 return listBox.headerComponent->getAccessibilityHandler();
1187
1188 return nullptr;
1189 }
1190
1191 const AccessibilityHandler* getRowHandler (int row) const override
1192 {
1193 if (auto* rowComponent = listBox.viewport->getComponentForRowIfOnscreen (row))
1194 return rowComponent->getAccessibilityHandler();
1195
1196 return nullptr;
1197 }
1198
1199 const AccessibilityHandler* getCellHandler (int, int) const override
1200 {
1201 return nullptr;
1202 }
1203
1204 Optional<Span> getRowSpan (const AccessibilityHandler& handler) const override
1205 {
1206 const auto rowNumber = listBox.getRowNumberOfComponent (&handler.getComponent());
1207
1208 return rowNumber != -1 ? makeOptional (Span { rowNumber, 1 })
1209 : nullopt;
1210 }
1211
1212 Optional<Span> getColumnSpan (const AccessibilityHandler&) const override
1213 {
1214 return Span { 0, 1 };
1215 }
1216
1217 void showCell (const AccessibilityHandler& h) const override
1218 {
1219 if (const auto row = getRowSpan (h))
1220 listBox.scrollToEnsureRowIsOnscreen (row->begin);
1221 }
1222
1223 private:
1224 ListBox& listBox;
1225
1227 };
1228
1229 return std::make_unique<AccessibilityHandler> (*this,
1230 AccessibilityRole::list,
1232 AccessibilityHandler::Interfaces { std::make_unique<TableInterface> (*this) });
1233}
1234
1235//==============================================================================
1237{
1238 jassert (existingComponentToUpdate == nullptr); // indicates a failure in the code that recycles the components
1239 return nullptr;
1240}
1241
1253
1254} // namespace juce
select
A simple wrapper for building a collection of supported accessibility actions and corresponding callb...
Base class for accessible Components.
virtual AccessibleState getCurrentState() const
Returns the current state of the UI element.
const Component & getComponent() const noexcept
Returns the Component that this handler represents.
An abstract interface which represents a UI element that supports a table interface.
AccessibleState withAccessibleOffscreen() const noexcept
Sets the accessible offscreen flag and returns the new state.
AccessibleState withSelectable() const noexcept
Sets the selectable flag and returns the new state.
AccessibleState withSelected() const noexcept
Sets the selected flag and returns the new state.
AccessibleState withMultiSelectable() const noexcept
Sets the multiSelectable flag and returns the new state.
static AffineTransform scale(float factorX, float factorY) noexcept
Returns a new transform which is a re-scale about the origin.
Specifies a set of gaps to be left around the sides of a rectangle.
void mouseDrag(const MouseEvent &e) override
Called when the mouse is moved while a button is held down.
void mouseUp(const MouseEvent &e) override
Called when a mouse button is released.
void mouseDown(const MouseEvent &e) override
Called when a mouse button is pressed.
The base class for all JUCE user-interface objects.
bool isVisible() const noexcept
Tests whether the component is visible or not.
bool isOpaque() const noexcept
Returns true if no parts of this component are transparent.
void setFocusContainerType(FocusContainerType containerType) noexcept
Sets whether this component is a container for components that can have their focus traversed,...
int getHeight() const noexcept
Returns the component's height in pixels.
Point< int > getLocalPoint(const Component *sourceComponent, Point< int > pointRelativeToSourceComponent) const
Converts a point to be relative to this component's coordinate space.
static float JUCE_CALLTYPE getApproximateScaleFactorForComponent(const Component *targetComponent)
Returns the approximate scale factor for a given component by traversing its parent hierarchy and app...
void addAndMakeVisible(Component *child, int zOrder=-1)
Adds a child component to this one, and also makes the child visible if it isn't already.
void addMouseListener(MouseListener *newListener, bool wantsEventsForAllNestedChildComponents)
Registers a listener to be told when mouse events occur in this component.
AccessibilityHandler * getAccessibilityHandler()
Returns the accessibility handler for this component, or nullptr if this component is not accessible.
void setOpaque(bool shouldBeOpaque)
Indicates whether any parts of the component might be transparent.
void setMouseCursor(const MouseCursor &cursorType)
Changes the mouse cursor shape to use when the mouse is over this component.
void repaint()
Marks the whole component as needing to be redrawn.
@ none
The component will not act as a focus container.
@ focusContainer
The component will act as a top-level component within which focus is passed around.
void removeMouseListener(MouseListener *listenerToRemove)
Deregisters a mouse listener.
void setWantsKeyboardFocus(bool wantsFocus) noexcept
Sets a flag to indicate whether this component wants keyboard focus or not.
Colour findColour(int colourID, bool inheritFromParent=false) const
Looks for a colour that has been registered with the given colour ID number.
int getWidth() const noexcept
Returns the component's width in pixels.
void mouseWheelMove(const MouseEvent &event, const MouseWheelDetails &wheel) override
Called when the mouse-wheel is moved.
bool isEnabled() const noexcept
Returns true if the component (and all its parents) are enabled.
Rectangle< int > getLocalBounds() const noexcept
Returns the component's bounds, relative to its own origin.
void invalidateAccessibilityHandler()
Invalidates the AccessibilityHandler that is currently being used for this component.
static DragAndDropContainer * findParentDragContainerFor(Component *childComponent)
Utility to find the DragAndDropContainer for a given Component.
A graphics context, used for drawing a component or image.
void drawRect(int x, int y, int width, int height, int lineThickness=1) const
Draws a rectangular outline, using the current colour or brush.
void endTransparencyLayer()
Completes a drawing operation to a temporary semi-transparent buffer.
void addTransform(const AffineTransform &transform)
Adds a transformation which will be performed on all the graphics operations that the context subsequ...
void beginTransparencyLayer(float layerOpacity)
Begins rendering to an off-screen bitmap which will later be flattened onto the current context with ...
bool reduceClipRegion(int x, int y, int width, int height)
Intersects the current clipping region with another region.
void setColour(Colour newColour)
Changes the current drawing colour.
void fillAll() const
Fills the context's entire clip region with the current colour or brush.
void setOrigin(Point< int > newOrigin)
Moves the position of the context's origin.
Holds a fixed-size bitmap.
Definition juce_Image.h:58
@ ARGB
< each pixel is a 4-byte ARGB premultiplied colour value.
Definition juce_Image.h:67
Represents a key press, including any modifier keys that are needed.
static const int homeKey
key-code for the home key
static const int upKey
key-code for the cursor-up key
static bool isKeyCurrentlyDown(int keyCode)
Checks whether a particular key is held down, irrespective of modifiers.
static const int endKey
key-code for the end key
bool isKeyCode(int keyCodeToCompare) const noexcept
Checks whether the KeyPress's key is the same as the one provided, without checking the modifiers.
static const int deleteKey
key-code for the delete key (not backspace)
ModifierKeys getModifiers() const noexcept
Returns the key modifiers.
static const int downKey
key-code for the cursor-down key
static const int returnKey
key-code for the return key
static const int pageUpKey
key-code for the page-up key
static const int pageDownKey
key-code for the page-down key
static const int backspaceKey
key-code for the backspace key
A subclass of this is used to drive a ListBox.
virtual void deleteKeyPressed(int lastRowSelected)
Override this to be informed when the delete key is pressed.
virtual void returnKeyPressed(int lastRowSelected)
Override this to be informed when the return key is pressed.
virtual Component * refreshComponentForRow(int rowNumber, bool isRowSelected, Component *existingComponentToUpdate)
This is used to create or update a custom component to go in a row of the list.
virtual void listBoxItemDoubleClicked(int row, const MouseEvent &)
This can be overridden to react to the user double-clicking on a row.
virtual String getTooltipForRow(int row)
You can override this to provide tool tips for specific rows.
virtual var getDragSourceDescription(const SparseSet< int > &rowsToDescribe)
To allow rows from your list to be dragged-and-dropped, implement this method.
virtual int getNumRows()=0
This has to return the number of items in the list.
virtual void listBoxItemClicked(int row, const MouseEvent &)
This can be overridden to react to the user clicking on a row.
virtual void listWasScrolled()
Override this to be informed when the list is scrolled.
virtual String getNameForRow(int rowNumber)
This can be overridden to return a name for the specified row.
virtual void backgroundClicked(const MouseEvent &)
This can be overridden to react to the user clicking on a part of the list where there are no rows.
virtual MouseCursor getMouseCursorForRow(int row)
You can override this to return a custom mouse cursor for each row.
virtual void selectedRowsChanged(int lastRowSelected)
Override this to be informed when rows are selected or deselected.
void paint(Graphics &g) override
Components can override this method to draw their content.
bool keyPressed(const KeyPress &key) override
Called when a key is pressed.
void visibleAreaChanged(const Rectangle< int > &) override
Callback method that is called when the visible area changes.
void resized() override
Called when this component's size has been changed.
void paint(Graphics &g) override
Components can override this method to draw their content.
void mouseDoubleClick(const MouseEvent &e) override
Called when a mouse button has been double-clicked on a component.
String getTooltip() override
Returns the string that this object wants to show as its tooltip.
std::unique_ptr< AccessibilityHandler > createAccessibilityHandler() override
Override this method to return a custom AccessibilityHandler for this component.
A list of items that can be scrolled vertically.
void setMultipleSelectionEnabled(bool shouldBeEnabled) noexcept
Turns on multiple-selection of rows.
void deselectRow(int rowNumber)
Deselects a row.
int getRowContainingPosition(int x, int y) const noexcept
Finds the row index that contains a given x,y position.
ListBox(const String &componentName=String(), ListBoxModel *model=nullptr)
Creates a ListBox.
bool keyStateChanged(bool isKeyDown) override
Called when a key is pressed or released.
int getVisibleRowWidth() const noexcept
Returns the width of a row (which may be less than the width of this component if there's a scrollbar...
int getRowNumberOfComponent(const Component *rowComponent) const noexcept
Returns the row number that the given component represents.
void parentHierarchyChanged() override
Called to indicate that the component's parents have changed.
void deselectAllRows()
Deselects any currently selected rows.
void setRowHeight(int newHeight)
Sets the height of each row in the list.
int getSelectedRow(int index=0) const
Returns the row number of a selected row.
virtual ScaledImage createSnapshotOfRows(const SparseSet< int > &rows, int &x, int &y)
This fairly obscure method creates an image that shows the row components specified in rows (for exam...
void scrollToEnsureRowIsOnscreen(int row)
Scrolls if necessary to make sure that a particular row is visible.
bool isRowSelected(int rowNumber) const
Checks whether a row is selected.
void paint(Graphics &) override
Components can override this method to draw their content.
void setMouseMoveSelectsRows(bool shouldSelect)
Makes the list react to mouse moves by selecting the row that the mouse if over.
int getLastRowSelected() const
Returns the last row that the user selected.
void mouseUp(const MouseEvent &) override
Called when a mouse button is released.
~ListBox() override
Destructor.
ScrollBar & getVerticalScrollBar() const noexcept
Returns a reference to the vertical scrollbar.
Viewport * getViewport() const noexcept
Returns the viewport that this ListBox uses.
void setMinimumContentWidth(int newMinimumWidth)
Changes the width of the rows in the list.
void setOutlineThickness(int outlineThickness)
Sets the thickness of a border that will be drawn around the box.
void colourChanged() override
This method is called when a colour is changed by the setColour() method, or when the look-and-feel i...
void selectRangeOfRows(int firstRow, int lastRow, bool dontScrollToShowThisRange=false)
Selects a set of rows.
void visibilityChanged() override
Called when this component's visibility changes.
int getInsertionIndexForPosition(int x, int y) const noexcept
Finds a row index that would be the most suitable place to insert a new item for a given position.
void repaintRow(int rowNumber) noexcept
Repaints one of the rows.
void setSelectedRows(const SparseSet< int > &setOfRowsToBeSelected, NotificationType sendNotificationEventToModel=sendNotification)
Sets the rows that should be selected, based on an explicit set of ranges.
void setModel(ListBoxModel *newModel)
Changes the current data model to display.
Component * getComponentForRowNumber(int rowNumber) const noexcept
Finds the row component for a given row in the list.
void setClickingTogglesRowSelection(bool flipRowSelection) noexcept
If enabled, this makes the listbox flip the selection status of each row that the user clicks,...
@ backgroundColourId
The background colour to fill the list with.
@ outlineColourId
An optional colour to use to draw a border around the list.
void setRowSelectedOnMouseDown(bool isSelectedOnMouseDown) noexcept
Sets whether a row should be selected when the mouse is pressed or released.
void paintOverChildren(Graphics &) override
Components can override this method to draw over the top of their children.
int getVisibleContentWidth() const noexcept
Returns the space currently available for the row items, taking into account borders,...
ScrollBar & getHorizontalScrollBar() const noexcept
Returns a reference to the horizontal scrollbar.
void flipRowSelection(int rowNumber)
Selects or deselects a row.
Rectangle< int > getRowPosition(int rowNumber, bool relativeToComponentTopLeft) const noexcept
Returns the position of one of the rows, relative to the top-left of the listbox.
double getVerticalPosition() const
Returns the current vertical position as a proportion of the total.
bool keyPressed(const KeyPress &) override
Called when a key is pressed.
int getNumRowsOnScreen() const noexcept
Returns the number of rows actually visible.
void updateContent()
Causes the list to refresh its content.
ListBoxModel * getListBoxModel() const noexcept
Returns the current list model.
int getNumSelectedRows() const
Returns the number of rows that are currently selected.
int getRowHeight() const noexcept
Returns the height of a row in the list.
void mouseWheelMove(const MouseEvent &, const MouseWheelDetails &) override
Called when the mouse-wheel is moved.
void setHeaderComponent(std::unique_ptr< Component > newHeaderComponent)
Sets a component that the list should use as a header.
SparseSet< int > getSelectedRows() const
Returns a sparse set indicating the rows that are currently selected.
void selectRow(int rowNumber, bool dontScrollToShowThisRow=false, bool deselectOthersFirst=true)
Selects a row.
void setVerticalPosition(double newProportion)
Scrolls the list to a particular position.
void resized() override
Called when this component's size has been changed.
void selectRowsBasedOnModifierKeys(int rowThatWasClickedOn, ModifierKeys modifiers, bool isMouseUpEvent)
Multiply-selects rows based on the modifier keys.
std::unique_ptr< AccessibilityHandler > createAccessibilityHandler() override
Override this method to return a custom AccessibilityHandler for this component.
Represents the state of the mouse buttons and modifier keys.
bool isCommandDown() const noexcept
Checks whether the 'command' key flag is set (or 'ctrl' on Windows/Linux).
int getRawFlags() const noexcept
Returns the raw flags for direct testing.
bool isPopupMenu() const noexcept
Checks whether the user is trying to launch a pop-up menu.
bool isShiftDown() const noexcept
Checks whether the shift key's flag is set.
@ commandModifier
Command key flag - on windows this is the same as the CTRL key flag.
@ shiftModifier
Shift key flag.
Represents a mouse cursor image.
@ NormalCursor
The standard arrow cursor.
Contains position and status information about a mouse event.
MouseInputSource source
The source device that generated this event.
MouseEvent getEventRelativeTo(Component *newComponent) const noexcept
Creates a version of this event that is relative to a different component.
const Point< float > position
The position of the mouse when the event occurred.
bool mouseWasDraggedSinceMouseDown() const noexcept
Returns true if the user seems to be performing a drag gesture.
bool mouseWasClicked() const noexcept
Returns true if the mouse event is part of a click gesture rather than a drag.
A MouseListener can be registered with a component to receive callbacks about mouse events that happe...
A simple optional type.
A pair of (x, y) coordinates.
Definition juce_Point.h:42
constexpr Point< int > toInt() const noexcept
Casts this point to a Point<int> object.
Definition juce_Point.h:236
A general-purpose range object, that simply represents any linear range with a start and end point.
Definition juce_Range.h:40
Manages a rectangle and allows geometric operations to be performed on it.
ValueType getY() const noexcept
Returns the y coordinate of the rectangle's top edge.
An image that will be resampled before it is drawn.
A scrollbar component.
void mouseWheelMove(const MouseEvent &, const MouseWheelDetails &) override
Called when the mouse-wheel is moved.
A non-owning view over contiguous objects stored in an Array or vector or other similar container.
Definition juce_Span.h:96
Holds a set of primitive values, storing them as a set of ranges.
void clear()
Clears the set.
Type size() const noexcept
Returns the number of values in the set.
void addRange(Range< Type > range)
Adds a range of contiguous values to the set.
bool isEmpty() const noexcept
Checks whether the set is empty.
bool contains(Type valueToLookFor) const noexcept
Checks whether a particular value is in the set.
void removeRange(Range< Type > rangeToRemove)
Removes a range of values from the set.
The JUCE String class!
Definition juce_String.h:53
Makes repeated callbacks to a virtual method at a specified time interval.
Definition juce_Timer.h:52
void stopTimer() noexcept
Stops the timer.
void startTimer(int intervalInMilliseconds) noexcept
Starts the timer and sets the length of interval required.
Components that want to use pop-up tooltips should implement this interface.
A Viewport is used to contain a larger child component, and allows the child to be automatically scro...
Component * getViewedComponent() const noexcept
Returns the component that's currently being used inside the Viewport.
int getViewPositionX() const noexcept
Returns the position within the child component of the top-left of its visible area.
int getMaximumVisibleHeight() const
Returns the height available within this component for the contents.
bool keyPressed(const KeyPress &) override
Called when a key is pressed.
void setViewPosition(int xPixelsOffset, int yPixelsOffset)
Changes the position of the viewed component.
int getViewPositionY() const noexcept
Returns the position within the child component of the top-left of its visible area.
int getMaximumVisibleWidth() const
Returns the width available within this component for the contents.
void setViewedComponent(Component *newViewedComponent, bool deleteComponentWhenNoLongerNeeded=true)
Sets the component that this viewport will contain and scroll around.
A variant class, that can be used to hold a range of primitive values.
T distance(T... args)
T exchange(T... args)
T find_if(T... args)
#define jassert(expression)
Platform-independent assertion macro.
#define JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(className)
This is a shorthand way of writing both a JUCE_DECLARE_NON_COPYABLE and JUCE_LEAK_DETECTOR macro for ...
#define jassertfalse
This will always cause an assertion failure.
typedef int
T lock(T... args)
typedef double
T max(T... args)
JUCE Namespace.
constexpr bool approximatelyEqual(Type a, Type b, Tolerance< Type > tolerance=Tolerance< Type >{} .withAbsolute(std::numeric_limits< Type >::min()) .withRelative(std::numeric_limits< Type >::epsilon()))
Returns true if the two floating-point numbers are approximately equal.
constexpr Type jmin(Type a, Type b)
Returns the smaller of two values.
constexpr Type jmax(Type a, Type b)
Returns the larger of two values.
Type jlimit(Type lowerLimit, Type upperLimit, Type valueToConstrain) noexcept
Constrains a value to keep it within a given range.
@ rowSelectionChanged
Indicates that the selection of rows in a list or table has changed.
@ structureChanged
Indicates that the structure of the UI elements has changed in a significant way.
NotificationType
These enums are used in various classes to indicate whether a notification event should be sent out.
@ sendNotification
Requests a notification message, either synchronous or not.
Type unalignedPointerCast(void *ptr) noexcept
Casts a pointer to another type via void*, which suppresses the cast-align warning which sometimes ar...
Definition juce_Memory.h:88
@ focus
Indicates that the UI element has received focus.
@ toggle
Represents a "toggle" action.
@ press
Represents a "press" action.
bool isPositiveAndBelow(Type1 valueToTest, Type2 upperLimit) noexcept
Returns true if a value is at least zero, and also below a specified upper limit.
int roundToInt(const FloatType value) noexcept
Fast floating-point-to-integer conversion.
AccessibilityRole
The list of available roles for an AccessibilityHandler object.
Contains status information about a mouse wheel event.
Utility struct which holds one or more accessibility interfaces.
void mouseExit(const MouseEvent &e) override
Called when the mouse moves out of a component.
void mouseMove(const MouseEvent &e) override
Called when the mouse moves inside a component.
typedef size_t