LMMS
Loading...
Searching...
No Matches
juce_TreeView.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
29static int getItemDepth (const TreeViewItem* item)
30{
31 if (item == nullptr || item->getOwnerView() == nullptr)
32 return 0;
33
34 auto depth = item->getOwnerView()->isRootItemVisible() ? 0 : -1;
35
36 for (auto* parent = item->getParentItem(); parent != nullptr; parent = parent->getParentItem())
37 ++depth;
38
39 return depth;
40}
41
42//==============================================================================
44 public TooltipClient
45{
46public:
47 explicit ItemComponent (TreeViewItem& itemToRepresent)
48 : item (itemToRepresent),
49 customComponent (item.createItemComponent())
50 {
53 }
54
55 void paint (Graphics& g) override
56 {
58 }
59
60 void resized() override
61 {
63 {
64 auto itemPosition = item.getItemPosition (false);
65
66 customComponent->setBounds (getLocalBounds().withX (itemPosition.getX())
67 .withWidth (itemPosition.getWidth()));
68 }
69 }
70
71 void setMouseIsOverButton (bool isOver)
72 {
73 mouseIsOverButton = isOver;
74 repaint();
75 }
76
81
82 String getTooltip() override
83 {
84 return item.getTooltip();
85 }
86
87private:
88 //==============================================================================
90 {
91 public:
96 { std::make_unique<ItemCellInterface> (comp) }),
97 itemComponent (comp)
98 {
99 }
100
101 String getTitle() const override
102 {
103 return itemComponent.getRepresentedItem().getAccessibilityName();
104 }
105
106 String getHelp() const override
107 {
108 return itemComponent.getRepresentedItem().getTooltip();
109 }
110
112 {
113 auto& treeItem = itemComponent.getRepresentedItem();
114
115 auto state = AccessibilityHandler::getCurrentState().withAccessibleOffscreen();
116
117 if (auto* tree = treeItem.getOwnerView())
118 {
119 if (tree->isMultiSelectEnabled())
120 state = state.withMultiSelectable();
121 else
122 state = state.withSelectable();
123 }
124
125 if (treeItem.mightContainSubItems())
126 {
127 state = state.withExpandable();
128
129 if (treeItem.isOpen())
130 state = state.withExpanded();
131 else
132 state = state.withCollapsed();
133 }
134
135 if (treeItem.isSelected())
136 state = state.withSelected();
137
138 return state;
139 }
140
142 {
143 public:
145
146 int getColumnIndex() const override { return 0; }
147 int getColumnSpan() const override { return 1; }
148
149 int getRowIndex() const override
150 {
151 return itemComponent.getRepresentedItem().getRowNumberInTree();
152 }
153
154 int getRowSpan() const override
155 {
156 return 1;
157 }
158
159 int getDisclosureLevel() const override
160 {
161 return getItemDepth (&itemComponent.getRepresentedItem());
162 }
163
164 const AccessibilityHandler* getTableHandler() const override
165 {
166 if (auto* tree = itemComponent.getRepresentedItem().getOwnerView())
167 return tree->getAccessibilityHandler();
168
169 return nullptr;
170 }
171
172 private:
174 };
175
176 private:
178 {
179 auto onFocus = [&itemComponent]
180 {
181 auto& treeItem = itemComponent.getRepresentedItem();
182
183 if (auto* tree = treeItem.getOwnerView())
184 tree->scrollToKeepItemVisible (&treeItem);
185 };
186
187 auto onPress = [&itemComponent]
188 {
189 itemComponent.getRepresentedItem().itemClicked (generateMouseEvent (itemComponent, { ModifierKeys::leftButtonModifier }));
190 };
191
192 auto onShowMenu = [&itemComponent]
193 {
195 };
196
197 auto onToggle = [&itemComponent, onFocus]
198 {
199 if (auto* handler = itemComponent.getAccessibilityHandler())
200 {
201 auto isSelected = handler->getCurrentState().isSelected();
202
203 if (! isSelected)
204 onFocus();
205
206 itemComponent.getRepresentedItem().setSelected (! isSelected, true);
207 }
208 };
209
211 .addAction (AccessibilityActionType::press, std::move (onPress))
212 .addAction (AccessibilityActionType::showMenu, std::move (onShowMenu))
213 .addAction (AccessibilityActionType::toggle, std::move (onToggle));
214
215 return actions;
216 }
217
219
229
231 };
232
233 std::unique_ptr<AccessibilityHandler> createAccessibilityHandler() override
234 {
235 if (hasCustomComponent() && customComponent->getAccessibilityHandler() != nullptr)
237
238 return std::make_unique<ItemAccessibilityHandler> (*this);
239 }
240
241 bool hasCustomComponent() const noexcept { return customComponent.get() != nullptr; }
242
244 std::unique_ptr<Component> customComponent;
245
246 bool mouseIsOverButton = false;
247
248 //==============================================================================
250};
251
252//==============================================================================
254 public TooltipClient,
255 public AsyncUpdater
256{
257public:
259 {
260 }
261
262 //==============================================================================
263 void resized() override
264 {
266 }
267
269 {
270 if (auto* itemComponent = getItemComponentAt (getMouseXYRelative()))
271 return itemComponent->getRepresentedItem().getTooltip();
272
273 return owner.getTooltip();
274 }
275
276 void mouseDown (const MouseEvent& e) override { mouseDownInternal (e.getEventRelativeTo (this)); }
277 void mouseUp (const MouseEvent& e) override { mouseUpInternal (e.getEventRelativeTo (this)); }
278 void mouseDoubleClick (const MouseEvent& e) override { mouseDoubleClickInternal (e.getEventRelativeTo (this));}
279 void mouseDrag (const MouseEvent& e) override { mouseDragInternal (e.getEventRelativeTo (this));}
280 void mouseMove (const MouseEvent& e) override { mouseMoveInternal (e.getEventRelativeTo (this)); }
281 void mouseExit (const MouseEvent& e) override { mouseExitInternal (e.getEventRelativeTo (this)); }
282
283 //==============================================================================
285 {
286 auto iter = std::find_if (itemComponents.cbegin(), itemComponents.cend(),
287 [p] (const std::unique_ptr<ItemComponent>& c)
288 {
289 return c->getBounds().contains (p);
290 });
291
292 if (iter != itemComponents.cend())
293 return iter->get();
294
295 return nullptr;
296 }
297
299 {
300 const auto iter = std::find_if (itemComponents.begin(), itemComponents.end(),
301 [item] (const std::unique_ptr<ItemComponent>& c)
302 {
303 return &c->getRepresentedItem() == item;
304 });
305
306 if (iter != itemComponents.end())
307 return iter->get();
308
309 return nullptr;
310 }
311
313 {
314 const auto iter = std::find_if (itemComponents.begin(), itemComponents.end(),
315 [item] (const std::unique_ptr<ItemComponent>& c)
316 {
317 return &c->getRepresentedItem() == item;
318 });
319
320 if (iter != itemComponents.end())
321 {
322 if (itemUnderMouse == iter->get())
323 itemUnderMouse = nullptr;
324
325 if (isMouseDraggingInChildComp (*(iter->get())))
326 owner.hideDragHighlight();
327
328 itemComponents.erase (iter);
329 }
330 }
331
333 {
334 std::set<ItemComponent*> componentsToKeep;
335
336 for (auto* treeItem : getAllVisibleItems())
337 {
338 if (auto* itemComp = getComponentForItem (treeItem))
339 {
340 componentsToKeep.insert (itemComp);
341 }
342 else
343 {
344 auto newComp = std::make_unique<ItemComponent> (*treeItem);
345
346 addAndMakeVisible (*newComp);
347 newComp->addMouseListener (this, treeItem->customComponentUsesTreeViewMouseHandler());
348 componentsToKeep.insert (newComp.get());
349
350 itemComponents.push_back (std::move (newComp));
351 }
352 }
353
354 auto removePredicate = [&] (auto& item)
355 {
356 if (item == nullptr)
357 return true;
358
359 return componentsToKeep.find (item.get()) == componentsToKeep.end()
360 && ! isMouseDraggingInChildComp (*item);
361 };
362
363 const auto iter = std::remove_if (itemComponents.begin(), itemComponents.end(), std::move (removePredicate));
364 itemComponents.erase (iter, itemComponents.end());
365
366 for (auto& comp : itemComponents)
367 {
368 auto& treeItem = comp->getRepresentedItem();
369 comp->setBounds ({ 0, treeItem.y, getWidth(), treeItem.itemHeight });
370 }
371 }
372
373private:
374 //==============================================================================
376 {
378 : item (&c)
379 {
380 item->setViewportIgnoreDragFlag (true);
381 }
382
384 {
385 if (item != nullptr)
386 item->setViewportIgnoreDragFlag (false);
387 }
388
390
392 };
393
394 //==============================================================================
395 std::unique_ptr<AccessibilityHandler> createAccessibilityHandler() override
396 {
398 }
399
401 {
403
404 isDragging = false;
405 scopedScrollDisabler = nullptr;
407
408 if (! isEnabled())
409 return;
410
411 if (auto* itemComponent = getItemComponentAt (e.getPosition()))
412 {
413 auto& item = itemComponent->getRepresentedItem();
414 auto pos = item.getItemPosition (false);
415
416 // (if the open/close buttons are hidden, we'll treat clicks to the left of the item
417 // as selection clicks)
418 if (e.x < pos.getX() && owner.openCloseButtonsVisible)
419 {
420 // (clicks to the left of an open/close button are ignored)
421 if (e.x >= pos.getX() - owner.getIndentSize())
422 item.setOpen (! item.isOpen());
423 }
424 else
425 {
426 // mouse-down inside the body of the item..
427 if (! owner.isMultiSelectEnabled())
428 item.setSelected (true, true);
429 else if (item.isSelected())
430 needSelectionOnMouseUp = ! e.mods.isPopupMenu();
431 else
432 selectBasedOnModifiers (item, e.mods);
433
434 if (e.x >= pos.getX())
435 item.itemClicked (e.withNewPosition (e.position - pos.getPosition().toFloat()));
436 }
437 }
438 }
439
441 {
443
444 if (isEnabled() && needSelectionOnMouseUp && e.mouseWasClicked())
445 if (auto* itemComponent = getItemComponentAt (e.getPosition()))
446 selectBasedOnModifiers (itemComponent->getRepresentedItem(), e.mods);
447 }
448
450 {
451 if (isEnabled() && e.getNumberOfClicks() != 3) // ignore triple clicks
452 {
453 if (auto* itemComponent = getItemComponentAt (e.getPosition()))
454 {
455 auto& item = itemComponent->getRepresentedItem();
456 auto pos = item.getItemPosition (false);
457
458 if (e.x >= pos.getX() || ! owner.openCloseButtonsVisible)
459 item.itemDoubleClicked (e.withNewPosition (e.position - pos.getPosition().toFloat()));
460 }
461 }
462 }
463
465 {
466 if (isEnabled()
467 && ! (isDragging || e.mouseWasClicked()
468 || e.getDistanceFromDragStart() < 5
469 || e.mods.isPopupMenu()))
470 {
471 isDragging = true;
472
473 if (auto* itemComponent = getItemComponentAt (e.getMouseDownPosition()))
474 {
475 auto& item = itemComponent->getRepresentedItem();
476 auto pos = item.getItemPosition (false);
477
478 if (e.getMouseDownX() >= pos.getX())
479 {
480 auto dragDescription = item.getDragSourceDescription();
481
482 if (! (dragDescription.isVoid() || (dragDescription.isString() && dragDescription.toString().isEmpty())))
483 {
484 if (auto* dragContainer = DragAndDropContainer::findParentDragContainerFor (this))
485 {
486 pos.setSize (pos.getWidth(), item.itemHeight);
487
488 const auto additionalScale = 2.0f;
489 auto dragImage = Component::createComponentSnapshot (pos,
490 true,
491 Component::getApproximateScaleFactorForComponent (itemComponent) * additionalScale);
492
493 dragImage.multiplyAllAlphas (0.6f);
494
495 auto imageOffset = pos.getPosition() - e.getPosition();
496 dragContainer->startDragging (dragDescription, &owner, { dragImage, additionalScale }, true, &imageOffset, &e.source);
497
498 scopedScrollDisabler = std::make_unique<ScopedDisableViewportScroll> (*itemComponent);
499 }
500 else
501 {
502 // to be able to do a drag-and-drop operation, the treeview needs to
503 // be inside a component which is also a DragAndDropContainer.
505 }
506 }
507 }
508 }
509 }
510 }
511
514
516 {
517 for (auto& ms : Desktop::getInstance().getMouseSources())
518 if (ms.isDragging())
519 if (auto* underMouse = ms.getComponentUnderMouse())
520 return (&comp == underMouse || comp.isParentOf (underMouse));
521
522 return false;
523 }
524
526 {
527 if (! owner.openCloseButtonsVisible)
528 return;
529
530 auto* newItem = [this, &e]() -> ItemComponent*
531 {
532 if (auto* itemComponent = getItemComponentAt (e.getPosition()))
533 {
534 auto& item = itemComponent->getRepresentedItem();
535
536 if (item.mightContainSubItems())
537 {
538 const auto xPos = item.getItemPosition (false).getX();
539
540 if (xPos - owner.getIndentSize() <= e.x && e.x < xPos)
541 return itemComponent;
542 }
543 }
544
545 return nullptr;
546 }();
547
548 if (itemUnderMouse != newItem)
549 {
550 if (itemUnderMouse != nullptr)
551 itemUnderMouse->setMouseIsOverButton (false);
552
553 if (newItem != nullptr)
554 newItem->setMouseIsOverButton (true);
555
556 itemUnderMouse = newItem;
557 }
558 }
559
560 void handleAsyncUpdate() override
561 {
562 owner.updateVisibleItems();
563 }
564
565 //==============================================================================
567 {
568 TreeViewItem* firstSelected = nullptr;
569
570 if (modifiers.isShiftDown() && ((firstSelected = owner.getSelectedItem (0)) != nullptr))
571 {
572 auto* lastSelected = owner.getSelectedItem (owner.getNumSelectedItems() - 1);
573
574 if (lastSelected == nullptr)
575 {
577 return;
578 }
579
580 auto rowStart = firstSelected->getRowNumberInTree();
581 auto rowEnd = lastSelected->getRowNumberInTree();
582
583 if (rowStart > rowEnd)
584 std::swap (rowStart, rowEnd);
585
586 auto ourRow = item.getRowNumberInTree();
587 auto otherEnd = ourRow < rowEnd ? rowStart : rowEnd;
588
589 if (ourRow > otherEnd)
590 std::swap (ourRow, otherEnd);
591
592 for (int i = ourRow; i <= otherEnd; ++i)
593 owner.getItemOnRow (i)->setSelected (true, false);
594 }
595 else
596 {
597 const auto cmd = modifiers.isCommandDown();
598 item.setSelected ((! cmd) || ! item.isSelected(), ! cmd);
599 }
600 }
601
602 static TreeViewItem* getNextVisibleItem (TreeViewItem* item, bool forwards)
603 {
604 if (item == nullptr || item->ownerView == nullptr)
605 return nullptr;
606
607 auto* nextItem = item->ownerView->getItemOnRow (item->getRowNumberInTree() + (forwards ? 1 : -1));
608
609 return nextItem == item->ownerView->rootItem && ! item->ownerView->rootItemVisible ? nullptr
610 : nextItem;
611 }
612
613 std::vector<TreeViewItem*> getAllVisibleItems() const
614 {
615 if (owner.rootItem == nullptr)
616 return {};
617
618 const auto visibleTop = -getY();
619 const auto visibleBottom = visibleTop + getParentHeight();
620
621 std::vector<TreeViewItem*> visibleItems;
622
623 auto* item = [&]
624 {
625 auto* i = owner.rootItemVisible ? owner.rootItem
626 : owner.rootItem->subItems.getFirst();
627
628 while (i != nullptr && i->y < visibleTop)
629 i = getNextVisibleItem (i, true);
630
631 return i;
632 }();
633
634 auto addOffscreenItemBuffer = [&visibleItems] (TreeViewItem* i, int num, bool forwards)
635 {
636 while (--num >= 0)
637 {
638 i = getNextVisibleItem (i, forwards);
639
640 if (i == nullptr)
641 return;
642
643 visibleItems.push_back (i);
644 }
645 };
646
647 addOffscreenItemBuffer (item, 2, false);
648
649 while (item != nullptr && item->y < visibleBottom)
650 {
651 visibleItems.push_back (item);
652 item = getNextVisibleItem (item, true);
653 }
654
655 if (item != nullptr)
656 visibleItems.push_back (item);
657
658 addOffscreenItemBuffer (item, 2, true);
659
660 return visibleItems;
661 }
662
663 //==============================================================================
665
666 std::vector<std::unique_ptr<ItemComponent>> itemComponents;
668 std::unique_ptr<ScopedDisableViewportScroll> scopedScrollDisabler;
669 bool isDragging = false, needSelectionOnMouseUp = false;
670
672};
673
674//==============================================================================
676 private AsyncUpdater
677{
678public:
679 explicit TreeViewport (TreeView& treeView) : owner (treeView) {}
680
681 void visibleAreaChanged (const Rectangle<int>& newVisibleArea) override
682 {
683 const auto hasScrolledSideways = (newVisibleArea.getX() != lastX);
684
685 lastX = newVisibleArea.getX();
686 updateComponents (hasScrolledSideways);
687
688 structureChanged = true;
690 }
691
692 bool keyPressed (const KeyPress& key) override
693 {
694 if (auto* tree = getParentComponent())
695 if (tree->keyPressed (key))
696 return true;
697
698 return Viewport::keyPressed (key);
699 }
700
705
706 enum class Async { yes, no };
707
708 void recalculatePositions (Async useAsyncUpdate)
709 {
710 needsRecalculating = true;
711
712 if (useAsyncUpdate == Async::yes)
714 else
716 }
717
718private:
719 std::unique_ptr<AccessibilityHandler> createAccessibilityHandler() override
720 {
722 }
723
724 void handleAsyncUpdate() override
725 {
727 {
728 if (auto* handler = owner.getAccessibilityHandler())
729 handler->notifyAccessibilityEvent (AccessibilityEvent::structureChanged);
730
731 structureChanged = false;
732 }
733
735 {
736 if (auto* root = owner.rootItem)
737 {
738 const auto startY = owner.rootItemVisible ? 0 : -root->itemHeight;
739
740 root->updatePositions (startY);
741 getViewedComponent()->setSize (jmax (getMaximumVisibleWidth(), root->totalWidth + 50),
742 root->totalHeight + startY);
743 }
744 else
745 {
746 getViewedComponent()->setSize (0, 0);
747 }
748
749 updateComponents (false);
750
751 needsRecalculating = false;
752 }
753 }
754
755 void updateComponents (bool triggerResize)
756 {
757 if (auto* content = getContentComp())
758 {
759 if (triggerResize)
760 content->resized();
761 else
762 content->updateComponents();
763 }
764
765 repaint();
766 }
767
769 int lastX = -1;
771
773};
774
775//==============================================================================
777{
778 viewport = std::make_unique<TreeViewport> (*this);
780 viewport->setViewedComponent (new ContentComponent (*this));
781
784}
785
787{
788 if (rootItem != nullptr)
789 rootItem->setOwnerView (nullptr);
790}
791
792void TreeView::setRootItem (TreeViewItem* const newRootItem)
793{
794 if (rootItem != newRootItem)
795 {
796 if (newRootItem != nullptr)
797 {
798 // can't use a tree item in more than one tree at once..
799 jassert (newRootItem->ownerView == nullptr);
800
801 if (newRootItem->ownerView != nullptr)
802 newRootItem->ownerView->setRootItem (nullptr);
803 }
804
805 if (rootItem != nullptr)
806 rootItem->setOwnerView (nullptr);
807
808 rootItem = newRootItem;
809
810 if (newRootItem != nullptr)
811 newRootItem->setOwnerView (this);
812
813 if (rootItem != nullptr && (defaultOpenness || ! rootItemVisible))
814 {
815 rootItem->setOpen (false); // force a re-open
816 rootItem->setOpen (true);
817 }
818
819 viewport->recalculatePositions (TreeViewport::Async::no);
820 }
821}
822
824{
825 const std::unique_ptr<TreeViewItem> deleter (rootItem);
826 setRootItem (nullptr);
827}
828
829void TreeView::setRootItemVisible (const bool shouldBeVisible)
830{
831 rootItemVisible = shouldBeVisible;
832
833 if (rootItem != nullptr && (defaultOpenness || ! rootItemVisible))
834 {
835 rootItem->setOpen (false); // force a re-open
836 rootItem->setOpen (true);
837 }
838
840}
841
847
848void TreeView::setIndentSize (const int newIndentSize)
849{
850 if (indentSize != newIndentSize)
851 {
852 indentSize = newIndentSize;
853 resized();
854 }
855}
856
858{
859 return indentSize >= 0 ? indentSize
860 : getLookAndFeel().getTreeViewIndentSize (*this);
861}
862
863void TreeView::setDefaultOpenness (const bool isOpenByDefault)
864{
865 if (defaultOpenness != isOpenByDefault)
866 {
867 defaultOpenness = isOpenByDefault;
869 }
870}
871
872void TreeView::setMultiSelectEnabled (const bool canMultiSelect)
873{
874 multiSelectEnabled = canMultiSelect;
875}
876
877void TreeView::setOpenCloseButtonsVisible (const bool shouldBeVisible)
878{
879 if (openCloseButtonsVisible != shouldBeVisible)
880 {
881 openCloseButtonsVisible = shouldBeVisible;
883 }
884}
885
887{
888 return viewport.get();
889}
890
891//==============================================================================
893{
894 if (rootItem != nullptr)
895 rootItem->deselectAllRecursively (nullptr);
896}
897
898int TreeView::getNumSelectedItems (int maximumDepthToSearchTo) const noexcept
899{
900 return rootItem != nullptr ? rootItem->countSelectedItemsRecursively (maximumDepthToSearchTo) : 0;
901}
902
903TreeViewItem* TreeView::getSelectedItem (const int index) const noexcept
904{
905 return rootItem != nullptr ? rootItem->getSelectedItemWithIndex (index) : nullptr;
906}
907
909{
910 return rootItem != nullptr ? (rootItem->getNumRows() - (rootItemVisible ? 0 : 1)) : 0;
911}
912
914{
915 if (! rootItemVisible)
916 ++index;
917
918 if (rootItem != nullptr && index >= 0)
919 return rootItem->getItemOnRow (index);
920
921 return nullptr;
922}
923
924TreeViewItem* TreeView::getItemAt (int y) const noexcept
925{
926 if (auto* contentComp = viewport->getContentComp())
927 if (auto* itemComponent = contentComp->getItemComponentAt (contentComp->getLocalPoint (this, Point<int> (0, y))))
928 return &itemComponent->getRepresentedItem();
929
930 return nullptr;
931}
932
934{
935 if (rootItem == nullptr)
936 return nullptr;
937
938 return rootItem->findItemFromIdentifierString (identifierString);
939}
940
942{
943 return viewport->getContentComp()->getComponentForItem (item);
944}
945
946//==============================================================================
948{
949 if (item->isSelected())
950 parent.createNewChildElement ("SELECTED")->setAttribute ("id", item->getItemIdentifierString());
951
952 auto numSubItems = item->getNumSubItems();
953
954 for (int i = 0; i < numSubItems; ++i)
956}
957
958std::unique_ptr<XmlElement> TreeView::getOpennessState (bool alsoIncludeScrollPosition) const
959{
960 if (rootItem != nullptr)
961 {
962 if (auto rootOpenness = rootItem->getOpennessState (false))
963 {
964 if (alsoIncludeScrollPosition)
965 rootOpenness->setAttribute ("scrollPos", viewport->getViewPositionY());
966
967 addAllSelectedItemIds (rootItem, *rootOpenness);
968 return rootOpenness;
969 }
970 }
971
972 return {};
973}
974
975void TreeView::restoreOpennessState (const XmlElement& newState, bool restoreStoredSelection)
976{
977 if (rootItem != nullptr)
978 {
979 rootItem->restoreOpennessState (newState);
980
981 if (newState.hasAttribute ("scrollPos"))
982 viewport->setViewPosition (viewport->getViewPositionX(),
983 newState.getIntAttribute ("scrollPos"));
984
985 if (restoreStoredSelection)
986 {
988
989 for (auto* e : newState.getChildWithTagNameIterator ("SELECTED"))
990 if (auto* item = rootItem->findItemFromIdentifierString (e->getStringAttribute ("id")))
991 item->setSelected (true, false);
992 }
993
995 }
996}
997
998//==============================================================================
1000{
1001 g.fillAll (findColour (backgroundColourId));
1002}
1003
1005{
1006 viewport->setBounds (getLocalBounds());
1008}
1009
1011{
1012 repaint();
1013}
1014
1016{
1017 auto numRowsInTree = getNumRowsInTree();
1018
1019 if (numRowsInTree > 0)
1020 {
1021 int rowSelected = 0;
1022
1023 if (auto* firstSelected = getSelectedItem (0))
1024 rowSelected = firstSelected->getRowNumberInTree();
1025
1026 rowSelected = jlimit (0, numRowsInTree - 1, rowSelected + delta);
1027
1028 for (;;)
1029 {
1030 if (auto* item = getItemOnRow (rowSelected))
1031 {
1032 if (! item->canBeSelected())
1033 {
1034 // if the row we want to highlight doesn't allow it, try skipping
1035 // to the next item..
1036 auto nextRowToTry = jlimit (0, numRowsInTree - 1, rowSelected + (delta < 0 ? -1 : 1));
1037
1038 if (rowSelected != nextRowToTry)
1039 {
1040 rowSelected = nextRowToTry;
1041 continue;
1042 }
1043
1044 break;
1045 }
1046
1047 item->setSelected (true, true);
1049 }
1050
1051 break;
1052 }
1053 }
1054}
1055
1057{
1058 if (item != nullptr && item->ownerView == this)
1059 {
1061
1062 item = item->getDeepestOpenParentItem();
1063
1064 auto y = item->y;
1065 auto viewTop = viewport->getViewPositionY();
1066
1067 if (y < viewTop)
1068 {
1069 viewport->setViewPosition (viewport->getViewPositionX(), y);
1070 }
1071 else if (y + item->itemHeight > viewTop + viewport->getViewHeight())
1072 {
1073 viewport->setViewPosition (viewport->getViewPositionX(),
1074 (y + item->itemHeight) - viewport->getViewHeight());
1075 }
1076 }
1077}
1078
1080{
1081 if (auto* firstSelected = getSelectedItem (0))
1082 {
1083 if (firstSelected->mightContainSubItems())
1084 {
1085 firstSelected->setOpen (! firstSelected->isOpen());
1086 return true;
1087 }
1088 }
1089
1090 return false;
1091}
1092
1094{
1095 if (auto* firstSelected = getSelectedItem (0))
1096 {
1097 if (firstSelected->isOpen())
1098 {
1099 firstSelected->setOpen (false);
1100 }
1101 else
1102 {
1103 auto* parent = firstSelected->parentItem;
1104
1105 if ((! rootItemVisible) && parent == rootItem)
1106 parent = nullptr;
1107
1108 if (parent != nullptr)
1109 {
1110 parent->setSelected (true, true);
1112 }
1113 }
1114 }
1115}
1116
1118{
1119 if (auto* firstSelected = getSelectedItem (0))
1120 {
1121 if (firstSelected->isOpen() || ! firstSelected->mightContainSubItems())
1122 moveSelectedRow (1);
1123 else
1124 firstSelected->setOpen (true);
1125 }
1126}
1127
1128void TreeView::moveByPages (int numPages)
1129{
1130 if (auto* currentItem = getSelectedItem (0))
1131 {
1132 auto pos = currentItem->getItemPosition (false);
1133 auto targetY = pos.getY() + numPages * (getHeight() - pos.getHeight());
1134 auto currentRow = currentItem->getRowNumberInTree();
1135
1136 for (;;)
1137 {
1138 moveSelectedRow (numPages);
1139 currentItem = getSelectedItem (0);
1140
1141 if (currentItem == nullptr)
1142 break;
1143
1144 auto y = currentItem->getItemPosition (false).getY();
1145
1146 if ((numPages < 0 && y <= targetY) || (numPages > 0 && y >= targetY))
1147 break;
1148
1149 auto newRow = currentItem->getRowNumberInTree();
1150
1151 if (newRow == currentRow)
1152 break;
1153
1154 currentRow = newRow;
1155 }
1156 }
1157}
1158
1160{
1161 if (rootItem != nullptr)
1162 {
1163 if (key == KeyPress::upKey) { moveSelectedRow (-1); return true; }
1164 if (key == KeyPress::downKey) { moveSelectedRow (1); return true; }
1165 if (key == KeyPress::homeKey) { moveSelectedRow (-0x3fffffff); return true; }
1166 if (key == KeyPress::endKey) { moveSelectedRow (0x3fffffff); return true; }
1167 if (key == KeyPress::pageUpKey) { moveByPages (-1); return true; }
1168 if (key == KeyPress::pageDownKey) { moveByPages (1); return true; }
1169 if (key == KeyPress::returnKey) { return toggleOpenSelectedItem(); }
1170 if (key == KeyPress::leftKey) { moveOutOfSelectedItem(); return true; }
1171 if (key == KeyPress::rightKey) { moveIntoSelectedItem(); return true; }
1172 }
1173
1174 return false;
1175}
1176
1178{
1179 viewport->recalculatePositions (TreeViewport::Async::yes);
1180}
1181
1182//==============================================================================
1184{
1186 const DragAndDropTarget::SourceDetails& dragSourceDetails)
1187 : pos (dragSourceDetails.localPosition),
1188 item (view.getItemAt (dragSourceDetails.localPosition.y))
1189 {
1190 if (item != nullptr)
1191 {
1192 auto itemPos = item->getItemPosition (true);
1193 insertIndex = item->getIndexInParent();
1194 auto oldY = pos.y;
1195 pos.y = itemPos.getY();
1196
1197 if (item->getNumSubItems() == 0 || ! item->isOpen())
1198 {
1199 if (files.size() > 0 ? item->isInterestedInFileDrag (files)
1200 : item->isInterestedInDragSource (dragSourceDetails))
1201 {
1202 // Check if we're trying to drag into an empty group item..
1203 if (oldY > itemPos.getY() + itemPos.getHeight() / 4
1204 && oldY < itemPos.getBottom() - itemPos.getHeight() / 4)
1205 {
1206 insertIndex = 0;
1207 pos.x = itemPos.getX() + view.getIndentSize();
1208 pos.y = itemPos.getBottom();
1209 return;
1210 }
1211 }
1212 }
1213
1214 if (oldY > itemPos.getCentreY())
1215 {
1216 pos.y += item->getItemHeight();
1217
1218 while (item->isLastOfSiblings() && item->getParentItem() != nullptr
1219 && item->getParentItem()->getParentItem() != nullptr)
1220 {
1221 if (pos.x > itemPos.getX())
1222 break;
1223
1224 item = item->getParentItem();
1225 itemPos = item->getItemPosition (true);
1226 insertIndex = item->getIndexInParent();
1227 }
1228
1229 ++insertIndex;
1230 }
1231
1232 pos.x = itemPos.getX();
1233 item = item->getParentItem();
1234 }
1235 else if (auto* root = view.getRootItem())
1236 {
1237 // If they're dragging beyond the bottom of the list, then insert at the end of the root item..
1238 item = root;
1239 insertIndex = root->getNumSubItems();
1240 pos = root->getItemPosition (true).getBottomLeft();
1241 pos.x += view.getIndentSize();
1242 }
1243 }
1244
1248};
1249
1250//==============================================================================
1252{
1253public:
1255 {
1256 setSize (100, 12);
1257 setAlwaysOnTop (true);
1258 setInterceptsMouseClicks (false, false);
1259 }
1260
1261 void setTargetPosition (const InsertPoint& insertPos, const int width) noexcept
1262 {
1263 lastItem = insertPos.item;
1264 lastIndex = insertPos.insertIndex;
1265 auto offset = getHeight() / 2;
1266 setBounds (insertPos.pos.x - offset, insertPos.pos.y - offset,
1267 width - (insertPos.pos.x - offset), getHeight());
1268 }
1269
1270 void paint (Graphics& g) override
1271 {
1272 Path p;
1273 auto h = (float) getHeight();
1274 p.addEllipse (2.0f, 2.0f, h - 4.0f, h - 4.0f);
1275 p.startNewSubPath (h - 2.0f, h / 2.0f);
1276 p.lineTo ((float) getWidth(), h / 2.0f);
1277
1279 g.strokePath (p, PathStrokeType (2.0f));
1280 }
1281
1283 int lastIndex = 0;
1284
1285private:
1287};
1288
1289//==============================================================================
1291{
1292public:
1294 {
1295 setAlwaysOnTop (true);
1296 setInterceptsMouseClicks (false, false);
1297 }
1298
1299 void setTargetPosition (TreeViewItem* const item) noexcept
1300 {
1301 setBounds (item->getItemPosition (true)
1302 .withHeight (item->getItemHeight()));
1303 }
1304
1305 void paint (Graphics& g) override
1306 {
1308 g.drawRoundedRectangle (1.0f, 1.0f, (float) getWidth() - 2.0f, (float) getHeight() - 2.0f, 3.0f, 2.0f);
1309 }
1310
1311private:
1313};
1314
1315//==============================================================================
1316void TreeView::showDragHighlight (const InsertPoint& insertPos) noexcept
1317{
1318 beginDragAutoRepeat (100);
1319
1320 if (dragInsertPointHighlight == nullptr)
1321 {
1322 dragInsertPointHighlight = std::make_unique<InsertPointHighlight>();
1323 dragTargetGroupHighlight = std::make_unique<TargetGroupHighlight>();
1324
1327 }
1328
1329 dragInsertPointHighlight->setTargetPosition (insertPos, viewport->getViewWidth());
1330 dragTargetGroupHighlight->setTargetPosition (insertPos.item);
1331}
1332
1338
1339void TreeView::handleDrag (const StringArray& files, const SourceDetails& dragSourceDetails)
1340{
1341 const auto scrolled = viewport->autoScroll (dragSourceDetails.localPosition.x,
1342 dragSourceDetails.localPosition.y, 20, 10);
1343
1344 InsertPoint insertPos (*this, files, dragSourceDetails);
1345
1346 if (insertPos.item != nullptr)
1347 {
1348 if (scrolled || dragInsertPointHighlight == nullptr
1349 || dragInsertPointHighlight->lastItem != insertPos.item
1350 || dragInsertPointHighlight->lastIndex != insertPos.insertIndex)
1351 {
1352 if (files.size() > 0 ? insertPos.item->isInterestedInFileDrag (files)
1353 : insertPos.item->isInterestedInDragSource (dragSourceDetails))
1354 showDragHighlight (insertPos);
1355 else
1357 }
1358 }
1359 else
1360 {
1362 }
1363}
1364
1365void TreeView::handleDrop (const StringArray& files, const SourceDetails& dragSourceDetails)
1366{
1368
1369 InsertPoint insertPos (*this, files, dragSourceDetails);
1370
1371 if (insertPos.item == nullptr)
1372 insertPos.item = rootItem;
1373
1374 if (insertPos.item != nullptr)
1375 {
1376 if (files.size() > 0)
1377 {
1378 if (insertPos.item->isInterestedInFileDrag (files))
1379 insertPos.item->filesDropped (files, insertPos.insertIndex);
1380 }
1381 else
1382 {
1383 if (insertPos.item->isInterestedInDragSource (dragSourceDetails))
1384 insertPos.item->itemDropped (dragSourceDetails, insertPos.insertIndex);
1385 }
1386 }
1387}
1388
1389//==============================================================================
1391{
1392 return true;
1393}
1394
1396{
1397 fileDragMove (files, x, y);
1398}
1399
1401{
1402 handleDrag (files, SourceDetails (var(), this, { x, y }));
1403}
1404
1406{
1408}
1409
1411{
1412 handleDrop (files, SourceDetails (var(), this, { x, y }));
1413}
1414
1415bool TreeView::isInterestedInDragSource (const SourceDetails& /*dragSourceDetails*/)
1416{
1417 return true;
1418}
1419
1420void TreeView::itemDragEnter (const SourceDetails& dragSourceDetails)
1421{
1422 itemDragMove (dragSourceDetails);
1423}
1424
1425void TreeView::itemDragMove (const SourceDetails& dragSourceDetails)
1426{
1427 handleDrag (StringArray(), dragSourceDetails);
1428}
1429
1430void TreeView::itemDragExit (const SourceDetails& /*dragSourceDetails*/)
1431{
1433}
1434
1435void TreeView::itemDropped (const SourceDetails& dragSourceDetails)
1436{
1437 handleDrop (StringArray(), dragSourceDetails);
1438}
1439
1440//==============================================================================
1441std::unique_ptr<AccessibilityHandler> TreeView::createAccessibilityHandler()
1442{
1443 class TableInterface : public AccessibilityTableInterface
1444 {
1445 public:
1446 explicit TableInterface (TreeView& treeViewToWrap) : treeView (treeViewToWrap) {}
1447
1448 int getNumRows() const override { return treeView.getNumRowsInTree(); }
1449 int getNumColumns() const override { return 1; }
1450
1451 const AccessibilityHandler* getCellHandler (int row, int) const override
1452 {
1453 if (auto* itemComp = treeView.getItemComponent (treeView.getItemOnRow (row)))
1454 return itemComp->getAccessibilityHandler();
1455
1456 return nullptr;
1457 }
1458
1459 private:
1460 TreeView& treeView;
1461
1463 };
1464
1465 return std::make_unique<AccessibilityHandler> (*this,
1468 AccessibilityHandler::Interfaces { std::make_unique<TableInterface> (*this) });
1469}
1470
1471//==============================================================================
1473{
1474 static int nextUID = 0;
1475 uid = nextUID++;
1476}
1477
1479{
1480 if (ownerView != nullptr)
1481 ownerView->viewport->getContentComp()->itemBeingDeleted (this);
1482}
1483
1485{
1486 return {};
1487}
1488
1492
1494{
1495 return subItems.size();
1496}
1497
1498TreeViewItem* TreeViewItem::getSubItem (const int index) const noexcept
1499{
1500 return subItems[index];
1501}
1502
1504{
1505 if (ownerView != nullptr)
1506 {
1507 if (! subItems.isEmpty())
1508 {
1511 }
1512 }
1513 else
1514 {
1516 }
1517}
1518
1520{
1521 for (int i = subItems.size(); --i >= 0;)
1522 removeSubItemFromList (i, true);
1523}
1524
1525void TreeViewItem::addSubItem (TreeViewItem* const newItem, const int insertPosition)
1526{
1527 if (newItem != nullptr)
1528 {
1529 newItem->parentItem = nullptr;
1530 newItem->setOwnerView (ownerView);
1531 newItem->y = 0;
1532 newItem->itemHeight = newItem->getItemHeight();
1533 newItem->totalHeight = 0;
1534 newItem->itemWidth = newItem->getItemWidth();
1535 newItem->totalWidth = 0;
1536 newItem->parentItem = this;
1537
1538 if (ownerView != nullptr)
1539 {
1540 subItems.insert (insertPosition, newItem);
1542
1543 if (newItem->isOpen())
1544 newItem->itemOpennessChanged (true);
1545 }
1546 else
1547 {
1548 subItems.insert (insertPosition, newItem);
1549
1550 if (newItem->isOpen())
1551 newItem->itemOpennessChanged (true);
1552 }
1553 }
1554}
1555
1556void TreeViewItem::removeSubItem (int index, bool deleteItem)
1557{
1558 if (ownerView != nullptr)
1559 {
1560 if (removeSubItemFromList (index, deleteItem))
1562 }
1563 else
1564 {
1565 removeSubItemFromList (index, deleteItem);
1566 }
1567}
1568
1569bool TreeViewItem::removeSubItemFromList (int index, bool deleteItem)
1570{
1571 if (auto* child = subItems[index])
1572 {
1573 child->parentItem = nullptr;
1574 subItems.remove (index, deleteItem);
1575
1576 return true;
1577 }
1578
1579 return false;
1580}
1581
1586
1588{
1589 auto wasOpen = isOpen();
1590 openness = newOpenness;
1591 auto isNowOpen = isOpen();
1592
1593 if (isNowOpen != wasOpen)
1594 {
1596 itemOpennessChanged (isNowOpen);
1597 }
1598}
1599
1601{
1603 return ownerView != nullptr && ownerView->defaultOpenness;
1604
1606}
1607
1608void TreeViewItem::setOpen (const bool shouldBeOpen)
1609{
1610 if (isOpen() != shouldBeOpen)
1611 setOpenness (shouldBeOpen ? Openness::opennessOpen
1613}
1614
1616{
1617 if (! isOpen())
1618 return false;
1619
1620 for (auto* i : subItems)
1621 if (! i->isFullyOpen())
1622 return false;
1623
1624 return true;
1625}
1626
1631
1633{
1634 return selected;
1635}
1636
1638{
1639 if (this != itemToIgnore)
1640 setSelected (false, false);
1641
1642 for (auto* i : subItems)
1643 i->deselectAllRecursively (itemToIgnore);
1644}
1645
1646void TreeViewItem::setSelected (const bool shouldBeSelected,
1647 const bool deselectOtherItemsFirst,
1648 const NotificationType notify)
1649{
1650 if (shouldBeSelected && ! canBeSelected())
1651 return;
1652
1653 if (deselectOtherItemsFirst)
1654 getTopLevelItem()->deselectAllRecursively (this);
1655
1656 if (shouldBeSelected != selected)
1657 {
1658 selected = shouldBeSelected;
1659
1660 if (ownerView != nullptr)
1661 {
1662 ownerView->repaint();
1663
1664 if (selected)
1665 {
1666 if (auto* itemComponent = ownerView->getItemComponent (this))
1667 if (auto* itemHandler = itemComponent->getAccessibilityHandler())
1668 itemHandler->grabFocus();
1669 }
1670
1671 if (auto* handler = ownerView->getAccessibilityHandler())
1672 handler->notifyAccessibilityEvent (AccessibilityEvent::rowSelectionChanged);
1673 }
1674
1675 if (notify != dontSendNotification)
1676 itemSelectionChanged (shouldBeSelected);
1677 }
1678}
1679
1681{
1682}
1683
1684void TreeViewItem::paintOpenCloseButton (Graphics& g, const Rectangle<float>& area, Colour backgroundColour, bool isMouseOver)
1685{
1686 getOwnerView()->getLookAndFeel()
1687 .drawTreeviewPlusMinusBox (g, area, backgroundColour, isOpen(), isMouseOver);
1688}
1689
1691{
1692 g.setColour (ownerView->findColour (TreeView::linesColourId));
1693 g.drawLine (line);
1694}
1695
1697{
1698 g.setColour (ownerView->findColour (TreeView::linesColourId));
1699 g.drawLine (line);
1700}
1701
1703{
1704}
1705
1707{
1709 setOpen (! isOpen());
1710}
1711
1715
1717{
1718 return {};
1719}
1720
1722{
1723 auto tooltipString = getTooltip();
1724
1725 return tooltipString.isNotEmpty()
1726 ? tooltipString
1727 : "Level " + String (getItemDepth (this)) + " row " + String (getIndexInParent());
1728}
1729
1733
1735{
1736 return {};
1737}
1738
1740{
1741 return false;
1742}
1743
1744void TreeViewItem::filesDropped (const StringArray& /*files*/, int /*insertIndex*/)
1745{
1746}
1747
1749{
1750 return false;
1751}
1752
1753void TreeViewItem::itemDropped (const DragAndDropTarget::SourceDetails& /*dragSourceDetails*/, int /*insertIndex*/)
1754{
1755}
1756
1757Rectangle<int> TreeViewItem::getItemPosition (const bool relativeToTreeViewTopLeft) const noexcept
1758{
1759 auto indentX = getIndentX();
1760 auto width = itemWidth;
1761
1762 if (ownerView != nullptr && width < 0)
1763 width = ownerView->viewport->getViewWidth() - indentX;
1764
1765 Rectangle<int> r (indentX, y, jmax (0, width), totalHeight);
1766
1767 if (relativeToTreeViewTopLeft && ownerView != nullptr)
1768 r -= ownerView->viewport->getViewPosition();
1769
1770 return r;
1771}
1772
1774{
1775 if (ownerView != nullptr)
1776 ownerView->updateVisibleItems();
1777}
1778
1780{
1781 if (ownerView != nullptr && areAllParentsOpen())
1782 if (auto* component = ownerView->getItemComponent (this))
1783 component->repaint();
1784}
1785
1787{
1788 return parentItem == nullptr
1789 || (parentItem->isOpen() && parentItem->areAllParentsOpen());
1790}
1791
1793{
1794 y = newY;
1799
1800 if (isOpen())
1801 {
1802 newY += totalHeight;
1803
1804 for (auto* i : subItems)
1805 {
1806 i->updatePositions (newY);
1807 newY += i->totalHeight;
1808 totalHeight += i->totalHeight;
1809 totalWidth = jmax (totalWidth, i->totalWidth);
1810 }
1811 }
1812}
1813
1815{
1816 auto* result = this;
1817 auto* item = this;
1818
1819 while (item->parentItem != nullptr)
1820 {
1821 item = item->parentItem;
1822
1823 if (! item->isOpen())
1824 result = item;
1825 }
1826
1827 return result;
1828}
1829
1830void TreeViewItem::setOwnerView (TreeView* const newOwner) noexcept
1831{
1832 ownerView = newOwner;
1833
1834 for (auto* i : subItems)
1835 {
1836 i->setOwnerView (newOwner);
1837 i->ownerViewChanged (newOwner);
1838 }
1839}
1840
1842{
1843 if (ownerView == nullptr)
1844 return 0;
1845
1846 int x = ownerView->rootItemVisible ? 1 : 0;
1847
1848 if (! ownerView->openCloseButtonsVisible)
1849 --x;
1850
1851 for (auto* p = parentItem; p != nullptr; p = p->parentItem)
1852 ++x;
1853
1854 return x * ownerView->getIndentSize();
1855}
1856
1857void TreeViewItem::setDrawsInLeftMargin (bool canDrawInLeftMargin) noexcept
1858{
1859 drawsInLeftMargin = canDrawInLeftMargin;
1860}
1861
1862void TreeViewItem::setDrawsInRightMargin (bool canDrawInRightMargin) noexcept
1863{
1864 drawsInRightMargin = canDrawInRightMargin;
1865}
1866
1868{
1870 : (ownerView != nullptr && ownerView->getLookAndFeel().areLinesDrawnForTreeView (*ownerView));
1871}
1872
1874{
1875 return parentItem == nullptr
1876 || parentItem->subItems.getLast() == this;
1877}
1878
1880{
1881 return parentItem == nullptr ? 0
1882 : parentItem->subItems.indexOf (this);
1883}
1884
1886{
1887 return parentItem == nullptr ? this
1888 : parentItem->getTopLevelItem();
1889}
1890
1892{
1893 int num = 1;
1894
1895 if (isOpen())
1896 for (auto* i : subItems)
1897 num += i->getNumRows();
1898
1899 return num;
1900}
1901
1903{
1904 if (index == 0)
1905 return this;
1906
1907 if (index > 0 && isOpen())
1908 {
1909 --index;
1910
1911 for (auto* i : subItems)
1912 {
1913 if (index == 0)
1914 return i;
1915
1916 auto numRows = i->getNumRows();
1917
1918 if (numRows > index)
1919 return i->getItemOnRow (index);
1920
1921 index -= numRows;
1922 }
1923 }
1924
1925 return nullptr;
1926}
1927
1929{
1930 int total = isSelected() ? 1 : 0;
1931
1932 if (depth != 0)
1933 for (auto* i : subItems)
1934 total += i->countSelectedItemsRecursively (depth - 1);
1935
1936 return total;
1937}
1938
1940{
1941 if (isSelected())
1942 {
1943 if (index == 0)
1944 return this;
1945
1946 --index;
1947 }
1948
1949 if (index >= 0)
1950 {
1951 for (auto* i : subItems)
1952 {
1953 if (auto* found = i->getSelectedItemWithIndex (index))
1954 return found;
1955
1956 index -= i->countSelectedItemsRecursively (-1);
1957 }
1958 }
1959
1960 return nullptr;
1961}
1962
1964{
1965 if (parentItem != nullptr && ownerView != nullptr)
1966 {
1967 if (! parentItem->isOpen())
1968 return parentItem->getRowNumberInTree();
1969
1970 auto n = 1 + parentItem->getRowNumberInTree();
1971
1972 auto ourIndex = parentItem->subItems.indexOf (this);
1973 jassert (ourIndex >= 0);
1974
1975 while (--ourIndex >= 0)
1976 n += parentItem->subItems [ourIndex]->getNumRows();
1977
1978 if (parentItem->parentItem == nullptr
1979 && ! ownerView->rootItemVisible)
1980 --n;
1981
1982 return n;
1983 }
1984
1985 return 0;
1986}
1987
1988void TreeViewItem::setLinesDrawnForSubItems (bool drawLines) noexcept
1989{
1990 drawLinesInside = drawLines;
1991 drawLinesSet = true;
1992}
1993
1995{
1996 return s.replaceCharacter ('/', '\\');
1997}
1998
2000{
2001 String s;
2002
2003 if (parentItem != nullptr)
2004 s = parentItem->getItemIdentifierString();
2005
2007}
2008
2010{
2011 auto thisId = "/" + escapeSlashesInTreeViewItemName (getUniqueName());
2012
2013 if (thisId == identifierString)
2014 return this;
2015
2016 if (identifierString.startsWith (thisId + "/"))
2017 {
2018 auto remainingPath = identifierString.substring (thisId.length());
2019
2020 const auto wasOpen = isOpen();
2021 setOpen (true);
2022
2023 for (auto* i : subItems)
2024 if (auto* item = i->findItemFromIdentifierString (remainingPath))
2025 return item;
2026
2027 setOpen (wasOpen);
2028 }
2029
2030 return nullptr;
2031}
2032
2034{
2035 if (e.hasTagName ("CLOSED"))
2036 {
2037 setOpen (false);
2038 }
2039 else if (e.hasTagName ("OPEN"))
2040 {
2041 setOpen (true);
2042
2044 items.addArray (subItems);
2045
2046 for (auto* n : e.getChildIterator())
2047 {
2048 auto id = n->getStringAttribute ("id");
2049
2050 for (int i = 0; i < items.size(); ++i)
2051 {
2052 auto* ti = items.getUnchecked (i);
2053
2054 if (ti->getUniqueName() == id)
2055 {
2056 ti->restoreOpennessState (*n);
2057 items.remove (i);
2058 break;
2059 }
2060 }
2061 }
2062
2063 // for any items that weren't mentioned in the XML, reset them to default:
2064 for (auto* i : items)
2065 i->restoreToDefaultOpenness();
2066 }
2067}
2068
2069std::unique_ptr<XmlElement> TreeViewItem::getOpennessState() const
2070{
2071 return getOpennessState (true);
2072}
2073
2074std::unique_ptr<XmlElement> TreeViewItem::getOpennessState (bool canReturnNull) const
2075{
2076 auto name = getUniqueName();
2077
2078 if (name.isNotEmpty())
2079 {
2080 std::unique_ptr<XmlElement> e;
2081
2082 if (isOpen())
2083 {
2084 if (canReturnNull && ownerView != nullptr && ownerView->defaultOpenness && isFullyOpen())
2085 return nullptr;
2086
2087 e = std::make_unique<XmlElement> ("OPEN");
2088
2089 for (int i = subItems.size(); --i >= 0;)
2090 e->prependChildElement (subItems.getUnchecked (i)->getOpennessState (true).release());
2091 }
2092 else
2093 {
2094 if (canReturnNull && ownerView != nullptr && ! ownerView->defaultOpenness)
2095 return nullptr;
2096
2097 e = std::make_unique<XmlElement> ("CLOSED");
2098 }
2099
2100 e->setAttribute ("id", name);
2101 return e;
2102 }
2103
2104 // trying to save the openness for an element that has no name - this won't
2105 // work because it needs the names to identify what to open.
2107 return {};
2108}
2109
2110//==============================================================================
2116
2118{
2119 if (oldOpenness != nullptr)
2120 treeViewItem.restoreOpennessState (*oldOpenness);
2121}
2122
2123void TreeViewItem::draw (Graphics& g, int width, bool isMouseOverButton)
2124{
2125 if (ownerView == nullptr)
2126 return;
2127
2128 const auto indent = getIndentX();
2129 const auto itemW = (itemWidth < 0 || drawsInRightMargin) ? width - indent : itemWidth;
2130
2131 {
2133 g.setOrigin (indent, 0);
2134
2135 if (g.reduceClipRegion (drawsInLeftMargin ? -indent : 0, 0,
2136 drawsInLeftMargin ? itemW + indent : itemW, itemHeight))
2137 {
2138 if (isSelected())
2140 else
2141 g.fillAll ((getRowNumberInTree() % 2 == 0) ? ownerView->findColour (TreeView::oddItemsColourId)
2142 : ownerView->findColour (TreeView::evenItemsColourId));
2143
2144 paintItem (g, itemWidth < 0 ? width - indent : itemWidth, itemHeight);
2145 }
2146 }
2147
2148 const auto halfH = (float) itemHeight * 0.5f;
2149 const auto indentWidth = ownerView->getIndentSize();
2150 const auto depth = getItemDepth (this);
2151
2152 if (depth >= 0 && ownerView->openCloseButtonsVisible)
2153 {
2154 auto x = ((float) depth + 0.5f) * (float) indentWidth;
2155 const auto parentLinesDrawn = parentItem != nullptr && parentItem->areLinesDrawn();
2156
2157 if (parentLinesDrawn)
2159
2160 if (parentLinesDrawn || (parentItem == nullptr && areLinesDrawn()))
2161 paintHorizontalConnectingLine (g, Line<float> (x, halfH, x + (float) indentWidth * 0.5f, halfH));
2162
2163 {
2164 auto* p = parentItem;
2165 auto d = depth;
2166
2167 while (p != nullptr && --d >= 0)
2168 {
2169 x -= (float) indentWidth;
2170
2171 if ((p->parentItem == nullptr || p->parentItem->areLinesDrawn()) && ! p->isLastOfSiblings())
2172 p->paintVerticalConnectingLine (g, Line<float> (x, 0, x, (float) itemHeight));
2173
2174 p = p->parentItem;
2175 }
2176 }
2177
2179 {
2180 auto backgroundColour = ownerView->findColour (TreeView::backgroundColourId);
2181
2182 paintOpenCloseButton (g, Rectangle<float> ((float) (depth * indentWidth), 0, (float) indentWidth, (float) itemHeight),
2183 backgroundColour.isTransparent() ? Colours::white : backgroundColour,
2184 isMouseOverButton);
2185 }
2186 }
2187}
2188
2189} // namespace juce
Type jmax(const Type a, const Type b)
Definition MathsFunctions.h:48
#define noexcept
Definition DistrhoDefines.h:72
#define nullptr
Definition DistrhoDefines.h:75
Definition juce_AccessibilityActions.h:73
AccessibilityActions & addAction(AccessibilityActionType type, std::function< void()> actionCallback)
Definition juce_AccessibilityActions.h:88
Definition juce_AccessibilityCellInterface.h:37
Definition juce_AccessibilityHandler.h:41
virtual AccessibleState getCurrentState() const
Definition juce_AccessibilityHandler.cpp:75
AccessibilityActions actions
Definition juce_AccessibilityHandler.h:311
AccessibilityHandler(Component &componentToWrap, AccessibilityRole accessibilityRole, AccessibilityActions actions={}, Interfaces interfaces={})
Definition juce_AccessibilityHandler.cpp:55
Definition juce_AccessibilityTableInterface.h:37
Definition juce_AccessibilityState.h:39
Definition juce_Array.h:56
ElementType getUnchecked(int index) const
Definition juce_Array.h:252
void addArray(const Type *elementsToAdd, int numElementsToAdd)
Definition juce_Array.h:583
int size() const noexcept
Definition juce_Array.h:215
void remove(int indexToRemove)
Definition juce_Array.h:767
void triggerAsyncUpdate()
Definition juce_AsyncUpdater.cpp:62
AsyncUpdater()
Definition juce_AsyncUpdater.cpp:44
Definition juce_Colour.h:38
Definition juce_Component.h:2287
void setInterceptsMouseClicks(bool allowClicksOnThisComponent, bool allowClicksOnChildComponents) noexcept
Definition juce_Component.cpp:1420
Component * getParentComponent() const noexcept
Definition juce_Component.h:804
Image createComponentSnapshot(Rectangle< int > areaToGrab, bool clipImageToComponentBounds=true, float scaleFactor=1.0f)
Definition juce_Component.cpp:2135
bool isOpaque() const noexcept
Definition juce_Component.cpp:843
void setFocusContainerType(FocusContainerType containerType) noexcept
Definition juce_Component.cpp:2862
int getHeight() const noexcept
Definition juce_Component.h:274
static float JUCE_CALLTYPE getApproximateScaleFactorForComponent(const Component *targetComponent)
Definition juce_Component.cpp:1383
void addAndMakeVisible(Component *child, int zOrder=-1)
Definition juce_Component.cpp:1554
void setAlwaysOnTop(bool shouldStayOnTop)
Definition juce_Component.cpp:1074
void setOpaque(bool shouldBeOpaque)
Definition juce_Component.cpp:829
void repaint()
Definition juce_Component.cpp:1917
Component() noexcept
Definition juce_Component.cpp:517
@ focusContainer
Definition juce_Component.h:1295
Point< int > getMouseXYRelative() const
Definition juce_Component.cpp:3210
int getY() const noexcept
Definition juce_Component.h:268
void setBounds(int x, int y, int width, int height)
Definition juce_Component.cpp:1147
void setSize(int newWidth, int newHeight)
Definition juce_Component.cpp:1262
void setWantsKeyboardFocus(bool wantsFocus) noexcept
Definition juce_Component.cpp:2842
Colour findColour(int colourID, bool inheritFromParent=false) const
Definition juce_Component.cpp:2219
static std::unique_ptr< AccessibilityHandler > createIgnoredAccessibilityHandler(Component &)
Definition juce_Component.cpp:3292
int getWidth() const noexcept
Definition juce_Component.h:271
static void JUCE_CALLTYPE beginDragAutoRepeat(int millisecondsBetweenCallbacks)
Definition juce_Component.cpp:2745
bool isEnabled() const noexcept
Definition juce_Component.cpp:3104
LookAndFeel & getLookAndFeel() const noexcept
Definition juce_Component.cpp:2173
Rectangle< int > getLocalBounds() const noexcept
Definition juce_Component.cpp:2283
int getParentHeight() const noexcept
Definition juce_Component.cpp:1120
static Desktop &JUCE_CALLTYPE getInstance()
Definition juce_Desktop.cpp:50
static DragAndDropContainer * findParentDragContainerFor(Component *childComponent)
Definition juce_DragAndDropContainer.cpp:547
Definition juce_DragAndDropTarget.h:54
Point< int > localPosition
Definition juce_DragAndDropTarget.h:70
Definition juce_GraphicsContext.h:660
Definition juce_GraphicsContext.h:45
Definition juce_KeyPress.h:40
static const int homeKey
Definition juce_KeyPress.h:204
static const int upKey
Definition juce_KeyPress.h:198
static const int endKey
Definition juce_KeyPress.h:205
static const int rightKey
Definition juce_KeyPress.h:201
static const int downKey
Definition juce_KeyPress.h:199
static const int returnKey
Definition juce_KeyPress.h:191
static const int leftKey
Definition juce_KeyPress.h:200
static const int pageUpKey
Definition juce_KeyPress.h:202
static const int pageDownKey
Definition juce_KeyPress.h:203
Definition juce_Line.h:47
Definition juce_ModifierKeys.h:41
bool isCommandDown() const noexcept
Definition juce_ModifierKeys.h:68
bool isShiftDown() const noexcept
Definition juce_ModifierKeys.h:99
@ leftButtonModifier
Definition juce_ModifierKeys.h:130
@ popupMenuClickModifier
Definition juce_ModifierKeys.h:151
Definition juce_MouseEvent.h:39
static constexpr float defaultRotation
Definition juce_MouseInputSource.h:233
static constexpr float defaultTiltX
Definition juce_MouseInputSource.h:236
static constexpr float defaultTiltY
Definition juce_MouseInputSource.h:237
static constexpr float defaultOrientation
Definition juce_MouseInputSource.h:230
static constexpr float defaultPressure
Definition juce_MouseInputSource.h:227
Definition juce_Path.h:65
Definition juce_PathStrokeType.h:42
Definition juce_Point.h:42
ValueType y
Definition juce_Point.h:247
ValueType x
Definition juce_Point.h:246
Definition juce_Rectangle.h:67
Rectangle< float > toFloat() const noexcept
Definition juce_Rectangle.h:873
Point< ValueType > getTopLeft() const noexcept
Definition juce_Rectangle.h:170
ValueType getX() const noexcept
Definition juce_Rectangle.h:127
Definition juce_StringArray.h:35
Definition juce_String.h:53
bool startsWith(StringRef text) const noexcept
Definition juce_String.cpp:1393
String substring(int startIndex, int endIndex) const
Definition juce_String.cpp:1498
static Time JUCE_CALLTYPE getCurrentTime() noexcept
Definition juce_Time.cpp:233
Definition juce_TooltipClient.h:42
Definition juce_TreeView.cpp:256
std::vector< std::unique_ptr< ItemComponent > > itemComponents
Definition juce_TreeView.cpp:666
void handleAsyncUpdate() override
Definition juce_TreeView.cpp:560
void itemBeingDeleted(const TreeViewItem *item)
Definition juce_TreeView.cpp:312
bool needSelectionOnMouseUp
Definition juce_TreeView.cpp:669
ItemComponent * getComponentForItem(const TreeViewItem *item) const
Definition juce_TreeView.cpp:298
void mouseDragInternal(const MouseEvent &e)
Definition juce_TreeView.cpp:464
static TreeViewItem * getNextVisibleItem(TreeViewItem *item, bool forwards)
Definition juce_TreeView.cpp:602
std::vector< TreeViewItem * > getAllVisibleItems() const
Definition juce_TreeView.cpp:613
void mouseDoubleClick(const MouseEvent &e) override
Definition juce_TreeView.cpp:278
ItemComponent * itemUnderMouse
Definition juce_TreeView.cpp:667
ContentComponent(TreeView &tree)
Definition juce_TreeView.cpp:258
static bool isMouseDraggingInChildComp(const Component &comp)
Definition juce_TreeView.cpp:515
void mouseDown(const MouseEvent &e) override
Definition juce_TreeView.cpp:276
void mouseMoveInternal(const MouseEvent &e)
Definition juce_TreeView.cpp:512
std::unique_ptr< AccessibilityHandler > createAccessibilityHandler() override
Definition juce_TreeView.cpp:395
std::unique_ptr< ScopedDisableViewportScroll > scopedScrollDisabler
Definition juce_TreeView.cpp:668
bool isDragging
Definition juce_TreeView.cpp:669
TreeView & owner
Definition juce_TreeView.cpp:664
void mouseMove(const MouseEvent &e) override
Definition juce_TreeView.cpp:280
void mouseDrag(const MouseEvent &e) override
Definition juce_TreeView.cpp:279
String getTooltip() override
Definition juce_TreeView.cpp:268
void mouseUpInternal(const MouseEvent &e)
Definition juce_TreeView.cpp:440
void updateItemUnderMouse(const MouseEvent &e)
Definition juce_TreeView.cpp:525
void mouseUp(const MouseEvent &e) override
Definition juce_TreeView.cpp:277
void resized() override
Definition juce_TreeView.cpp:263
void selectBasedOnModifiers(TreeViewItem &item, const ModifierKeys modifiers)
Definition juce_TreeView.cpp:566
void mouseExitInternal(const MouseEvent &e)
Definition juce_TreeView.cpp:513
void mouseDownInternal(const MouseEvent &e)
Definition juce_TreeView.cpp:400
void mouseDoubleClickInternal(const MouseEvent &e)
Definition juce_TreeView.cpp:449
ItemComponent * getItemComponentAt(Point< int > p)
Definition juce_TreeView.cpp:284
void mouseExit(const MouseEvent &e) override
Definition juce_TreeView.cpp:281
void updateComponents()
Definition juce_TreeView.cpp:332
Definition juce_TreeView.cpp:1252
int lastIndex
Definition juce_TreeView.cpp:1283
void paint(Graphics &g) override
Definition juce_TreeView.cpp:1270
InsertPointHighlight()
Definition juce_TreeView.cpp:1254
void setTargetPosition(const InsertPoint &insertPos, const int width) noexcept
Definition juce_TreeView.cpp:1261
TreeViewItem * lastItem
Definition juce_TreeView.cpp:1282
ItemCellInterface(ItemComponent &c)
Definition juce_TreeView.cpp:144
int getRowIndex() const override
Definition juce_TreeView.cpp:149
int getColumnIndex() const override
Definition juce_TreeView.cpp:146
const AccessibilityHandler * getTableHandler() const override
Definition juce_TreeView.cpp:164
int getColumnSpan() const override
Definition juce_TreeView.cpp:147
int getDisclosureLevel() const override
Definition juce_TreeView.cpp:159
ItemComponent & itemComponent
Definition juce_TreeView.cpp:173
int getRowSpan() const override
Definition juce_TreeView.cpp:154
String getTitle() const override
Definition juce_TreeView.cpp:101
ItemAccessibilityHandler(ItemComponent &comp)
Definition juce_TreeView.cpp:92
static MouseEvent generateMouseEvent(ItemComponent &itemComp, ModifierKeys mods)
Definition juce_TreeView.cpp:220
ItemComponent & itemComponent
Definition juce_TreeView.cpp:218
static AccessibilityActions getAccessibilityActions(ItemComponent &itemComponent)
Definition juce_TreeView.cpp:177
String getHelp() const override
Definition juce_TreeView.cpp:106
AccessibleState getCurrentState() const override
Definition juce_TreeView.cpp:111
Definition juce_TreeView.cpp:45
std::unique_ptr< AccessibilityHandler > createAccessibilityHandler() override
Definition juce_TreeView.cpp:233
TreeViewItem & getRepresentedItem() const noexcept
Definition juce_TreeView.cpp:77
bool mouseIsOverButton
Definition juce_TreeView.cpp:246
void paint(Graphics &g) override
Definition juce_TreeView.cpp:55
bool hasCustomComponent() const noexcept
Definition juce_TreeView.cpp:241
std::unique_ptr< Component > customComponent
Definition juce_TreeView.cpp:244
void resized() override
Definition juce_TreeView.cpp:60
ItemComponent(TreeViewItem &itemToRepresent)
Definition juce_TreeView.cpp:47
TreeViewItem & item
Definition juce_TreeView.cpp:243
String getTooltip() override
Definition juce_TreeView.cpp:82
void setMouseIsOverButton(bool isOver)
Definition juce_TreeView.cpp:71
Definition juce_TreeView.cpp:1291
void paint(Graphics &g) override
Definition juce_TreeView.cpp:1305
void setTargetPosition(TreeViewItem *const item) noexcept
Definition juce_TreeView.cpp:1299
TargetGroupHighlight()
Definition juce_TreeView.cpp:1293
Definition juce_TreeView.cpp:677
std::unique_ptr< AccessibilityHandler > createAccessibilityHandler() override
Definition juce_TreeView.cpp:719
void visibleAreaChanged(const Rectangle< int > &newVisibleArea) override
Definition juce_TreeView.cpp:681
bool needsRecalculating
Definition juce_TreeView.cpp:770
int lastX
Definition juce_TreeView.cpp:769
ContentComponent * getContentComp() const noexcept
Definition juce_TreeView.cpp:701
void recalculatePositions(Async useAsyncUpdate)
Definition juce_TreeView.cpp:708
bool keyPressed(const KeyPress &key) override
Definition juce_TreeView.cpp:692
bool structureChanged
Definition juce_TreeView.cpp:770
Async
Definition juce_TreeView.cpp:706
@ no
Definition juce_TreeView.cpp:706
@ yes
Definition juce_TreeView.cpp:706
void handleAsyncUpdate() override
Definition juce_TreeView.cpp:724
TreeViewport(TreeView &treeView)
Definition juce_TreeView.cpp:679
void updateComponents(bool triggerResize)
Definition juce_TreeView.cpp:755
TreeView & owner
Definition juce_TreeView.cpp:768
TreeViewItem * findItemFromIdentifierString(const String &identifierString) const
Definition juce_TreeView.cpp:933
bool isInterestedInFileDrag(const StringArray &) override
Definition juce_TreeView.cpp:1390
TreeViewItem * getSelectedItem(int index) const noexcept
Definition juce_TreeView.cpp:903
bool rootItemVisible
Definition juce_TreeView.h:954
void showDragHighlight(const InsertPoint &) noexcept
Definition juce_TreeView.cpp:1316
Component * getItemComponent(const TreeViewItem *item) const
Definition juce_TreeView.cpp:941
void filesDropped(const StringArray &, int, int) override
Definition juce_TreeView.cpp:1410
std::unique_ptr< TargetGroupHighlight > dragTargetGroupHighlight
Definition juce_TreeView.h:952
TreeViewItem * getItemOnRow(int index) const
Definition juce_TreeView.cpp:913
void colourChanged() override
Definition juce_TreeView.cpp:842
@ dragAndDropIndicatorColourId
Definition juce_TreeView.h:872
@ oddItemsColourId
Definition juce_TreeView.h:874
@ linesColourId
Definition juce_TreeView.h:871
@ evenItemsColourId
Definition juce_TreeView.h:875
@ selectedItemBackgroundColourId
Definition juce_TreeView.h:873
@ backgroundColourId
Definition juce_TreeView.h:870
TreeViewItem * getRootItem() const noexcept
Definition juce_TreeView.h:691
void moveOutOfSelectedItem()
Definition juce_TreeView.cpp:1093
void moveSelectedRow(int deltaRows)
Definition juce_TreeView.cpp:1015
void setDefaultOpenness(bool isOpenByDefault)
Definition juce_TreeView.cpp:863
TreeViewItem * rootItem
Definition juce_TreeView.h:950
int getNumRowsInTree() const
Definition juce_TreeView.cpp:908
void updateVisibleItems()
Definition juce_TreeView.cpp:1177
TreeView(const String &componentName={})
Definition juce_TreeView.cpp:776
void handleDrag(const StringArray &, const SourceDetails &)
Definition juce_TreeView.cpp:1339
TreeViewItem * getItemAt(int yPosition) const noexcept
Definition juce_TreeView.cpp:924
Viewport * getViewport() const noexcept
Definition juce_TreeView.cpp:886
void fileDragMove(const StringArray &, int, int) override
Definition juce_TreeView.cpp:1400
void clearSelectedItems()
Definition juce_TreeView.cpp:892
bool multiSelectEnabled
Definition juce_TreeView.h:954
void resized() override
Definition juce_TreeView.cpp:1004
std::unique_ptr< AccessibilityHandler > createAccessibilityHandler() override
Definition juce_TreeView.cpp:1441
void paint(Graphics &) override
Definition juce_TreeView.cpp:999
void itemDragEnter(const SourceDetails &) override
Definition juce_TreeView.cpp:1420
void restoreOpennessState(const XmlElement &newState, bool restoreStoredSelection)
Definition juce_TreeView.cpp:975
friend class TreeViewItem
Definition juce_TreeView.h:926
int indentSize
Definition juce_TreeView.h:953
bool isInterestedInDragSource(const SourceDetails &) override
Definition juce_TreeView.cpp:1415
bool openCloseButtonsVisible
Definition juce_TreeView.h:954
std::unique_ptr< XmlElement > getOpennessState(bool alsoIncludeScrollPosition) const
Definition juce_TreeView.cpp:958
void handleDrop(const StringArray &, const SourceDetails &)
Definition juce_TreeView.cpp:1365
void scrollToKeepItemVisible(TreeViewItem *item)
Definition juce_TreeView.cpp:1056
bool keyPressed(const KeyPress &) override
Definition juce_TreeView.cpp:1159
std::unique_ptr< InsertPointHighlight > dragInsertPointHighlight
Definition juce_TreeView.h:951
void fileDragEnter(const StringArray &, int, int) override
Definition juce_TreeView.cpp:1395
int getNumSelectedItems(int maximumDepthToSearchTo=-1) const noexcept
Definition juce_TreeView.cpp:898
void itemDropped(const SourceDetails &) override
Definition juce_TreeView.cpp:1435
void enablementChanged() override
Definition juce_TreeView.cpp:1010
void moveByPages(int)
Definition juce_TreeView.cpp:1128
bool defaultOpenness
Definition juce_TreeView.h:954
void itemDragMove(const SourceDetails &) override
Definition juce_TreeView.cpp:1425
void setIndentSize(int newIndentSize)
Definition juce_TreeView.cpp:848
void fileDragExit(const StringArray &) override
Definition juce_TreeView.cpp:1405
std::unique_ptr< TreeViewport > viewport
Definition juce_TreeView.h:949
int getIndentSize() noexcept
Definition juce_TreeView.cpp:857
void setOpenCloseButtonsVisible(bool shouldBeVisible)
Definition juce_TreeView.cpp:877
void deleteRootItem()
Definition juce_TreeView.cpp:823
bool isRootItemVisible() const noexcept
Definition juce_TreeView.h:711
void hideDragHighlight() noexcept
Definition juce_TreeView.cpp:1333
~TreeView() override
Definition juce_TreeView.cpp:786
void setMultiSelectEnabled(bool canMultiSelect)
Definition juce_TreeView.cpp:872
void itemDragExit(const SourceDetails &) override
Definition juce_TreeView.cpp:1430
bool toggleOpenSelectedItem()
Definition juce_TreeView.cpp:1079
void moveIntoSelectedItem()
Definition juce_TreeView.cpp:1117
void setRootItem(TreeViewItem *newRootItem)
Definition juce_TreeView.cpp:792
void setRootItemVisible(bool shouldBeVisible)
Definition juce_TreeView.cpp:829
OpennessRestorer(TreeViewItem &)
Definition juce_TreeView.cpp:2111
~OpennessRestorer()
Definition juce_TreeView.cpp:2117
std::unique_ptr< XmlElement > oldOpenness
Definition juce_TreeView.h:603
TreeViewItem & treeViewItem
Definition juce_TreeView.h:602
Definition juce_TreeView.h:48
virtual bool canBeSelected() const
Definition juce_TreeView.h:307
TreeView * getOwnerView() const noexcept
Definition juce_TreeView.h:130
TreeViewItem * parentItem
Definition juce_TreeView.h:633
virtual String getUniqueName() const
Definition juce_TreeView.cpp:1484
void removeSubItem(int index, bool deleteItem=true)
Definition juce_TreeView.cpp:1556
TreeViewItem * getSelectedItemWithIndex(int) noexcept
Definition juce_TreeView.cpp:1939
friend class TreeView
Definition juce_TreeView.h:610
bool isSelected() const noexcept
Definition juce_TreeView.cpp:1632
TreeViewItem * getTopLevelItem() noexcept
Definition juce_TreeView.cpp:1885
bool drawLinesSet
Definition juce_TreeView.h:638
void setDrawsInRightMargin(bool canDrawInRightMargin) noexcept
Definition juce_TreeView.cpp:1862
bool isFullyOpen() const noexcept
Definition juce_TreeView.cpp:1615
void clearSubItems()
Definition juce_TreeView.cpp:1503
void restoreToDefaultOpenness()
Definition juce_TreeView.cpp:1627
virtual void itemDropped(const DragAndDropTarget::SourceDetails &dragSourceDetails, int insertIndex)
Definition juce_TreeView.cpp:1753
void setDrawsInLeftMargin(bool canDrawInLeftMargin) noexcept
Definition juce_TreeView.cpp:1857
int getNumSubItems() const noexcept
Definition juce_TreeView.cpp:1493
virtual bool mightContainSubItems()=0
virtual void itemClicked(const MouseEvent &)
Definition juce_TreeView.cpp:1702
void setOpenness(Openness newOpenness)
Definition juce_TreeView.cpp:1587
bool removeSubItemFromList(int, bool)
Definition juce_TreeView.cpp:1569
int getIndexInParent() const noexcept
Definition juce_TreeView.cpp:1879
virtual void paintItem(Graphics &g, int width, int height)
Definition juce_TreeView.cpp:1680
virtual void itemDoubleClicked(const MouseEvent &)
Definition juce_TreeView.cpp:1706
virtual int getItemWidth() const
Definition juce_TreeView.h:294
void restoreOpennessState(const XmlElement &xml)
Definition juce_TreeView.cpp:2033
TreeViewItem * getDeepestOpenParentItem() noexcept
Definition juce_TreeView.cpp:1814
virtual bool isInterestedInDragSource(const DragAndDropTarget::SourceDetails &dragSourceDetails)
Definition juce_TreeView.cpp:1748
virtual void paintOpenCloseButton(Graphics &, const Rectangle< float > &area, Colour backgroundColour, bool isMouseOver)
Definition juce_TreeView.cpp:1684
int countSelectedItemsRecursively(int) const noexcept
Definition juce_TreeView.cpp:1928
void removeAllSubItemsFromList()
Definition juce_TreeView.cpp:1519
virtual void paintHorizontalConnectingLine(Graphics &, const Line< float > &line)
Definition juce_TreeView.cpp:1690
OwnedArray< TreeViewItem > subItems
Definition juce_TreeView.h:634
TreeView * ownerView
Definition juce_TreeView.h:632
int y
Definition juce_TreeView.h:637
TreeViewItem * findItemFromIdentifierString(const String &)
Definition juce_TreeView.cpp:2009
virtual void itemOpennessChanged(bool isNowOpen)
Definition juce_TreeView.cpp:1489
bool isOpen() const noexcept
Definition juce_TreeView.cpp:1600
void setLinesDrawnForSubItems(bool shouldDrawLines) noexcept
Definition juce_TreeView.cpp:1988
void updatePositions(int)
Definition juce_TreeView.cpp:1792
void treeHasChanged() const noexcept
Definition juce_TreeView.cpp:1773
int getRowNumberInTree() const noexcept
Definition juce_TreeView.cpp:1963
void setOpen(bool shouldBeOpen)
Definition juce_TreeView.cpp:1608
TreeViewItem()
Definition juce_TreeView.cpp:1472
void deselectAllRecursively(TreeViewItem *)
Definition juce_TreeView.cpp:1637
void repaintItem() const
Definition juce_TreeView.cpp:1779
Openness getOpenness() const noexcept
Definition juce_TreeView.cpp:1582
bool drawLinesInside
Definition juce_TreeView.h:638
virtual int getItemHeight() const
Definition juce_TreeView.h:302
virtual bool isInterestedInFileDrag(const StringArray &files)
Definition juce_TreeView.cpp:1739
std::unique_ptr< XmlElement > getOpennessState() const
Definition juce_TreeView.cpp:2069
bool drawsInLeftMargin
Definition juce_TreeView.h:639
virtual ~TreeViewItem()
Definition juce_TreeView.cpp:1478
int getIndentX() const noexcept
Definition juce_TreeView.cpp:1841
bool areLinesDrawn() const
Definition juce_TreeView.cpp:1867
virtual void ownerViewChanged(TreeView *newOwner)
Definition juce_TreeView.cpp:1730
virtual void itemSelectionChanged(bool isNowSelected)
Definition juce_TreeView.cpp:1712
virtual void filesDropped(const StringArray &files, int insertIndex)
Definition juce_TreeView.cpp:1744
virtual String getTooltip()
Definition juce_TreeView.cpp:1716
void addSubItem(TreeViewItem *newItem, int insertPosition=-1)
Definition juce_TreeView.cpp:1525
int itemHeight
Definition juce_TreeView.h:637
void setOwnerView(TreeView *) noexcept
Definition juce_TreeView.cpp:1830
bool isLastOfSiblings() const noexcept
Definition juce_TreeView.cpp:1873
TreeViewItem * getSubItem(int index) const noexcept
Definition juce_TreeView.cpp:1498
void draw(Graphics &, int, bool)
Definition juce_TreeView.cpp:2123
virtual String getAccessibilityName()
Definition juce_TreeView.cpp:1721
TreeViewItem * getParentItem() const noexcept
Definition juce_TreeView.h:133
int totalWidth
Definition juce_TreeView.h:637
Openness
Definition juce_TreeView.h:159
@ opennessClosed
Definition juce_TreeView.h:161
@ opennessOpen
Definition juce_TreeView.h:162
@ opennessDefault
Definition juce_TreeView.h:160
String getItemIdentifierString() const
Definition juce_TreeView.cpp:1999
virtual var getDragSourceDescription()
Definition juce_TreeView.cpp:1734
int getNumRows() const noexcept
Definition juce_TreeView.cpp:1891
TreeViewItem * getItemOnRow(int) noexcept
Definition juce_TreeView.cpp:1902
bool drawsInRightMargin
Definition juce_TreeView.h:639
Rectangle< int > getItemPosition(bool relativeToTreeViewTopLeft) const noexcept
Definition juce_TreeView.cpp:1757
virtual void paintVerticalConnectingLine(Graphics &, const Line< float > &line)
Definition juce_TreeView.cpp:1696
int uid
Definition juce_TreeView.h:637
int totalHeight
Definition juce_TreeView.h:637
bool areAllParentsOpen() const noexcept
Definition juce_TreeView.cpp:1786
bool selected
Definition juce_TreeView.h:638
int itemWidth
Definition juce_TreeView.h:637
void setSelected(bool shouldBeSelected, bool deselectOtherItemsFirst, NotificationType shouldNotify=sendNotification)
Definition juce_TreeView.cpp:1646
Openness openness
Definition juce_TreeView.h:636
Definition juce_Viewport.h:47
Component * getViewedComponent() const noexcept
Definition juce_Viewport.h:83
bool keyPressed(const KeyPress &) override
Definition juce_Viewport.cpp:621
int getMaximumVisibleWidth() const
Definition juce_Viewport.cpp:246
Viewport(const String &componentName=String())
Definition juce_Viewport.cpp:160
Definition juce_XmlElement.h:83
Iterator< GetNextElementWithTagName > getChildWithTagNameIterator(StringRef name) const
Definition juce_XmlElement.h:730
bool hasAttribute(StringRef attributeName) const noexcept
Definition juce_XmlElement.cpp:549
int getIntAttribute(StringRef attributeName, int defaultReturnValue=0) const
Definition juce_XmlElement.cpp:571
Definition juce_Variant.h:42
* e
Definition inflate.c:1404
int y
Definition inflate.c:1588
unsigned d
Definition inflate.c:940
int g
Definition inflate.c:1573
register unsigned i
Definition inflate.c:1575
unsigned s
Definition inflate.c:1555
unsigned x[BMAX+1]
Definition inflate.c:1586
static const char * name
Definition pugl.h:1582
static int width
Definition pugl.h:1593
static uintptr_t parent
Definition pugl.h:1644
#define jassert(expression)
#define JUCE_DECLARE_NON_COPYABLE(className)
#define JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(className)
#define jassertfalse
static int JUCE_CDECL comp(const void *a, const void *b)
Definition lsp.c:298
static char ** files
Definition misc.c:28
const Colour white
Definition juce_Colours.h:180
Definition carla_juce.cpp:31
@ no
Definition juce_AlertWindow.cpp:567
@ yes
Definition juce_AlertWindow.cpp:567
constexpr Type jmax(Type a, Type b)
Definition juce_MathsFunctions.h:94
Type jlimit(Type lowerLimit, Type upperLimit, Type valueToConstrain) noexcept
Definition juce_MathsFunctions.h:262
static int getItemDepth(const TreeViewItem *item)
Definition juce_TreeView.cpp:29
@ rowSelectionChanged
Definition juce_AccessibilityEvent.h:78
@ structureChanged
Definition juce_AccessibilityEvent.h:57
NotificationType
Definition juce_NotificationType.h:32
@ dontSendNotification
Definition juce_NotificationType.h:33
static String escapeSlashesInTreeViewItemName(const String &s)
Definition juce_TreeView.cpp:1994
@ showMenu
Definition juce_AccessibilityActions.h:61
@ focus
Definition juce_AccessibilityActions.h:54
@ toggle
Definition juce_AccessibilityActions.h:47
@ press
Definition juce_AccessibilityActions.h:40
static void addAllSelectedItemIds(TreeViewItem *item, XmlElement &parent)
Definition juce_TreeView.cpp:947
AccessibilityRole
Definition juce_AccessibilityRole.h:37
@ treeItem
Definition juce_AccessibilityRole.h:59
@ tree
Definition juce_AccessibilityRole.h:58
@ row
Definition juce_AccessibilityRole.h:53
Definition juce_AccessibilityHandler.h:49
SafePointer< ItemComponent > item
Definition juce_TreeView.cpp:389
~ScopedDisableViewportScroll()
Definition juce_TreeView.cpp:383
ScopedDisableViewportScroll(ItemComponent &c)
Definition juce_TreeView.cpp:377
Definition juce_TreeView.cpp:1184
InsertPoint(TreeView &view, const StringArray &files, const DragAndDropTarget::SourceDetails &dragSourceDetails)
Definition juce_TreeView.cpp:1185
int insertIndex
Definition juce_TreeView.cpp:1247
Point< int > pos
Definition juce_TreeView.cpp:1245
TreeViewItem * item
Definition juce_TreeView.cpp:1246
int n
Definition crypt.c:458
uch * p
Definition crypt.c:594
return c
Definition crypt.c:175
ZCONST char * key
Definition crypt.c:587
int r
Definition crypt.c:458
uch h[RAND_HEAD_LEN]
Definition crypt.c:459
void handler(int signal)
Definition fileio.c:1632
int result
Definition process.c:1455
ss
Definition zipinfo.c:2292
#define const
Definition zconf.h:137