| @@ -6601,13 +6601,13 @@ static const unsigned char temp16[] = {47,42,13,10,32,32,61,61,61,61,61,61,61,61 | |||
| 102,105,108,101,84,114,101,101,67,111,109,112,45,62,103,101,116,72,101,105,103,104,116,40,41,41,59,13,10,32,32,32,32,125,13,10,13,10,32,32, | |||
| 32,32,118,111,105,100,32,114,101,115,105,122,101,100,40,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,105,102,32,40,116,114,101, | |||
| 101,86,105,101,119,32,33,61,32,48,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,116,114,101,101,86,105,101,119,45,62,115,101,116,66,111, | |||
| 117,110,100,115,82,101,108,97,116,105,118,101,32,40,48,46,48,53,102,44,32,48,46,48,55,102,44,32,48,46,57,102,44,32,48,46,57,102,41,59, | |||
| 117,110,100,115,73,110,115,101,116,32,40,66,111,114,100,101,114,83,105,122,101,32,40,52,48,44,32,49,48,44,32,49,48,44,32,49,48,41,41,59, | |||
| 13,10,32,32,32,32,32,32,32,32,101,108,115,101,32,105,102,32,40,102,105,108,101,84,114,101,101,67,111,109,112,32,33,61,32,48,41,13,10,32, | |||
| 32,32,32,32,32,32,32,32,32,32,32,102,105,108,101,84,114,101,101,67,111,109,112,45,62,115,101,116,66,111,117,110,100,115,82,101,108,97,116,105, | |||
| 118,101,32,40,48,46,48,53,102,44,32,48,46,48,55,102,44,32,48,46,57,102,44,32,48,46,57,102,41,59,13,10,13,10,32,32,32,32,32,32, | |||
| 32,32,116,121,112,101,66,117,116,116,111,110,45,62,99,104,97,110,103,101,87,105,100,116,104,84,111,70,105,116,84,101,120,116,32,40,50,48,41,59, | |||
| 32,32,32,32,32,32,32,32,32,32,32,102,105,108,101,84,114,101,101,67,111,109,112,45,62,115,101,116,66,111,117,110,100,115,73,110,115,101,116,32, | |||
| 40,66,111,114,100,101,114,83,105,122,101,32,40,52,48,44,32,49,48,44,32,49,48,44,32,49,48,41,41,59,13,10,13,10,32,32,32,32,32,32, | |||
| 32,32,116,121,112,101,66,117,116,116,111,110,45,62,99,104,97,110,103,101,87,105,100,116,104,84,111,70,105,116,84,101,120,116,32,40,50,50,41,59, | |||
| 13,10,32,32,32,32,32,32,32,32,116,121,112,101,66,117,116,116,111,110,45,62,115,101,116,84,111,112,76,101,102,116,80,111,115,105,116,105,111,110, | |||
| 32,40,52,48,44,32,49,48,41,59,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,118,111,105,100,32,115,104,111,119,67,117,115,116,111,109, | |||
| 32,40,49,48,44,32,49,48,41,59,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,118,111,105,100,32,115,104,111,119,67,117,115,116,111,109, | |||
| 84,114,101,101,86,105,101,119,40,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,100,101,108,101,116,101,65,110,100,90,101,114,111, | |||
| 32,40,116,114,101,101,86,105,101,119,41,59,13,10,32,32,32,32,32,32,32,32,100,101,108,101,116,101,65,110,100,90,101,114,111,32,40,102,105,108, | |||
| 101,84,114,101,101,67,111,109,112,41,59,13,10,13,10,32,32,32,32,32,32,32,32,97,100,100,65,110,100,77,97,107,101,86,105,115,105,98,108,101, | |||
| @@ -6625,12 +6625,37 @@ static const unsigned char temp16[] = {47,42,13,10,32,32,61,61,61,61,61,61,61,61 | |||
| 109,59,13,10,32,32,32,32,32,32,32,32,109,46,97,100,100,73,116,101,109,32,40,49,44,32,84,40,34,67,117,115,116,111,109,32,116,114,101,101, | |||
| 118,105,101,119,32,115,104,111,119,105,110,103,32,97,110,32,88,77,76,32,116,114,101,101,34,41,41,59,13,10,32,32,32,32,32,32,32,32,109,46, | |||
| 97,100,100,73,116,101,109,32,40,50,44,32,84,40,34,70,105,108,101,84,114,101,101,67,111,109,112,111,110,101,110,116,32,115,104,111,119,105,110,103, | |||
| 32,116,104,101,32,102,105,108,101,32,115,121,115,116,101,109,34,41,41,59,13,10,13,10,32,32,32,32,32,32,32,32,99,111,110,115,116,32,105,110, | |||
| 116,32,114,32,61,32,109,46,115,104,111,119,65,116,32,40,116,121,112,101,66,117,116,116,111,110,41,59,13,10,13,10,32,32,32,32,32,32,32,32, | |||
| 105,102,32,40,114,32,61,61,32,49,41,13,10,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,115,104,111,119, | |||
| 67,117,115,116,111,109,84,114,101,101,86,105,101,119,40,41,59,13,10,32,32,32,32,32,32,32,32,125,13,10,32,32,32,32,32,32,32,32,101,108, | |||
| 115,101,32,105,102,32,40,114,32,61,61,32,50,41,13,10,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,115, | |||
| 104,111,119,70,105,108,101,84,114,101,101,67,111,109,112,40,41,59,13,10,32,32,32,32,32,32,32,32,125,13,10,32,32,32,32,125,13,10,13,10, | |||
| 32,116,104,101,32,102,105,108,101,32,115,121,115,116,101,109,34,41,41,59,13,10,32,32,32,32,32,32,32,32,109,46,97,100,100,83,101,112,97,114, | |||
| 97,116,111,114,40,41,59,13,10,32,32,32,32,32,32,32,32,109,46,97,100,100,73,116,101,109,32,40,51,44,32,84,40,34,83,104,111,119,32,114, | |||
| 111,111,116,32,105,116,101,109,34,41,44,32,116,114,117,101,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,116,114, | |||
| 101,101,86,105,101,119,32,33,61,32,48,32,63,32,116,114,101,101,86,105,101,119,45,62,105,115,82,111,111,116,73,116,101,109,86,105,115,105,98,108, | |||
| 101,40,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,58,32, | |||
| 102,105,108,101,84,114,101,101,67,111,109,112,45,62,105,115,82,111,111,116,73,116,101,109,86,105,115,105,98,108,101,40,41,41,59,13,10,32,32,32, | |||
| 32,32,32,32,32,109,46,97,100,100,73,116,101,109,32,40,52,44,32,84,40,34,83,104,111,119,32,111,112,101,110,47,99,108,111,115,101,32,98,117, | |||
| 116,116,111,110,115,34,41,44,32,116,114,117,101,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,116,114,101,101,86, | |||
| 105,101,119,32,33,61,32,48,32,63,32,116,114,101,101,86,105,101,119,45,62,97,114,101,79,112,101,110,67,108,111,115,101,66,117,116,116,111,110,115, | |||
| 86,105,115,105,98,108,101,40,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, | |||
| 32,32,32,32,58,32,102,105,108,101,84,114,101,101,67,111,109,112,45,62,97,114,101,79,112,101,110,67,108,111,115,101,66,117,116,116,111,110,115,86, | |||
| 105,115,105,98,108,101,40,41,41,59,13,10,13,10,32,32,32,32,32,32,32,32,99,111,110,115,116,32,105,110,116,32,114,32,61,32,109,46,115,104, | |||
| 111,119,65,116,32,40,116,121,112,101,66,117,116,116,111,110,41,59,13,10,13,10,32,32,32,32,32,32,32,32,105,102,32,40,114,32,61,61,32,49, | |||
| 41,13,10,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,115,104,111,119,67,117,115,116,111,109,84,114,101,101, | |||
| 86,105,101,119,40,41,59,13,10,32,32,32,32,32,32,32,32,125,13,10,32,32,32,32,32,32,32,32,101,108,115,101,32,105,102,32,40,114,32,61, | |||
| 61,32,50,41,13,10,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,115,104,111,119,70,105,108,101,84,114,101, | |||
| 101,67,111,109,112,40,41,59,13,10,32,32,32,32,32,32,32,32,125,13,10,32,32,32,32,32,32,32,32,101,108,115,101,32,105,102,32,40,114,32, | |||
| 61,61,32,51,41,13,10,32,32,32,32,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,105,102,32,40,116,114,101,101,86,105, | |||
| 101,119,32,33,61,32,48,41,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,116,114,101,101,86,105,101,119,45,62,115,101,116,82, | |||
| 111,111,116,73,116,101,109,86,105,115,105,98,108,101,32,40,33,32,116,114,101,101,86,105,101,119,45,62,105,115,82,111,111,116,73,116,101,109,86,105, | |||
| 115,105,98,108,101,40,41,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,101,108,115,101,13,10,32,32,32,32,32,32,32,32,32,32,32, | |||
| 32,32,32,32,32,102,105,108,101,84,114,101,101,67,111,109,112,45,62,115,101,116,82,111,111,116,73,116,101,109,86,105,115,105,98,108,101,32,40,33, | |||
| 32,102,105,108,101,84,114,101,101,67,111,109,112,45,62,105,115,82,111,111,116,73,116,101,109,86,105,115,105,98,108,101,40,41,41,59,13,10,32,32, | |||
| 32,32,32,32,32,32,125,13,10,32,32,32,32,32,32,32,32,101,108,115,101,32,105,102,32,40,114,32,61,61,32,52,41,13,10,32,32,32,32,32, | |||
| 32,32,32,123,13,10,32,32,32,32,32,32,32,32,32,32,32,32,105,102,32,40,116,114,101,101,86,105,101,119,32,33,61,32,48,41,13,10,32,32, | |||
| 32,32,32,32,32,32,32,32,32,32,32,32,32,32,116,114,101,101,86,105,101,119,45,62,115,101,116,79,112,101,110,67,108,111,115,101,66,117,116,116, | |||
| 111,110,115,86,105,115,105,98,108,101,32,40,33,32,116,114,101,101,86,105,101,119,45,62,97,114,101,79,112,101,110,67,108,111,115,101,66,117,116,116, | |||
| 111,110,115,86,105,115,105,98,108,101,40,41,41,59,13,10,32,32,32,32,32,32,32,32,32,32,32,32,101,108,115,101,13,10,32,32,32,32,32,32, | |||
| 32,32,32,32,32,32,32,32,32,32,102,105,108,101,84,114,101,101,67,111,109,112,45,62,115,101,116,79,112,101,110,67,108,111,115,101,66,117,116,116, | |||
| 111,110,115,86,105,115,105,98,108,101,32,40,33,32,102,105,108,101,84,114,101,101,67,111,109,112,45,62,97,114,101,79,112,101,110,67,108,111,115,101, | |||
| 66,117,116,116,111,110,115,86,105,115,105,98,108,101,40,41,41,59,13,10,32,32,32,32,32,32,32,32,125,13,10,32,32,32,32,125,13,10,13,10, | |||
| 32,32,32,32,106,117,99,101,95,85,115,101,68,101,98,117,103,103,105,110,103,78,101,119,79,112,101,114,97,116,111,114,13,10,125,59,13,10,13,10, | |||
| 13,10,47,47,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, | |||
| 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, | |||
| @@ -51,7 +51,7 @@ namespace BinaryData | |||
| const int treedemo_xmlSize = 1126; | |||
| extern const char* treeviewdemo_cpp; | |||
| const int treeviewdemo_cppSize = 7715; | |||
| const int treeviewdemo_cppSize = 8715; | |||
| extern const char* widgetsdemo_cpp; | |||
| const int widgetsdemo_cppSize = 53388; | |||
| @@ -197,12 +197,12 @@ public: | |||
| void resized() | |||
| { | |||
| if (treeView != 0) | |||
| treeView->setBoundsRelative (0.05f, 0.07f, 0.9f, 0.9f); | |||
| treeView->setBoundsInset (BorderSize (40, 10, 10, 10)); | |||
| else if (fileTreeComp != 0) | |||
| fileTreeComp->setBoundsRelative (0.05f, 0.07f, 0.9f, 0.9f); | |||
| fileTreeComp->setBoundsInset (BorderSize (40, 10, 10, 10)); | |||
| typeButton->changeWidthToFitText (20); | |||
| typeButton->setTopLeftPosition (40, 10); | |||
| typeButton->changeWidthToFitText (22); | |||
| typeButton->setTopLeftPosition (10, 10); | |||
| } | |||
| void showCustomTreeView() | |||
| @@ -232,6 +232,13 @@ public: | |||
| PopupMenu m; | |||
| m.addItem (1, T("Custom treeview showing an XML tree")); | |||
| m.addItem (2, T("FileTreeComponent showing the file system")); | |||
| m.addSeparator(); | |||
| m.addItem (3, T("Show root item"), true, | |||
| treeView != 0 ? treeView->isRootItemVisible() | |||
| : fileTreeComp->isRootItemVisible()); | |||
| m.addItem (4, T("Show open/close buttons"), true, | |||
| treeView != 0 ? treeView->areOpenCloseButtonsVisible() | |||
| : fileTreeComp->areOpenCloseButtonsVisible()); | |||
| const int r = m.showAt (typeButton); | |||
| @@ -243,6 +250,20 @@ public: | |||
| { | |||
| showFileTreeComp(); | |||
| } | |||
| else if (r == 3) | |||
| { | |||
| if (treeView != 0) | |||
| treeView->setRootItemVisible (! treeView->isRootItemVisible()); | |||
| else | |||
| fileTreeComp->setRootItemVisible (! fileTreeComp->isRootItemVisible()); | |||
| } | |||
| else if (r == 4) | |||
| { | |||
| if (treeView != 0) | |||
| treeView->setOpenCloseButtonsVisible (! treeView->areOpenCloseButtonsVisible()); | |||
| else | |||
| fileTreeComp->setOpenCloseButtonsVisible (! fileTreeComp->areOpenCloseButtonsVisible()); | |||
| } | |||
| } | |||
| juce_UseDebuggingNewOperator | |||
| @@ -197,12 +197,12 @@ public: | |||
| void resized() | |||
| { | |||
| if (treeView != 0) | |||
| treeView->setBoundsRelative (0.05f, 0.07f, 0.9f, 0.9f); | |||
| treeView->setBoundsInset (BorderSize (40, 10, 10, 10)); | |||
| else if (fileTreeComp != 0) | |||
| fileTreeComp->setBoundsRelative (0.05f, 0.07f, 0.9f, 0.9f); | |||
| fileTreeComp->setBoundsInset (BorderSize (40, 10, 10, 10)); | |||
| typeButton->changeWidthToFitText (20); | |||
| typeButton->setTopLeftPosition (40, 10); | |||
| typeButton->changeWidthToFitText (22); | |||
| typeButton->setTopLeftPosition (10, 10); | |||
| } | |||
| void showCustomTreeView() | |||
| @@ -232,6 +232,13 @@ public: | |||
| PopupMenu m; | |||
| m.addItem (1, T("Custom treeview showing an XML tree")); | |||
| m.addItem (2, T("FileTreeComponent showing the file system")); | |||
| m.addSeparator(); | |||
| m.addItem (3, T("Show root item"), true, | |||
| treeView != 0 ? treeView->isRootItemVisible() | |||
| : fileTreeComp->isRootItemVisible()); | |||
| m.addItem (4, T("Show open/close buttons"), true, | |||
| treeView != 0 ? treeView->areOpenCloseButtonsVisible() | |||
| : fileTreeComp->areOpenCloseButtonsVisible()); | |||
| const int r = m.showAt (typeButton); | |||
| @@ -243,6 +250,20 @@ public: | |||
| { | |||
| showFileTreeComp(); | |||
| } | |||
| else if (r == 3) | |||
| { | |||
| if (treeView != 0) | |||
| treeView->setRootItemVisible (! treeView->isRootItemVisible()); | |||
| else | |||
| fileTreeComp->setRootItemVisible (! fileTreeComp->isRootItemVisible()); | |||
| } | |||
| else if (r == 4) | |||
| { | |||
| if (treeView != 0) | |||
| treeView->setOpenCloseButtonsVisible (! treeView->areOpenCloseButtonsVisible()); | |||
| else | |||
| fileTreeComp->setOpenCloseButtonsVisible (! fileTreeComp->areOpenCloseButtonsVisible()); | |||
| } | |||
| } | |||
| juce_UseDebuggingNewOperator | |||
| @@ -51120,6 +51120,7 @@ class TreeViewContentComponent : public Component | |||
| public: | |||
| TreeViewContentComponent (TreeView* const owner_) | |||
| : owner (owner_), | |||
| buttonUnderMouse (0), | |||
| isDragging (false) | |||
| { | |||
| } | |||
| @@ -51131,14 +51132,29 @@ public: | |||
| void mouseDown (const MouseEvent& e) | |||
| { | |||
| updateButtonUnderMouse (e); | |||
| isDragging = false; | |||
| needSelectionOnMouseUp = false; | |||
| Rectangle pos; | |||
| TreeViewItem* const item = findItemAt (e.y, pos); | |||
| if (item != 0 && e.x >= pos.getX()) | |||
| if (item == 0) | |||
| return; | |||
| // (if the open/close buttons are hidden, we'll treat clicks to the left of the item | |||
| // as selection clicks) | |||
| if (e.x < pos.getX() && owner->openCloseButtonsVisible) | |||
| { | |||
| if (e.x >= pos.getX() - owner->getIndentSize()) | |||
| item->setOpen (! item->isOpen()); | |||
| // (clicks to the left of an open/close button are ignored) | |||
| } | |||
| else | |||
| { | |||
| // mouse-down inside the body of the item.. | |||
| if (! owner->isMultiSelectEnabled()) | |||
| item->setSelected (true, true); | |||
| else if (item->isSelected()) | |||
| @@ -51149,29 +51165,23 @@ public: | |||
| MouseEvent e2 (e); | |||
| e2.x -= pos.getX(); | |||
| e2.y -= pos.getY(); | |||
| item->itemClicked (e2); | |||
| if (e2.x >= 0) | |||
| item->itemClicked (e2); | |||
| } | |||
| } | |||
| void mouseUp (const MouseEvent& e) | |||
| { | |||
| Rectangle pos; | |||
| TreeViewItem* const item = findItemAt (e.y, pos); | |||
| updateButtonUnderMouse (e); | |||
| if (item != 0 && e.mouseWasClicked()) | |||
| if (needSelectionOnMouseUp && e.mouseWasClicked()) | |||
| { | |||
| if (needSelectionOnMouseUp) | |||
| { | |||
| Rectangle pos; | |||
| TreeViewItem* const item = findItemAt (e.y, pos); | |||
| if (item != 0) | |||
| selectBasedOnModifiers (item, e.mods); | |||
| } | |||
| else if (e.mouseWasClicked()) | |||
| { | |||
| if (e.x >= pos.getX() - owner->getIndentSize() | |||
| && e.x < pos.getX()) | |||
| { | |||
| item->setOpen (! item->isOpen()); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -51182,7 +51192,7 @@ public: | |||
| Rectangle pos; | |||
| TreeViewItem* const item = findItemAt (e.y, pos); | |||
| if (item != 0 && e.x >= pos.getX()) | |||
| if (item != 0 && (e.x >= pos.getX() || ! owner->openCloseButtonsVisible)) | |||
| { | |||
| MouseEvent e2 (e); | |||
| e2.x -= pos.getX(); | |||
| @@ -51229,6 +51239,16 @@ public: | |||
| } | |||
| } | |||
| void mouseMove (const MouseEvent& e) | |||
| { | |||
| updateButtonUnderMouse (e); | |||
| } | |||
| void mouseExit (const MouseEvent& e) | |||
| { | |||
| updateButtonUnderMouse (e); | |||
| } | |||
| void paint (Graphics& g); | |||
| TreeViewItem* findItemAt (int y, Rectangle& itemPosition) const; | |||
| @@ -51236,12 +51256,6 @@ public: | |||
| { | |||
| int xAdjust = 0, yAdjust = 0; | |||
| if ((! owner->rootItemVisible) && owner->rootItem != 0) | |||
| { | |||
| yAdjust = owner->rootItem->itemHeight; | |||
| xAdjust = owner->getIndentSize(); | |||
| } | |||
| const int visibleTop = -getY(); | |||
| const int visibleBottom = visibleTop + getParentHeight(); | |||
| @@ -51293,7 +51307,6 @@ public: | |||
| const TreeViewItem* const item = (TreeViewItem*) rowComponentItems.getUnchecked(i); | |||
| Rectangle pos (item->getItemPosition (false)); | |||
| pos.translate (-xAdjust, -yAdjust); | |||
| pos.setSize (pos.getWidth() + xAdjust, item->itemHeight); | |||
| if (pos.getBottom() >= visibleTop && pos.getY() < visibleBottom) | |||
| @@ -51318,6 +51331,47 @@ public: | |||
| } | |||
| } | |||
| void updateButtonUnderMouse (const MouseEvent& e) | |||
| { | |||
| TreeViewItem* newItem = 0; | |||
| if (owner->openCloseButtonsVisible) | |||
| { | |||
| Rectangle pos; | |||
| TreeViewItem* item = findItemAt (e.y, pos); | |||
| if (item != 0 && e.x < pos.getX() && e.x >= pos.getX() - owner->getIndentSize()) | |||
| { | |||
| newItem = item; | |||
| if (! newItem->mightContainSubItems()) | |||
| newItem = 0; | |||
| } | |||
| } | |||
| if (buttonUnderMouse != newItem) | |||
| { | |||
| if (buttonUnderMouse != 0) | |||
| { | |||
| const Rectangle r (buttonUnderMouse->getItemPosition (false)); | |||
| repaint (0, r.getY(), r.getX(), buttonUnderMouse->getItemHeight()); | |||
| } | |||
| buttonUnderMouse = newItem; | |||
| if (buttonUnderMouse != 0) | |||
| { | |||
| const Rectangle r (buttonUnderMouse->getItemPosition (false)); | |||
| repaint (0, r.getY(), r.getX(), buttonUnderMouse->getItemHeight()); | |||
| } | |||
| } | |||
| } | |||
| bool isMouseOverButton (TreeViewItem* item) const throw() | |||
| { | |||
| return item == buttonUnderMouse; | |||
| } | |||
| void resized() | |||
| { | |||
| owner->itemsChanged(); | |||
| @@ -51331,6 +51385,7 @@ private: | |||
| VoidArray rowComponentItems; | |||
| Array <int> rowComponentIds; | |||
| VoidArray rowComponents; | |||
| TreeViewItem* buttonUnderMouse; | |||
| bool isDragging, needSelectionOnMouseUp; | |||
| TreeViewContentComponent (const TreeViewContentComponent&); | |||
| @@ -51401,7 +51456,8 @@ TreeView::TreeView (const String& componentName) | |||
| defaultOpenness (false), | |||
| needsRecalculating (true), | |||
| rootItemVisible (true), | |||
| multiSelectEnabled (false) | |||
| multiSelectEnabled (false), | |||
| openCloseButtonsVisible (true) | |||
| { | |||
| addAndMakeVisible (viewport = new TreeViewport()); | |||
| viewport->setViewedComponent (new TreeViewContentComponent (this)); | |||
| @@ -51490,6 +51546,15 @@ void TreeView::setMultiSelectEnabled (const bool canMultiSelect) | |||
| multiSelectEnabled = canMultiSelect; | |||
| } | |||
| void TreeView::setOpenCloseButtonsVisible (const bool shouldBeVisible) | |||
| { | |||
| if (openCloseButtonsVisible != shouldBeVisible) | |||
| { | |||
| openCloseButtonsVisible = shouldBeVisible; | |||
| itemsChanged(); | |||
| } | |||
| } | |||
| void TreeView::clearSelectedItems() | |||
| { | |||
| if (rootItem != 0) | |||
| @@ -51592,9 +51657,6 @@ void TreeView::scrollToKeepItemVisible (TreeViewItem* item) | |||
| item = item->getDeepestOpenParentItem(); | |||
| int y = item->y; | |||
| if (! rootItemVisible) | |||
| y -= rootItem->itemHeight; | |||
| int viewTop = viewport->getViewPositionY(); | |||
| if (y < viewTop) | |||
| @@ -51706,7 +51768,7 @@ void TreeView::handleAsyncUpdate() | |||
| const ScopedLock sl (nodeAlterationLock); | |||
| if (rootItem != 0) | |||
| rootItem->updatePositions (0); | |||
| rootItem->updatePositions (rootItemVisible ? 0 : -rootItem->itemHeight); | |||
| ((TreeViewport*) viewport)->updateComponents(); | |||
| @@ -51729,17 +51791,10 @@ void TreeViewContentComponent::paint (Graphics& g) | |||
| { | |||
| owner->handleAsyncUpdate(); | |||
| int w = getWidth(); | |||
| if (! owner->rootItemVisible) | |||
| { | |||
| const int indentWidth = owner->getIndentSize(); | |||
| g.setOrigin (0, -owner->rootItem->itemHeight); | |||
| g.setOrigin (-indentWidth, -owner->rootItem->itemHeight); | |||
| w += indentWidth; | |||
| } | |||
| owner->rootItem->paintRecursively (g, w); | |||
| owner->rootItem->paintRecursively (g, getWidth()); | |||
| } | |||
| } | |||
| @@ -51755,14 +51810,8 @@ TreeViewItem* TreeViewContentComponent::findItemAt (int y, Rectangle& itemPositi | |||
| TreeViewItem* const ti = owner->rootItem->findItemRecursively (y); | |||
| if (ti != 0) | |||
| { | |||
| itemPosition = ti->getItemPosition (false); | |||
| if (! owner->rootItemVisible) | |||
| itemPosition.translate (-owner->getIndentSize(), | |||
| -owner->rootItem->itemHeight); | |||
| } | |||
| return ti; | |||
| } | |||
| @@ -51929,6 +51978,12 @@ void TreeViewItem::paintItem (Graphics&, int, int) | |||
| { | |||
| } | |||
| void TreeViewItem::paintOpenCloseButton (Graphics& g, int width, int height, bool isMouseOver) | |||
| { | |||
| ownerView->getLookAndFeel() | |||
| .drawTreeviewPlusMinusBox (g, 0, 0, width, height, ! isOpen(), isMouseOver); | |||
| } | |||
| void TreeViewItem::itemClicked (const MouseEvent&) | |||
| { | |||
| } | |||
| @@ -51972,17 +52027,25 @@ void TreeViewItem::treeHasChanged() const throw() | |||
| ownerView->itemsChanged(); | |||
| } | |||
| void TreeViewItem::repaintItem() const | |||
| { | |||
| if (ownerView != 0) | |||
| { | |||
| const Rectangle r (getItemPosition (false)); | |||
| ownerView->viewport->repaint (0, r.getY(), r.getRight(), r.getHeight()); | |||
| } | |||
| } | |||
| void TreeViewItem::updatePositions (int newY) | |||
| { | |||
| y = newY; | |||
| itemHeight = getItemHeight(); | |||
| totalHeight = itemHeight; | |||
| itemWidth = getItemWidth(); | |||
| totalWidth = jmax (itemWidth, 0); | |||
| totalWidth = jmax (itemWidth, 0) + getIndentX(); | |||
| if (isOpen()) | |||
| { | |||
| const int ourIndent = getIndentX(); | |||
| newY += totalHeight; | |||
| for (int i = 0; i < subItems.size(); ++i) | |||
| @@ -51992,7 +52055,7 @@ void TreeViewItem::updatePositions (int newY) | |||
| ti->updatePositions (newY); | |||
| newY += ti->totalHeight; | |||
| totalHeight += ti->totalHeight; | |||
| totalWidth = jmax (totalWidth, ti->totalWidth + ourIndent); | |||
| totalWidth = jmax (totalWidth, ti->totalWidth); | |||
| } | |||
| } | |||
| } | |||
| @@ -52024,7 +52087,10 @@ void TreeViewItem::setOwnerView (TreeView* const newOwner) throw() | |||
| int TreeViewItem::getIndentX() const throw() | |||
| { | |||
| const int indentWidth = ownerView->getIndentSize(); | |||
| int x = indentWidth; | |||
| int x = ownerView->rootItemVisible ? indentWidth : 0; | |||
| if (! ownerView->openCloseButtonsVisible) | |||
| x -= indentWidth; | |||
| TreeViewItem* p = parentItem; | |||
| @@ -52058,11 +52124,15 @@ void TreeViewItem::paintRecursively (Graphics& g, int width) | |||
| p = p->parentItem; | |||
| } | |||
| if (! ownerView->rootItemVisible) | |||
| --depth; | |||
| const int indentWidth = ownerView->getIndentSize(); | |||
| float x = (depth + 0.5f) * indentWidth; | |||
| if (x > 0) | |||
| if (depth >= 0 && ownerView->openCloseButtonsVisible) | |||
| { | |||
| float x = (depth + 0.5f) * indentWidth; | |||
| if (depth >= 0) | |||
| { | |||
| if (parentItem != 0 && parentItem->drawLinesInside) | |||
| @@ -52091,11 +52161,15 @@ void TreeViewItem::paintRecursively (Graphics& g, int width) | |||
| if (mightContainSubItems()) | |||
| { | |||
| ownerView->getLookAndFeel() | |||
| .drawTreeviewPlusMinusBox (g, | |||
| depth * indentWidth, 0, | |||
| indentWidth, itemHeight, | |||
| ! isOpen()); | |||
| g.saveState(); | |||
| g.setOrigin (depth * indentWidth, 0); | |||
| g.reduceClipRegion (0, 0, indentWidth, itemHeight); | |||
| paintOpenCloseButton (g, indentWidth, itemHeight, | |||
| ((TreeViewContentComponent*) ownerView->viewport->getViewedComponent()) | |||
| ->isMouseOverButton (this)); | |||
| g.restoreState(); | |||
| } | |||
| } | |||
| @@ -60196,7 +60270,7 @@ const Path LookAndFeel::getCrossShape (const float height) | |||
| return p; | |||
| } | |||
| void LookAndFeel::drawTreeviewPlusMinusBox (Graphics& g, int x, int y, int w, int h, bool isPlus) | |||
| void LookAndFeel::drawTreeviewPlusMinusBox (Graphics& g, int x, int y, int w, int h, bool isPlus, bool isMouseOver) | |||
| { | |||
| const int boxSize = ((jmin (16, w, h) << 1) / 3) | 1; | |||
| @@ -42922,6 +42922,13 @@ public: | |||
| */ | |||
| void treeHasChanged() const throw(); | |||
| /** Sends a repaint message to redraw just this item. | |||
| Note that you should only call this if you want to repaint a superficial change. If | |||
| you're altering the tree's nodes, you should instead call treeHasChanged(). | |||
| */ | |||
| void repaintItem() const; | |||
| /** Returns the row number of this item in the tree. | |||
| The row number of an item will change according to which items are open. | |||
| @@ -43044,6 +43051,14 @@ public: | |||
| */ | |||
| virtual void paintItem (Graphics& g, int width, int height); | |||
| /** Draws the item's open/close button. | |||
| If you don't implement this method, the default behaviour is to | |||
| call LookAndFeel::drawTreeviewPlusMinusBox(), but you can override | |||
| it for custom effects. | |||
| */ | |||
| virtual void paintOpenCloseButton (Graphics& g, int width, int height, bool isMouseOver); | |||
| /** Called when the user clicks on this item. | |||
| If you're using createItemComponent() to create a custom component for the | |||
| @@ -43221,6 +43236,18 @@ public: | |||
| */ | |||
| bool isMultiSelectEnabled() const throw() { return multiSelectEnabled; } | |||
| /** Sets a flag to indicate whether to hide the open/close buttons. | |||
| @see areOpenCloseButtonsVisible | |||
| */ | |||
| void setOpenCloseButtonsVisible (const bool shouldBeVisible); | |||
| /** Returns whether open/close buttons are shown. | |||
| @see setOpenCloseButtonsVisible | |||
| */ | |||
| bool areOpenCloseButtonsVisible() const throw() { return openCloseButtonsVisible; } | |||
| /** Deselects any items that are currently selected. */ | |||
| void clearSelectedItems(); | |||
| @@ -43332,10 +43359,12 @@ private: | |||
| bool needsRecalculating : 1; | |||
| bool rootItemVisible : 1; | |||
| bool multiSelectEnabled : 1; | |||
| bool openCloseButtonsVisible : 1; | |||
| void itemsChanged() throw(); | |||
| void handleAsyncUpdate(); | |||
| void moveSelectedRow (int delta); | |||
| void updateButtonUnderMouse (const MouseEvent& e); | |||
| TreeView (const TreeView&); | |||
| const TreeView& operator= (const TreeView&); | |||
| @@ -46969,6 +46998,14 @@ public: | |||
| */ | |||
| int getCurrentTabIndex() const throw() { return currentTabIndex; } | |||
| /** Returns the button for a specific tab. | |||
| The button that is returned may be deleted later by this component, so don't hang | |||
| on to the pointer that is returned. A null pointer may be returned if the index is | |||
| out of range. | |||
| */ | |||
| TabBarButton* getTabButton (const int index) const; | |||
| /** Callback method to indicate the selected tab has been changed. | |||
| @see setCurrentTabIndex | |||
| @@ -47041,8 +47078,6 @@ private: | |||
| Component* behindFrontTab; | |||
| Button* extraTabsButton; | |||
| TabBarButton* getTabButton (const int index) const; | |||
| TabbedButtonBar (const TabbedButtonBar&); | |||
| const TabbedButtonBar& operator= (const TabbedButtonBar&); | |||
| }; | |||
| @@ -51763,6 +51798,12 @@ public: | |||
| */ | |||
| int getLowestVisibleKey() const throw() { return firstKey; } | |||
| /** Returns the length of the black notes. | |||
| This will be their vertical or horizontal length, depending on the keyboard's orientation. | |||
| */ | |||
| int getBlackNoteLength() const throw() { return blackNoteLength; } | |||
| /** If set to true, then scroll buttons will appear at either end of the keyboard | |||
| if there are too many notes to fit them all in the component at once. | |||
| */ | |||
| @@ -53040,7 +53081,7 @@ public: | |||
| virtual const Path getCrossShape (const float height); | |||
| /** Draws the + or - box in a treeview. */ | |||
| virtual void drawTreeviewPlusMinusBox (Graphics& g, int x, int y, int w, int h, bool isPlus); | |||
| virtual void drawTreeviewPlusMinusBox (Graphics& g, int x, int y, int w, int h, bool isPlus, bool isMouseOver); | |||
| virtual void fillTextEditorBackground (Graphics& g, int width, int height, TextEditor& textEditor); | |||
| virtual void drawTextEditorOutline (Graphics& g, int width, int height, TextEditor& textEditor); | |||
| @@ -53356,13 +53397,11 @@ protected: | |||
| // xxx the following methods are only here to cause a compiler error, because they've been | |||
| // deprecated or their parameters have changed. Hopefully these definitions should cause an | |||
| // error if you try to build a subclass with the old versions. | |||
| virtual int drawTickBox (Graphics&, int, int, int, int, bool, const bool, const bool, const bool) { return 0; } | |||
| virtual int drawProgressBar (Graphics&, int, int, int, int, float) { return 0; } | |||
| virtual int drawProgressBar (Graphics&, ProgressBar&, int, int, int, int, float) { return 0; } | |||
| virtual void getTabButtonBestWidth (int, const String&, int) {} | |||
| virtual int drawTreeviewPlusMinusBox (Graphics&, int, int, int, int, bool) { return 0; } | |||
| private: | |||
| friend void JUCE_PUBLIC_FUNCTION shutdownJuce_GUI(); | |||
| @@ -46,6 +46,7 @@ class TreeViewContentComponent : public Component | |||
| public: | |||
| TreeViewContentComponent (TreeView* const owner_) | |||
| : owner (owner_), | |||
| buttonUnderMouse (0), | |||
| isDragging (false) | |||
| { | |||
| } | |||
| @@ -57,14 +58,29 @@ public: | |||
| void mouseDown (const MouseEvent& e) | |||
| { | |||
| updateButtonUnderMouse (e); | |||
| isDragging = false; | |||
| needSelectionOnMouseUp = false; | |||
| Rectangle pos; | |||
| TreeViewItem* const item = findItemAt (e.y, pos); | |||
| if (item != 0 && e.x >= pos.getX()) | |||
| if (item == 0) | |||
| return; | |||
| // (if the open/close buttons are hidden, we'll treat clicks to the left of the item | |||
| // as selection clicks) | |||
| if (e.x < pos.getX() && owner->openCloseButtonsVisible) | |||
| { | |||
| if (e.x >= pos.getX() - owner->getIndentSize()) | |||
| item->setOpen (! item->isOpen()); | |||
| // (clicks to the left of an open/close button are ignored) | |||
| } | |||
| else | |||
| { | |||
| // mouse-down inside the body of the item.. | |||
| if (! owner->isMultiSelectEnabled()) | |||
| item->setSelected (true, true); | |||
| else if (item->isSelected()) | |||
| @@ -75,29 +91,23 @@ public: | |||
| MouseEvent e2 (e); | |||
| e2.x -= pos.getX(); | |||
| e2.y -= pos.getY(); | |||
| item->itemClicked (e2); | |||
| if (e2.x >= 0) | |||
| item->itemClicked (e2); | |||
| } | |||
| } | |||
| void mouseUp (const MouseEvent& e) | |||
| { | |||
| Rectangle pos; | |||
| TreeViewItem* const item = findItemAt (e.y, pos); | |||
| updateButtonUnderMouse (e); | |||
| if (item != 0 && e.mouseWasClicked()) | |||
| if (needSelectionOnMouseUp && e.mouseWasClicked()) | |||
| { | |||
| if (needSelectionOnMouseUp) | |||
| { | |||
| Rectangle pos; | |||
| TreeViewItem* const item = findItemAt (e.y, pos); | |||
| if (item != 0) | |||
| selectBasedOnModifiers (item, e.mods); | |||
| } | |||
| else if (e.mouseWasClicked()) | |||
| { | |||
| if (e.x >= pos.getX() - owner->getIndentSize() | |||
| && e.x < pos.getX()) | |||
| { | |||
| item->setOpen (! item->isOpen()); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -108,7 +118,7 @@ public: | |||
| Rectangle pos; | |||
| TreeViewItem* const item = findItemAt (e.y, pos); | |||
| if (item != 0 && e.x >= pos.getX()) | |||
| if (item != 0 && (e.x >= pos.getX() || ! owner->openCloseButtonsVisible)) | |||
| { | |||
| MouseEvent e2 (e); | |||
| e2.x -= pos.getX(); | |||
| @@ -155,6 +165,16 @@ public: | |||
| } | |||
| } | |||
| void mouseMove (const MouseEvent& e) | |||
| { | |||
| updateButtonUnderMouse (e); | |||
| } | |||
| void mouseExit (const MouseEvent& e) | |||
| { | |||
| updateButtonUnderMouse (e); | |||
| } | |||
| void paint (Graphics& g); | |||
| TreeViewItem* findItemAt (int y, Rectangle& itemPosition) const; | |||
| @@ -162,12 +182,6 @@ public: | |||
| { | |||
| int xAdjust = 0, yAdjust = 0; | |||
| if ((! owner->rootItemVisible) && owner->rootItem != 0) | |||
| { | |||
| yAdjust = owner->rootItem->itemHeight; | |||
| xAdjust = owner->getIndentSize(); | |||
| } | |||
| const int visibleTop = -getY(); | |||
| const int visibleBottom = visibleTop + getParentHeight(); | |||
| @@ -219,7 +233,6 @@ public: | |||
| const TreeViewItem* const item = (TreeViewItem*) rowComponentItems.getUnchecked(i); | |||
| Rectangle pos (item->getItemPosition (false)); | |||
| pos.translate (-xAdjust, -yAdjust); | |||
| pos.setSize (pos.getWidth() + xAdjust, item->itemHeight); | |||
| if (pos.getBottom() >= visibleTop && pos.getY() < visibleBottom) | |||
| @@ -244,6 +257,47 @@ public: | |||
| } | |||
| } | |||
| void updateButtonUnderMouse (const MouseEvent& e) | |||
| { | |||
| TreeViewItem* newItem = 0; | |||
| if (owner->openCloseButtonsVisible) | |||
| { | |||
| Rectangle pos; | |||
| TreeViewItem* item = findItemAt (e.y, pos); | |||
| if (item != 0 && e.x < pos.getX() && e.x >= pos.getX() - owner->getIndentSize()) | |||
| { | |||
| newItem = item; | |||
| if (! newItem->mightContainSubItems()) | |||
| newItem = 0; | |||
| } | |||
| } | |||
| if (buttonUnderMouse != newItem) | |||
| { | |||
| if (buttonUnderMouse != 0) | |||
| { | |||
| const Rectangle r (buttonUnderMouse->getItemPosition (false)); | |||
| repaint (0, r.getY(), r.getX(), buttonUnderMouse->getItemHeight()); | |||
| } | |||
| buttonUnderMouse = newItem; | |||
| if (buttonUnderMouse != 0) | |||
| { | |||
| const Rectangle r (buttonUnderMouse->getItemPosition (false)); | |||
| repaint (0, r.getY(), r.getX(), buttonUnderMouse->getItemHeight()); | |||
| } | |||
| } | |||
| } | |||
| bool isMouseOverButton (TreeViewItem* item) const throw() | |||
| { | |||
| return item == buttonUnderMouse; | |||
| } | |||
| void resized() | |||
| { | |||
| owner->itemsChanged(); | |||
| @@ -258,6 +312,7 @@ private: | |||
| VoidArray rowComponentItems; | |||
| Array <int> rowComponentIds; | |||
| VoidArray rowComponents; | |||
| TreeViewItem* buttonUnderMouse; | |||
| bool isDragging, needSelectionOnMouseUp; | |||
| TreeViewContentComponent (const TreeViewContentComponent&); | |||
| @@ -332,7 +387,8 @@ TreeView::TreeView (const String& componentName) | |||
| defaultOpenness (false), | |||
| needsRecalculating (true), | |||
| rootItemVisible (true), | |||
| multiSelectEnabled (false) | |||
| multiSelectEnabled (false), | |||
| openCloseButtonsVisible (true) | |||
| { | |||
| addAndMakeVisible (viewport = new TreeViewport()); | |||
| viewport->setViewedComponent (new TreeViewContentComponent (this)); | |||
| @@ -421,6 +477,15 @@ void TreeView::setMultiSelectEnabled (const bool canMultiSelect) | |||
| multiSelectEnabled = canMultiSelect; | |||
| } | |||
| void TreeView::setOpenCloseButtonsVisible (const bool shouldBeVisible) | |||
| { | |||
| if (openCloseButtonsVisible != shouldBeVisible) | |||
| { | |||
| openCloseButtonsVisible = shouldBeVisible; | |||
| itemsChanged(); | |||
| } | |||
| } | |||
| //============================================================================== | |||
| void TreeView::clearSelectedItems() | |||
| { | |||
| @@ -526,9 +591,6 @@ void TreeView::scrollToKeepItemVisible (TreeViewItem* item) | |||
| item = item->getDeepestOpenParentItem(); | |||
| int y = item->y; | |||
| if (! rootItemVisible) | |||
| y -= rootItem->itemHeight; | |||
| int viewTop = viewport->getViewPositionY(); | |||
| if (y < viewTop) | |||
| @@ -640,7 +702,7 @@ void TreeView::handleAsyncUpdate() | |||
| const ScopedLock sl (nodeAlterationLock); | |||
| if (rootItem != 0) | |||
| rootItem->updatePositions (0); | |||
| rootItem->updatePositions (rootItemVisible ? 0 : -rootItem->itemHeight); | |||
| ((TreeViewport*) viewport)->updateComponents(); | |||
| @@ -665,17 +727,10 @@ void TreeViewContentComponent::paint (Graphics& g) | |||
| { | |||
| owner->handleAsyncUpdate(); | |||
| int w = getWidth(); | |||
| if (! owner->rootItemVisible) | |||
| { | |||
| const int indentWidth = owner->getIndentSize(); | |||
| g.setOrigin (0, -owner->rootItem->itemHeight); | |||
| g.setOrigin (-indentWidth, -owner->rootItem->itemHeight); | |||
| w += indentWidth; | |||
| } | |||
| owner->rootItem->paintRecursively (g, w); | |||
| owner->rootItem->paintRecursively (g, getWidth()); | |||
| } | |||
| } | |||
| @@ -691,14 +746,8 @@ TreeViewItem* TreeViewContentComponent::findItemAt (int y, Rectangle& itemPositi | |||
| TreeViewItem* const ti = owner->rootItem->findItemRecursively (y); | |||
| if (ti != 0) | |||
| { | |||
| itemPosition = ti->getItemPosition (false); | |||
| if (! owner->rootItemVisible) | |||
| itemPosition.translate (-owner->getIndentSize(), | |||
| -owner->rootItem->itemHeight); | |||
| } | |||
| return ti; | |||
| } | |||
| @@ -866,6 +915,12 @@ void TreeViewItem::paintItem (Graphics&, int, int) | |||
| { | |||
| } | |||
| void TreeViewItem::paintOpenCloseButton (Graphics& g, int width, int height, bool isMouseOver) | |||
| { | |||
| ownerView->getLookAndFeel() | |||
| .drawTreeviewPlusMinusBox (g, 0, 0, width, height, ! isOpen(), isMouseOver); | |||
| } | |||
| void TreeViewItem::itemClicked (const MouseEvent&) | |||
| { | |||
| } | |||
| @@ -909,17 +964,25 @@ void TreeViewItem::treeHasChanged() const throw() | |||
| ownerView->itemsChanged(); | |||
| } | |||
| void TreeViewItem::repaintItem() const | |||
| { | |||
| if (ownerView != 0) | |||
| { | |||
| const Rectangle r (getItemPosition (false)); | |||
| ownerView->viewport->repaint (0, r.getY(), r.getRight(), r.getHeight()); | |||
| } | |||
| } | |||
| void TreeViewItem::updatePositions (int newY) | |||
| { | |||
| y = newY; | |||
| itemHeight = getItemHeight(); | |||
| totalHeight = itemHeight; | |||
| itemWidth = getItemWidth(); | |||
| totalWidth = jmax (itemWidth, 0); | |||
| totalWidth = jmax (itemWidth, 0) + getIndentX(); | |||
| if (isOpen()) | |||
| { | |||
| const int ourIndent = getIndentX(); | |||
| newY += totalHeight; | |||
| for (int i = 0; i < subItems.size(); ++i) | |||
| @@ -929,7 +992,7 @@ void TreeViewItem::updatePositions (int newY) | |||
| ti->updatePositions (newY); | |||
| newY += ti->totalHeight; | |||
| totalHeight += ti->totalHeight; | |||
| totalWidth = jmax (totalWidth, ti->totalWidth + ourIndent); | |||
| totalWidth = jmax (totalWidth, ti->totalWidth); | |||
| } | |||
| } | |||
| } | |||
| @@ -961,7 +1024,10 @@ void TreeViewItem::setOwnerView (TreeView* const newOwner) throw() | |||
| int TreeViewItem::getIndentX() const throw() | |||
| { | |||
| const int indentWidth = ownerView->getIndentSize(); | |||
| int x = indentWidth; | |||
| int x = ownerView->rootItemVisible ? indentWidth : 0; | |||
| if (! ownerView->openCloseButtonsVisible) | |||
| x -= indentWidth; | |||
| TreeViewItem* p = parentItem; | |||
| @@ -995,11 +1061,15 @@ void TreeViewItem::paintRecursively (Graphics& g, int width) | |||
| p = p->parentItem; | |||
| } | |||
| if (! ownerView->rootItemVisible) | |||
| --depth; | |||
| const int indentWidth = ownerView->getIndentSize(); | |||
| float x = (depth + 0.5f) * indentWidth; | |||
| if (x > 0) | |||
| if (depth >= 0 && ownerView->openCloseButtonsVisible) | |||
| { | |||
| float x = (depth + 0.5f) * indentWidth; | |||
| if (depth >= 0) | |||
| { | |||
| if (parentItem != 0 && parentItem->drawLinesInside) | |||
| @@ -1029,11 +1099,15 @@ void TreeViewItem::paintRecursively (Graphics& g, int width) | |||
| if (mightContainSubItems()) | |||
| { | |||
| ownerView->getLookAndFeel() | |||
| .drawTreeviewPlusMinusBox (g, | |||
| depth * indentWidth, 0, | |||
| indentWidth, itemHeight, | |||
| ! isOpen()); | |||
| g.saveState(); | |||
| g.setOrigin (depth * indentWidth, 0); | |||
| g.reduceClipRegion (0, 0, indentWidth, itemHeight); | |||
| paintOpenCloseButton (g, indentWidth, itemHeight, | |||
| ((TreeViewContentComponent*) ownerView->viewport->getViewedComponent()) | |||
| ->isMouseOverButton (this)); | |||
| g.restoreState(); | |||
| } | |||
| } | |||
| @@ -151,6 +151,13 @@ public: | |||
| */ | |||
| void treeHasChanged() const throw(); | |||
| /** Sends a repaint message to redraw just this item. | |||
| Note that you should only call this if you want to repaint a superficial change. If | |||
| you're altering the tree's nodes, you should instead call treeHasChanged(). | |||
| */ | |||
| void repaintItem() const; | |||
| /** Returns the row number of this item in the tree. | |||
| The row number of an item will change according to which items are open. | |||
| @@ -275,6 +282,14 @@ public: | |||
| */ | |||
| virtual void paintItem (Graphics& g, int width, int height); | |||
| /** Draws the item's open/close button. | |||
| If you don't implement this method, the default behaviour is to | |||
| call LookAndFeel::drawTreeviewPlusMinusBox(), but you can override | |||
| it for custom effects. | |||
| */ | |||
| virtual void paintOpenCloseButton (Graphics& g, int width, int height, bool isMouseOver); | |||
| /** Called when the user clicks on this item. | |||
| If you're using createItemComponent() to create a custom component for the | |||
| @@ -456,6 +471,18 @@ public: | |||
| */ | |||
| bool isMultiSelectEnabled() const throw() { return multiSelectEnabled; } | |||
| /** Sets a flag to indicate whether to hide the open/close buttons. | |||
| @see areOpenCloseButtonsVisible | |||
| */ | |||
| void setOpenCloseButtonsVisible (const bool shouldBeVisible); | |||
| /** Returns whether open/close buttons are shown. | |||
| @see setOpenCloseButtonsVisible | |||
| */ | |||
| bool areOpenCloseButtonsVisible() const throw() { return openCloseButtonsVisible; } | |||
| //============================================================================== | |||
| /** Deselects any items that are currently selected. */ | |||
| void clearSelectedItems(); | |||
| @@ -572,10 +599,12 @@ private: | |||
| bool needsRecalculating : 1; | |||
| bool rootItemVisible : 1; | |||
| bool multiSelectEnabled : 1; | |||
| bool openCloseButtonsVisible : 1; | |||
| void itemsChanged() throw(); | |||
| void handleAsyncUpdate(); | |||
| void moveSelectedRow (int delta); | |||
| void updateButtonUnderMouse (const MouseEvent& e); | |||
| TreeView (const TreeView&); | |||
| const TreeView& operator= (const TreeView&); | |||
| @@ -211,6 +211,14 @@ public: | |||
| */ | |||
| int getCurrentTabIndex() const throw() { return currentTabIndex; } | |||
| /** Returns the button for a specific tab. | |||
| The button that is returned may be deleted later by this component, so don't hang | |||
| on to the pointer that is returned. A null pointer may be returned if the index is | |||
| out of range. | |||
| */ | |||
| TabBarButton* getTabButton (const int index) const; | |||
| //============================================================================== | |||
| /** Callback method to indicate the selected tab has been changed. | |||
| @@ -252,8 +260,8 @@ public: | |||
| tabTextColourId = 0x1005813, /**< The colour to use to draw the tab names. If this isn't specified, | |||
| the look and feel will choose an appropriate colour. */ | |||
| frontOutlineColourId = 0x1005814, /**< The colour to use to draw an outline around the currently-selected tab. */ | |||
| frontTextColourId = 0x1005815, /**< The colour to use to draw the currently-selected tab name. If | |||
| this isn't specified, the look and feel will choose an appropriate | |||
| frontTextColourId = 0x1005815, /**< The colour to use to draw the currently-selected tab name. If | |||
| this isn't specified, the look and feel will choose an appropriate | |||
| colour. */ | |||
| }; | |||
| @@ -286,8 +294,6 @@ private: | |||
| Component* behindFrontTab; | |||
| Button* extraTabsButton; | |||
| TabBarButton* getTabButton (const int index) const; | |||
| TabbedButtonBar (const TabbedButtonBar&); | |||
| const TabbedButtonBar& operator= (const TabbedButtonBar&); | |||
| }; | |||
| @@ -90,7 +90,7 @@ public: | |||
| /** Specifies the thickness of an outline that should be drawn around the content component. | |||
| If this thickness is > 0, a line will be drawn around the three sides of the content | |||
| If this thickness is > 0, a line will be drawn around the three sides of the content | |||
| component which don't touch the tab-bar, and the content component will be inset by this amount. | |||
| To set the colour of the line, use setColour (outlineColourId, ...). | |||
| @@ -207,7 +207,7 @@ public: | |||
| enum ColourIds | |||
| { | |||
| backgroundColourId = 0x1005800, /**< The colour to fill the background behind the tabs. */ | |||
| outlineColourId = 0x1005801, /**< The colour to use to draw an outline around the content. | |||
| outlineColourId = 0x1005801, /**< The colour to use to draw an outline around the content. | |||
| (See setOutline) */ | |||
| }; | |||
| @@ -187,7 +187,7 @@ LookAndFeel::LookAndFeel() | |||
| TabbedComponent::backgroundColourId, 0x00000000, | |||
| TabbedComponent::outlineColourId, 0xff777777, | |||
| TabbedButtonBar::tabOutlineColourId, 0x80000000, | |||
| TabbedButtonBar::frontOutlineColourId, 0x90000000, | |||
| TabbedButtonBar::frontOutlineColourId, 0x90000000, | |||
| Toolbar::backgroundColourId, 0xfff6f8f9, | |||
| Toolbar::separatorColourId, 0x4c000000, | |||
| @@ -836,7 +836,7 @@ const Path LookAndFeel::getCrossShape (const float height) | |||
| } | |||
| //============================================================================== | |||
| void LookAndFeel::drawTreeviewPlusMinusBox (Graphics& g, int x, int y, int w, int h, bool isPlus) | |||
| void LookAndFeel::drawTreeviewPlusMinusBox (Graphics& g, int x, int y, int w, int h, bool isPlus, bool isMouseOver) | |||
| { | |||
| const int boxSize = ((jmin (16, w, h) << 1) / 3) | 1; | |||
| @@ -126,7 +126,7 @@ public: | |||
| */ | |||
| void setColour (const int colourId, const Colour& colour) throw(); | |||
| /** Returns true if the specified colour ID has been explicitly set using the | |||
| /** Returns true if the specified colour ID has been explicitly set using the | |||
| setColour() method. | |||
| */ | |||
| bool isColourSpecified (const int colourId) const throw(); | |||
| @@ -266,7 +266,7 @@ public: | |||
| //============================================================================== | |||
| /** Draws the + or - box in a treeview. */ | |||
| virtual void drawTreeviewPlusMinusBox (Graphics& g, int x, int y, int w, int h, bool isPlus); | |||
| virtual void drawTreeviewPlusMinusBox (Graphics& g, int x, int y, int w, int h, bool isPlus, bool isMouseOver); | |||
| //============================================================================== | |||
| virtual void fillTextEditorBackground (Graphics& g, int width, int height, TextEditor& textEditor); | |||
| @@ -606,13 +606,11 @@ protected: | |||
| // xxx the following methods are only here to cause a compiler error, because they've been | |||
| // deprecated or their parameters have changed. Hopefully these definitions should cause an | |||
| // error if you try to build a subclass with the old versions. | |||
| virtual int drawTickBox (Graphics&, int, int, int, int, bool, const bool, const bool, const bool) { return 0; } | |||
| virtual int drawProgressBar (Graphics&, int, int, int, int, float) { return 0; } | |||
| virtual int drawProgressBar (Graphics&, ProgressBar&, int, int, int, int, float) { return 0; } | |||
| virtual void getTabButtonBestWidth (int, const String&, int) {} | |||
| virtual int drawTreeviewPlusMinusBox (Graphics&, int, int, int, int, bool) { return 0; } | |||
| private: | |||
| friend void JUCE_PUBLIC_FUNCTION shutdownJuce_GUI(); | |||
| @@ -185,6 +185,12 @@ public: | |||
| */ | |||
| int getLowestVisibleKey() const throw() { return firstKey; } | |||
| /** Returns the length of the black notes. | |||
| This will be their vertical or horizontal length, depending on the keyboard's orientation. | |||
| */ | |||
| int getBlackNoteLength() const throw() { return blackNoteLength; } | |||
| /** If set to true, then scroll buttons will appear at either end of the keyboard | |||
| if there are too many notes to fit them all in the component at once. | |||
| */ | |||
| @@ -132,9 +132,9 @@ public: | |||
| e.g. "Arial", "Courier", etc. | |||
| Note that this may also be one of the values: Typeface::defaultTypefaceNameSans, | |||
| Typeface::defaultTypefaceNameSerif, or Typeface::defaultTypefaceNameMono, which are not actual | |||
| platform-specific font names, but are generic names that are used to represent the various | |||
| Note that this may also be one of the values: Typeface::defaultTypefaceNameSans, | |||
| Typeface::defaultTypefaceNameSerif, or Typeface::defaultTypefaceNameMono, which are not actual | |||
| platform-specific font names, but are generic names that are used to represent the various | |||
| default fonts. If you need to know the exact typeface name being used, you can call | |||
| Font::getTypeface()->getTypefaceName(), which will give you the platform-specific name. | |||
| */ | |||
| @@ -266,7 +266,7 @@ public: | |||
| Note that this is NOT the platform-specific typeface name (e.g. "Times"), but | |||
| is a generic string that represents whatever that font is, such as "DefaultSans". | |||
| If you try to create a typeface with this name, the global default LookAndFeel | |||
| If you try to create a typeface with this name, the global default LookAndFeel | |||
| object will be asked to provide an appropriate typeface. | |||
| */ | |||
| static const tchar* defaultTypefaceNameSans; | |||
| @@ -276,7 +276,7 @@ public: | |||
| Note that this is NOT the platform-specific typeface name (e.g. "Times"), but | |||
| is a generic string that represents it, such as "DefaultSans". | |||
| If you try to create a typeface with this name, the global default LookAndFeel | |||
| If you try to create a typeface with this name, the global default LookAndFeel | |||
| object will be asked to provide an appropriate typeface. | |||
| */ | |||
| static const tchar* defaultTypefaceNameSerif; | |||
| @@ -286,7 +286,7 @@ public: | |||
| Note that this is NOT the platform-specific typeface name (e.g. "Times"), but | |||
| is a generic string that represents it, such as "DefaultSans". | |||
| If you try to create a typeface with this name, the global default LookAndFeel | |||
| If you try to create a typeface with this name, the global default LookAndFeel | |||
| object will be asked to provide an appropriate typeface. | |||
| */ | |||
| static const tchar* defaultTypefaceNameMono; | |||