| @@ -378,9 +378,9 @@ CodeGenerator::CustomCodeList::~CustomCodeList() | |||
| void CodeGenerator::CustomCodeList::reloadFrom (const String& fileContent) | |||
| { | |||
| sectionNames.clear(); | |||
| sectionContent.clear(); | |||
| StringArray newNames; | |||
| ReferenceCountedArray<CodeDocumentRef> newContent; | |||
| StringArray lines; | |||
| lines.addLines (fileContent); | |||
| @@ -400,22 +400,28 @@ void CodeGenerator::CustomCodeList::reloadFrom (const String& fileContent) | |||
| if (endLine > i) | |||
| { | |||
| String content (lines.joinIntoString (newLine, i + 1, endLine - i - 1)); | |||
| newNames.add (tag); | |||
| sectionNames.add (tag); | |||
| CodeDocumentRef::Ptr doc (new CodeDocumentRef (new CodeDocument())); | |||
| sectionContent.add (doc); | |||
| doc->getDocument().replaceAllContent (content); | |||
| doc->getDocument().clearUndoHistory(); | |||
| doc->getDocument().setSavePoint(); | |||
| CodeDocumentRef::Ptr doc (getDocumentFor (tag, false)); | |||
| if (doc == 0) | |||
| { | |||
| CodeDocument* const codeDoc = new CodeDocument(); | |||
| doc = new CodeDocumentRef (codeDoc); | |||
| codeDoc->replaceAllContent (content); | |||
| codeDoc->clearUndoHistory(); | |||
| codeDoc->setSavePoint(); | |||
| } | |||
| newContent.add (doc); | |||
| i = endLine; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| sectionNames = newNames; | |||
| sectionContent = newContent; | |||
| sendSynchronousChangeMessage (this); | |||
| } | |||
| @@ -90,14 +90,13 @@ public: | |||
| class CodeDocumentRef : public ReferenceCountedObject | |||
| { | |||
| public: | |||
| CodeDocumentRef (CodeDocument* doc_) : doc (doc_) {} | |||
| CodeDocument& getDocument() const throw() { return *doc; } | |||
| CodeDocumentRef (CodeDocument* doc_) : doc (doc_) {} | |||
| CodeDocument& getDocument() const throw() { return *doc; } | |||
| typedef ReferenceCountedObjectPtr<CodeDocumentRef> Ptr; | |||
| private: | |||
| CodeDocument* doc; | |||
| CodeDocument* const doc; | |||
| }; | |||
| //============================================================================== | |||
| @@ -122,6 +122,20 @@ bool ComponentDocument::isComponentFile (const File& file) | |||
| const String ComponentDocument::getCppTemplate() const { return String (BinaryData::jucer_ComponentTemplate_cpp); } | |||
| const String ComponentDocument::getHeaderTemplate() const { return String (BinaryData::jucer_ComponentTemplate_h); } | |||
| const String ComponentDocument::getCppContent() | |||
| { | |||
| MemoryOutputStream cpp, header; | |||
| writeCode (cpp, header); | |||
| return cpp.toUTF8(); | |||
| } | |||
| const String ComponentDocument::getHeaderContent() | |||
| { | |||
| MemoryOutputStream cpp, header; | |||
| writeCode (cpp, header); | |||
| return header.toUTF8(); | |||
| } | |||
| void ComponentDocument::writeCode (OutputStream& cpp, OutputStream& header) | |||
| { | |||
| CodeGenerator codeGen; | |||
| @@ -142,6 +142,9 @@ public: | |||
| const String getCppTemplate() const; | |||
| const String getHeaderTemplate() const; | |||
| const String getCppContent(); | |||
| const String getHeaderContent(); | |||
| //============================================================================== | |||
| ValueTree& getRoot() { return root; } | |||
| ValueTree getComponentGroup() const; | |||
| @@ -530,15 +530,20 @@ private: | |||
| }; | |||
| //============================================================================== | |||
| class ComponentEditor::CodeEditorHolder : public Component | |||
| class ComponentEditor::CodeEditorHolder : public Component, | |||
| public ButtonListener | |||
| { | |||
| public: | |||
| CodeEditorHolder (ComponentEditor& editor_) | |||
| : editor (editor_) | |||
| : editor (editor_), switchFileButton (String::empty), showingHeader (true) | |||
| { | |||
| addAndMakeVisible (viewport = new Viewport()); | |||
| viewport->setScrollBarsShown (true, false); | |||
| viewport->setViewedComponent (new ContentHolder (editor)); | |||
| addAndMakeVisible (&viewport); | |||
| viewport.setScrollBarsShown (true, false); | |||
| addAndMakeVisible (&switchFileButton); | |||
| buttonClicked (0); | |||
| switchFileButton.addButtonListener (this); | |||
| } | |||
| ~CodeEditorHolder() | |||
| @@ -547,26 +552,36 @@ public: | |||
| void resized() | |||
| { | |||
| viewport->setBounds (getLocalBounds()); | |||
| viewport.setBounds (getLocalBounds()); | |||
| int visWidth = viewport.getMaximumVisibleWidth(); | |||
| dynamic_cast <ContentHolder*> (viewport.getViewedComponent())->updateSize (visWidth); | |||
| int visWidth = viewport->getMaximumVisibleWidth(); | |||
| dynamic_cast <ContentHolder*> (viewport->getViewedComponent())->updateSize (visWidth); | |||
| if (viewport.getMaximumVisibleWidth() != visWidth) | |||
| dynamic_cast <ContentHolder*> (viewport.getViewedComponent())->updateSize (viewport.getMaximumVisibleWidth()); | |||
| if (viewport->getMaximumVisibleWidth() != visWidth) | |||
| dynamic_cast <ContentHolder*> (viewport->getViewedComponent())->updateSize (viewport->getMaximumVisibleWidth()); | |||
| switchFileButton.setBounds (getWidth() - 150, 4, 120, 20); | |||
| } | |||
| void buttonClicked (Button*) | |||
| { | |||
| showingHeader = ! showingHeader; | |||
| viewport.setViewedComponent (new ContentHolder (editor.getDocument(), showingHeader)); | |||
| resized(); | |||
| switchFileButton.setButtonText (showingHeader ? "Show CPP file" : "Show header file"); | |||
| } | |||
| private: | |||
| ComponentEditor& editor; | |||
| enum { updateCommandId = 0x23427fa1 }; | |||
| //============================================================================== | |||
| class EditorHolder : public Component, | |||
| public CodeDocument::Listener | |||
| { | |||
| public: | |||
| EditorHolder (const CodeGenerator::CustomCodeList::CodeDocumentRef::Ptr doc, | |||
| const String& name, const String& textBefore, const String& textAfter) | |||
| : Component (name), document (doc), cppTokeniser(), codeEditor (doc->getDocument(), &cppTokeniser) | |||
| const String& textBefore, const String& textAfter) | |||
| : document (doc), cppTokeniser(), codeEditor (doc->getDocument(), &cppTokeniser) | |||
| { | |||
| linesBefore.addLines (textBefore); | |||
| linesAfter.addLines (textAfter); | |||
| @@ -603,7 +618,7 @@ private: | |||
| codeEditor.setBounds (0, fontHeight * linesBefore.size() + 1, | |||
| width, 2 + codeEditor.getScrollbarThickness() | |||
| + fontHeight * jmax (1, document->getDocument().getNumLines())); | |||
| + fontHeight * jlimit (1, 50, document->getDocument().getNumLines())); | |||
| setSize (width, (linesBefore.size() + linesAfter.size()) * fontHeight + codeEditor.getHeight()); | |||
| } | |||
| @@ -616,27 +631,29 @@ private: | |||
| getParentComponent()->handleCommandMessage (updateCommandId); | |||
| } | |||
| private: | |||
| const CodeGenerator::CustomCodeList::CodeDocumentRef::Ptr document; | |||
| CPlusPlusCodeTokeniser cppTokeniser; | |||
| CodeEditorComponent codeEditor; | |||
| StringArray linesBefore, linesAfter; | |||
| }; | |||
| //============================================================================== | |||
| class ContentHolder : public Component, | |||
| public ChangeListener | |||
| { | |||
| public: | |||
| ContentHolder (ComponentEditor& editor_) | |||
| : editor (editor_) | |||
| ContentHolder (ComponentDocument& document_, bool isHeader_) | |||
| : document (document_), isHeader (isHeader_) | |||
| { | |||
| setOpaque (true); | |||
| editor.getDocument().getCustomCodeList().addChangeListener (this); | |||
| document.getCustomCodeList().addChangeListener (this); | |||
| changeListenerCallback (0); | |||
| } | |||
| ~ContentHolder() | |||
| { | |||
| editor.getDocument().getCustomCodeList().removeChangeListener (this); | |||
| document.getCustomCodeList().removeChangeListener (this); | |||
| } | |||
| void paint (Graphics& g) | |||
| @@ -647,12 +664,12 @@ private: | |||
| void updateSize (int width) | |||
| { | |||
| int y = 2; | |||
| for (int i = 0; i < editors.size(); ++i) | |||
| { | |||
| editors.getUnchecked(i)->updateSize (width - 8); | |||
| editors.getUnchecked(i)->setTopLeftPosition (4, y + 1); | |||
| y = editors.getUnchecked(i)->getBottom() + 1; | |||
| EditorHolder* const ed = editors.getUnchecked(i); | |||
| ed->updateSize (width - 8); | |||
| ed->setTopLeftPosition (4, y + 1); | |||
| y = ed->getBottom() + 1; | |||
| } | |||
| setSize (width, y + 2); | |||
| @@ -662,12 +679,13 @@ private: | |||
| { | |||
| editors.clear(); | |||
| CodeGenerator::CustomCodeList::Iterator iter (editor.getDocument().getCppTemplate(), | |||
| editor.getDocument().getCustomCodeList()); | |||
| CodeGenerator::CustomCodeList::Iterator iter (isHeader ? document.getHeaderContent() | |||
| : document.getCppContent(), | |||
| document.getCustomCodeList()); | |||
| while (iter.next()) | |||
| { | |||
| EditorHolder* ed = new EditorHolder (iter.codeDocument, iter.sectionName, iter.textBefore, iter.textAfter); | |||
| EditorHolder* ed = new EditorHolder (iter.codeDocument, iter.textBefore, iter.textAfter); | |||
| editors.add (ed); | |||
| addAndMakeVisible (ed); | |||
| } | |||
| @@ -683,11 +701,16 @@ private: | |||
| Component::handleCommandMessage (commandId); | |||
| } | |||
| private: | |||
| OwnedArray <EditorHolder> editors; | |||
| ComponentEditor& editor; | |||
| ComponentDocument& document; | |||
| bool isHeader; | |||
| }; | |||
| Viewport* viewport; | |||
| ComponentEditor& editor; | |||
| Viewport viewport; | |||
| TextButton switchFileButton; | |||
| bool showingHeader; | |||
| }; | |||
| //============================================================================== | |||
| @@ -485,6 +485,14 @@ public: | |||
| canvas.continueDrag (e); | |||
| showSizeGuides(); | |||
| } | |||
| Viewport* viewport = Component::findParentComponentOfClass ((Viewport*) 0); | |||
| if (viewport != 0) | |||
| { | |||
| MouseEvent e2 (e.getEventRelativeTo (viewport)); | |||
| viewport->autoScroll (e2.x, e2.y, 8, 16); | |||
| } | |||
| } | |||
| void mouseUp (const MouseEvent& e) | |||
| @@ -524,10 +532,10 @@ public: | |||
| } | |||
| } | |||
| void findLassoItemsInArea (Array <SelectedItems::ItemType>& itemsFound, int x, int y, int width, int height) | |||
| void findLassoItemsInArea (Array <SelectedItems::ItemType>& itemsFound, const Rectangle<int>& area) | |||
| { | |||
| canvas.getComponentHolder()->findLassoItemsInArea (itemsFound, Rectangle<int> (x, y, width, height) | |||
| + relativePositionToOtherComponent (canvas.getComponentHolder(), Point<int>())); | |||
| canvas.getComponentHolder() | |||
| ->findLassoItemsInArea (itemsFound, area + relativePositionToOtherComponent (canvas.getComponentHolder(), Point<int>())); | |||
| } | |||
| SelectedItems& getLassoSelection() { return canvas.getSelection(); } | |||
| @@ -770,7 +778,7 @@ ComponentEditorCanvas::~ComponentEditorCanvas() | |||
| { | |||
| dragger = 0; | |||
| getDocument().getRoot().removeListener (this); | |||
| componentHolder->deleteAllChildren(); | |||
| //deleteAndZero (componentHolder); | |||
| deleteAllChildren(); | |||
| } | |||
| @@ -1006,6 +1014,7 @@ ComponentEditorCanvas::ComponentHolder::ComponentHolder() | |||
| ComponentEditorCanvas::ComponentHolder::~ComponentHolder() | |||
| { | |||
| deleteAllChildren(); | |||
| } | |||
| void ComponentEditorCanvas::ComponentHolder::updateComponents (ComponentDocument& doc, SelectedItems& selection) | |||
| @@ -1055,7 +1064,6 @@ Component* ComponentEditorCanvas::ComponentHolder::getComponentForState (Compone | |||
| for (int i = getNumChildComponents(); --i >= 0;) | |||
| { | |||
| Component* const c = getChildComponent (i); | |||
| if (doc.isStateForComponent (state, c)) | |||
| return c; | |||
| } | |||
| @@ -1068,7 +1076,6 @@ Component* ComponentEditorCanvas::ComponentHolder::findComponentWithID (const St | |||
| for (int i = getNumChildComponents(); --i >= 0;) | |||
| { | |||
| Component* const c = getChildComponent(i); | |||
| if (ComponentDocument::getJucerIDFor (c) == uid) | |||
| return c; | |||
| } | |||
| @@ -191,14 +191,14 @@ void DrawableEditor::Canvas::mouseUp (const MouseEvent& e) | |||
| } | |||
| } | |||
| void DrawableEditor::Canvas::findLassoItemsInArea (Array <int64>& itemsFound, int x, int y, int width, int height) | |||
| void DrawableEditor::Canvas::findLassoItemsInArea (Array <int64>& itemsFound, const Rectangle<int>& area) | |||
| { | |||
| for (int i = getNumChildComponents(); --i >= 0;) | |||
| { | |||
| DrawableObjectComponent* d = dynamic_cast <DrawableObjectComponent*> (getChildComponent(i)); | |||
| if (d != 0) | |||
| d->findLassoItemsInArea (itemsFound, Rectangle<int> (x, y, width, height)); | |||
| d->findLassoItemsInArea (itemsFound, area); | |||
| } | |||
| } | |||
| @@ -67,7 +67,7 @@ public: | |||
| void childBoundsChanged (Component* child); | |||
| void updateSize(); | |||
| void findLassoItemsInArea (Array <int64>& itemsFound, int x, int y, int width, int height); | |||
| void findLassoItemsInArea (Array <int64>& itemsFound, const Rectangle<int>& area); | |||
| SelectedItemSet <int64>& getLassoSelection(); | |||
| private: | |||
| @@ -73,6 +73,9 @@ void JuceDemoPluginAudioProcessorEditor::resized() | |||
| midiKeyboard->setBounds (4, getHeight() - keyboardHeight - 4, getWidth() - 8, keyboardHeight); | |||
| resizer->setBounds (getWidth() - 16, getHeight() - 16, 16, 16); | |||
| getProcessor()->lastUIWidth = getWidth(); | |||
| getProcessor()->lastUIHeight = getHeight(); | |||
| } | |||
| //============================================================================== | |||
| @@ -402,10 +402,9 @@ ComponentOverlayComponent* ComponentLayoutEditor::getOverlayCompFor (Component* | |||
| return 0; | |||
| } | |||
| void ComponentLayoutEditor::findLassoItemsInArea (Array <Component*>& results, | |||
| int x, int y, int w, int h) | |||
| void ComponentLayoutEditor::findLassoItemsInArea (Array <Component*>& results, const Rectangle<int>& area) | |||
| { | |||
| const Rectangle<int> lasso (x - subCompHolder->getX(), y - subCompHolder->getY(), w, h); | |||
| const Rectangle<int> lasso (area - subCompHolder->getPosition()); | |||
| for (int i = 0; i < subCompHolder->getNumChildComponents(); ++i) | |||
| { | |||
| @@ -60,8 +60,7 @@ public: | |||
| ComponentLayout& getLayout() const throw() { return layout; } | |||
| void findLassoItemsInArea (Array <Component*>& results, | |||
| int x, int y, int w, int h); | |||
| void findLassoItemsInArea (Array <Component*>& results, const Rectangle<int>& area); | |||
| SelectedItemSet <Component*>& getLassoSelection(); | |||
| @@ -260,11 +260,8 @@ void PaintRoutineEditor::mouseUp (const MouseEvent& e) | |||
| } | |||
| } | |||
| void PaintRoutineEditor::findLassoItemsInArea (Array <PaintElement*>& results, | |||
| int x, int y, int w, int h) | |||
| void PaintRoutineEditor::findLassoItemsInArea (Array <PaintElement*>& results, const Rectangle<int>& lasso) | |||
| { | |||
| const Rectangle<int> lasso (x, y, w, h); | |||
| for (int i = 0; i < getNumChildComponents(); ++i) | |||
| { | |||
| PaintElement* const e = dynamic_cast <PaintElement*> (getChildComponent (i)); | |||
| @@ -58,8 +58,7 @@ public: | |||
| void mouseUp (const MouseEvent& e); | |||
| void visibilityChanged(); | |||
| void findLassoItemsInArea (Array <PaintElement*>& results, | |||
| int x, int y, int w, int h); | |||
| void findLassoItemsInArea (Array <PaintElement*>& results, const Rectangle<int>& area); | |||
| SelectedItemSet <PaintElement*>& getLassoSelection(); | |||
| @@ -34316,7 +34316,7 @@ XmlElement* AudioProcessor::getXmlFromBinary (const void* data, | |||
| const int sizeInBytes) | |||
| { | |||
| if (sizeInBytes > 8 | |||
| && ByteOrder::littleEndianInt ((const char*) data) == magicXmlNumber) | |||
| && ByteOrder::littleEndianInt (data) == magicXmlNumber) | |||
| { | |||
| const int stringLength = (int) ByteOrder::littleEndianInt (((const char*) data) + 4); | |||
| @@ -54338,7 +54338,7 @@ class TreeViewContentComponent : public Component, | |||
| public TooltipClient | |||
| { | |||
| public: | |||
| TreeViewContentComponent (TreeView* const owner_) | |||
| TreeViewContentComponent (TreeView& owner_) | |||
| : owner (owner_), | |||
| buttonUnderMouse (0), | |||
| isDragging (false) | |||
| @@ -54365,9 +54365,9 @@ public: | |||
| // (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.openCloseButtonsVisible) | |||
| { | |||
| if (e.x >= pos.getX() - owner->getIndentSize()) | |||
| if (e.x >= pos.getX() - owner.getIndentSize()) | |||
| item->setOpen (! item->isOpen()); | |||
| // (clicks to the left of an open/close button are ignored) | |||
| @@ -54375,7 +54375,7 @@ public: | |||
| else | |||
| { | |||
| // mouse-down inside the body of the item.. | |||
| if (! owner->isMultiSelectEnabled()) | |||
| if (! owner.isMultiSelectEnabled()) | |||
| item->setSelected (true, true); | |||
| else if (item->isSelected()) | |||
| needSelectionOnMouseUp = ! e.mods.isPopupMenu(); | |||
| @@ -54408,7 +54408,7 @@ public: | |||
| Rectangle<int> pos; | |||
| TreeViewItem* const item = findItemAt (e.y, pos); | |||
| if (item != 0 && (e.x >= pos.getX() || ! owner->openCloseButtonsVisible)) | |||
| if (item != 0 && (e.x >= pos.getX() || ! owner.openCloseButtonsVisible)) | |||
| item->itemDoubleClicked (e.withNewPosition (e.getPosition() - pos.getPosition())); | |||
| } | |||
| } | |||
| @@ -54441,7 +54441,7 @@ public: | |||
| dragImage->multiplyAllAlphas (0.6f); | |||
| Point<int> imageOffset (pos.getX() - e.x, pos.getY() - e.y); | |||
| dragContainer->startDragging (dragDescription, owner, dragImage, true, &imageOffset); | |||
| dragContainer->startDragging (dragDescription, &owner, dragImage, true, &imageOffset); | |||
| } | |||
| else | |||
| { | |||
| @@ -54464,25 +54464,37 @@ public: | |||
| updateButtonUnderMouse (e); | |||
| } | |||
| void paint (Graphics& g); | |||
| TreeViewItem* findItemAt (int y, Rectangle<int>& itemPosition) const; | |||
| void paint (Graphics& g) | |||
| { | |||
| if (owner.rootItem != 0) | |||
| { | |||
| owner.handleAsyncUpdate(); | |||
| static bool isMouseDraggingInChildCompOf (Component* const comp) | |||
| if (! owner.rootItemVisible) | |||
| g.setOrigin (0, -owner.rootItem->itemHeight); | |||
| owner.rootItem->paintRecursively (g, getWidth()); | |||
| } | |||
| } | |||
| TreeViewItem* findItemAt (int y, Rectangle<int>& itemPosition) const | |||
| { | |||
| for (int i = Desktop::getInstance().getNumMouseSources(); --i >= 0;) | |||
| if (owner.rootItem != 0) | |||
| { | |||
| MouseInputSource* source = Desktop::getInstance().getMouseSource(i); | |||
| owner.handleAsyncUpdate(); | |||
| if (source->isDragging()) | |||
| { | |||
| Component* const underMouse = source->getComponentUnderMouse(); | |||
| if (! owner.rootItemVisible) | |||
| y += owner.rootItem->itemHeight; | |||
| if (underMouse != 0 && (comp == underMouse || comp->isParentOf (underMouse))) | |||
| return true; | |||
| } | |||
| TreeViewItem* const ti = owner.rootItem->findItemRecursively (y); | |||
| if (ti != 0) | |||
| itemPosition = ti->getItemPosition (false); | |||
| return ti; | |||
| } | |||
| return false; | |||
| return 0; | |||
| } | |||
| void updateComponents() | |||
| @@ -54491,8 +54503,8 @@ public: | |||
| const int visibleBottom = visibleTop + getParentHeight(); | |||
| BigInteger itemsToKeep; | |||
| TreeViewItem* item = owner->rootItem; | |||
| int y = (item != 0 && !owner->rootItemVisible) ? -item->itemHeight : 0; | |||
| TreeViewItem* item = owner.rootItem; | |||
| int y = (item != 0 && ! owner.rootItemVisible) ? -item->itemHeight : 0; | |||
| while (item != 0 && y < visibleBottom) | |||
| { | |||
| @@ -54566,12 +54578,12 @@ public: | |||
| { | |||
| TreeViewItem* newItem = 0; | |||
| if (owner->openCloseButtonsVisible) | |||
| if (owner.openCloseButtonsVisible) | |||
| { | |||
| Rectangle<int> pos; | |||
| TreeViewItem* item = findItemAt (e.y, pos); | |||
| if (item != 0 && e.x < pos.getX() && e.x >= pos.getX() - owner->getIndentSize()) | |||
| if (item != 0 && e.x < pos.getX() && e.x >= pos.getX() - owner.getIndentSize()) | |||
| { | |||
| newItem = item; | |||
| @@ -54598,14 +54610,14 @@ public: | |||
| } | |||
| } | |||
| bool isMouseOverButton (TreeViewItem* item) const throw() | |||
| bool isMouseOverButton (TreeViewItem* const item) const throw() | |||
| { | |||
| return item == buttonUnderMouse; | |||
| } | |||
| void resized() | |||
| { | |||
| owner->itemsChanged(); | |||
| owner.itemsChanged(); | |||
| } | |||
| const String getTooltip() | |||
| @@ -54616,30 +54628,26 @@ public: | |||
| if (item != 0) | |||
| return item->getTooltip(); | |||
| return owner->getTooltip(); | |||
| return owner.getTooltip(); | |||
| } | |||
| juce_UseDebuggingNewOperator | |||
| private: | |||
| TreeView* const owner; | |||
| TreeView& owner; | |||
| Array <TreeViewItem*> rowComponentItems; | |||
| Array <int> rowComponentIds; | |||
| Array <Component*> rowComponents; | |||
| TreeViewItem* buttonUnderMouse; | |||
| bool isDragging, needSelectionOnMouseUp; | |||
| TreeViewContentComponent (const TreeViewContentComponent&); | |||
| TreeViewContentComponent& operator= (const TreeViewContentComponent&); | |||
| void selectBasedOnModifiers (TreeViewItem* const item, const ModifierKeys& modifiers) | |||
| { | |||
| TreeViewItem* firstSelected = 0; | |||
| if (modifiers.isShiftDown() && ((firstSelected = owner->getSelectedItem (0)) != 0)) | |||
| if (modifiers.isShiftDown() && ((firstSelected = owner.getSelectedItem (0)) != 0)) | |||
| { | |||
| TreeViewItem* const lastSelected = owner->getSelectedItem (owner->getNumSelectedItems() - 1); | |||
| TreeViewItem* const lastSelected = owner.getSelectedItem (owner.getNumSelectedItems() - 1); | |||
| jassert (lastSelected != 0); | |||
| int rowStart = firstSelected->getRowNumberInTree(); | |||
| @@ -54654,13 +54662,12 @@ private: | |||
| swapVariables (ourRow, otherEnd); | |||
| for (int i = ourRow; i <= otherEnd; ++i) | |||
| owner->getItemOnRow (i)->setSelected (true, false); | |||
| owner.getItemOnRow (i)->setSelected (true, false); | |||
| } | |||
| else | |||
| { | |||
| const bool cmd = modifiers.isCommandDown(); | |||
| item->setSelected ((! cmd) || (! item->isSelected()), ! cmd); | |||
| const bool cmd = modifiers.isCommandDown(); | |||
| item->setSelected ((! cmd) || ! item->isSelected(), ! cmd); | |||
| } | |||
| } | |||
| @@ -54672,31 +54679,61 @@ private: | |||
| return false; | |||
| } | |||
| static bool isMouseDraggingInChildCompOf (Component* const comp) | |||
| { | |||
| for (int i = Desktop::getInstance().getNumMouseSources(); --i >= 0;) | |||
| { | |||
| MouseInputSource* const source = Desktop::getInstance().getMouseSource(i); | |||
| if (source->isDragging()) | |||
| { | |||
| Component* const underMouse = source->getComponentUnderMouse(); | |||
| if (underMouse != 0 && (comp == underMouse || comp->isParentOf (underMouse))) | |||
| return true; | |||
| } | |||
| } | |||
| return false; | |||
| } | |||
| TreeViewContentComponent (const TreeViewContentComponent&); | |||
| TreeViewContentComponent& operator= (const TreeViewContentComponent&); | |||
| }; | |||
| class TreeView::TreeViewport : public Viewport | |||
| { | |||
| public: | |||
| TreeViewport() throw() {} | |||
| ~TreeViewport() throw() {} | |||
| TreeViewport() throw() : lastX (-1) {} | |||
| ~TreeViewport() throw() {} | |||
| void updateComponents() | |||
| void updateComponents (const bool triggerResize = false) | |||
| { | |||
| TreeViewContentComponent* const tvc = static_cast <TreeViewContentComponent*> (getViewedComponent()); | |||
| if (tvc != 0) | |||
| tvc->updateComponents(); | |||
| { | |||
| if (triggerResize) | |||
| tvc->resized(); | |||
| else | |||
| tvc->updateComponents(); | |||
| } | |||
| repaint(); | |||
| } | |||
| void visibleAreaChanged (int, int, int, int) | |||
| void visibleAreaChanged (int x, int, int, int) | |||
| { | |||
| updateComponents(); | |||
| const bool hasScrolledSideways = (x != lastX); | |||
| lastX = x; | |||
| updateComponents (hasScrolledSideways); | |||
| } | |||
| juce_UseDebuggingNewOperator | |||
| private: | |||
| int lastX; | |||
| TreeViewport (const TreeViewport&); | |||
| TreeViewport& operator= (const TreeViewport&); | |||
| }; | |||
| @@ -54714,7 +54751,7 @@ TreeView::TreeView (const String& componentName) | |||
| openCloseButtonsVisible (true) | |||
| { | |||
| addAndMakeVisible (viewport = new TreeViewport()); | |||
| viewport->setViewedComponent (new TreeViewContentComponent (this)); | |||
| viewport->setViewedComponent (new TreeViewContentComponent (*this)); | |||
| viewport->setWantsKeyboardFocus (false); | |||
| setWantsKeyboardFocus (true); | |||
| } | |||
| @@ -55340,39 +55377,6 @@ void TreeView::itemDropped (const String& sourceDescription, Component* sourceCo | |||
| handleDrop (StringArray(), sourceDescription, sourceComponent, x, y); | |||
| } | |||
| void TreeViewContentComponent::paint (Graphics& g) | |||
| { | |||
| if (owner->rootItem != 0) | |||
| { | |||
| owner->handleAsyncUpdate(); | |||
| if (! owner->rootItemVisible) | |||
| g.setOrigin (0, -owner->rootItem->itemHeight); | |||
| owner->rootItem->paintRecursively (g, getWidth()); | |||
| } | |||
| } | |||
| TreeViewItem* TreeViewContentComponent::findItemAt (int y, Rectangle<int>& itemPosition) const | |||
| { | |||
| if (owner->rootItem != 0) | |||
| { | |||
| owner->handleAsyncUpdate(); | |||
| if (! owner->rootItemVisible) | |||
| y += owner->rootItem->itemHeight; | |||
| TreeViewItem* const ti = owner->rootItem->findItemRecursively (y); | |||
| if (ti != 0) | |||
| itemPosition = ti->getItemPosition (false); | |||
| return ti; | |||
| } | |||
| return 0; | |||
| } | |||
| enum TreeViewOpenness | |||
| { | |||
| opennessDefault = 0, | |||
| @@ -55593,7 +55597,6 @@ void TreeViewItem::itemDropped (const String& /*sourceDescription*/, Component* | |||
| const Rectangle<int> TreeViewItem::getItemPosition (const bool relativeToTreeViewTopLeft) const throw() | |||
| { | |||
| const int indentX = getIndentX(); | |||
| int width = itemWidth; | |||
| if (ownerView != 0 && width < 0) | |||
| @@ -55602,8 +55605,7 @@ const Rectangle<int> TreeViewItem::getItemPosition (const bool relativeToTreeVie | |||
| Rectangle<int> r (indentX, y, jmax (0, width), totalHeight); | |||
| if (relativeToTreeViewTopLeft) | |||
| r.setPosition (r.getX() - ownerView->viewport->getViewPositionX(), | |||
| r.getY() - ownerView->viewport->getViewPositionY()); | |||
| r -= ownerView->viewport->getViewPosition(); | |||
| return r; | |||
| } | |||
| @@ -56536,6 +56538,11 @@ const File FileBrowserComponent::getHighlightedFile() const throw() | |||
| return fileListComponent->getSelectedFile (0); | |||
| } | |||
| void FileBrowserComponent::deselectAllFiles() | |||
| { | |||
| fileListComponent->deselectAllFiles(); | |||
| } | |||
| bool FileBrowserComponent::isFileSuitable (const File& file) const | |||
| { | |||
| return (flags & canSelectFiles) != 0 ? (fileFilter == 0 || fileFilter->isFileSuitable (file)) | |||
| @@ -57215,6 +57222,11 @@ const File FileListComponent::getSelectedFile (int index) const | |||
| return fileList.getFile (getSelectedRow (index)); | |||
| } | |||
| void FileListComponent::deselectAllFiles() | |||
| { | |||
| deselectAllRows(); | |||
| } | |||
| void FileListComponent::scrollToTop() | |||
| { | |||
| getVerticalScrollBar()->setCurrentRangeStart (0); | |||
| @@ -58097,10 +58109,13 @@ const File FileTreeComponent::getSelectedFile (const int index) const | |||
| { | |||
| const FileListTreeItem* const item = dynamic_cast <const FileListTreeItem*> (getSelectedItem (index)); | |||
| if (item != 0) | |||
| return item->file; | |||
| return item != 0 ? item->file | |||
| : File::nonexistent; | |||
| } | |||
| return File::nonexistent; | |||
| void FileTreeComponent::deselectAllFiles() | |||
| { | |||
| clearSelectedItems(); | |||
| } | |||
| void FileTreeComponent::scrollToTop() | |||
| @@ -62786,10 +62801,6 @@ BEGIN_JUCE_NAMESPACE | |||
| Viewport::Viewport (const String& componentName) | |||
| : Component (componentName), | |||
| contentComp (0), | |||
| lastVX (0), | |||
| lastVY (0), | |||
| lastVW (0), | |||
| lastVH (0), | |||
| scrollBarThickness (0), | |||
| singleStepX (16), | |||
| singleStepY (16), | |||
| @@ -62855,16 +62866,14 @@ int Viewport::getMaximumVisibleHeight() const throw() | |||
| return jmax (0, getHeight() - (horizontalScrollBar->isVisible() ? getScrollBarThickness() : 0)); | |||
| } | |||
| void Viewport::setViewPosition (const int xPixelsOffset, | |||
| const int yPixelsOffset) | |||
| void Viewport::setViewPosition (const int xPixelsOffset, const int yPixelsOffset) | |||
| { | |||
| if (contentComp != 0) | |||
| contentComp->setTopLeftPosition (-xPixelsOffset, | |||
| -yPixelsOffset); | |||
| } | |||
| void Viewport::setViewPositionProportionately (const double x, | |||
| const double y) | |||
| void Viewport::setViewPositionProportionately (const double x, const double y) | |||
| { | |||
| if (contentComp != 0) | |||
| setViewPosition (jmax (0, roundToInt (x * (contentComp->getWidth() - getWidth()))), | |||
| @@ -62877,25 +62886,31 @@ bool Viewport::autoScroll (int mouseX, int mouseY, int activeBorderThickness, in | |||
| { | |||
| int dx = 0, dy = 0; | |||
| if (mouseX < activeBorderThickness) | |||
| dx = activeBorderThickness - mouseX; | |||
| else if (mouseX >= contentHolder->getWidth() - activeBorderThickness) | |||
| dx = (contentHolder->getWidth() - activeBorderThickness) - mouseX; | |||
| if (horizontalScrollBar->isVisible()) | |||
| { | |||
| if (mouseX < activeBorderThickness) | |||
| dx = activeBorderThickness - mouseX; | |||
| else if (mouseX >= contentHolder->getWidth() - activeBorderThickness) | |||
| dx = (contentHolder->getWidth() - activeBorderThickness) - mouseX; | |||
| if (dx < 0) | |||
| dx = jmax (dx, -maximumSpeed, contentHolder->getWidth() - contentComp->getRight()); | |||
| else | |||
| dx = jmin (dx, maximumSpeed, -contentComp->getX()); | |||
| if (dx < 0) | |||
| dx = jmax (dx, -maximumSpeed, contentHolder->getWidth() - contentComp->getRight()); | |||
| else | |||
| dx = jmin (dx, maximumSpeed, -contentComp->getX()); | |||
| } | |||
| if (mouseY < activeBorderThickness) | |||
| dy = activeBorderThickness - mouseY; | |||
| else if (mouseY >= contentHolder->getHeight() - activeBorderThickness) | |||
| dy = (contentHolder->getHeight() - activeBorderThickness) - mouseY; | |||
| if (verticalScrollBar->isVisible()) | |||
| { | |||
| if (mouseY < activeBorderThickness) | |||
| dy = activeBorderThickness - mouseY; | |||
| else if (mouseY >= contentHolder->getHeight() - activeBorderThickness) | |||
| dy = (contentHolder->getHeight() - activeBorderThickness) - mouseY; | |||
| if (dy < 0) | |||
| dy = jmax (dy, -maximumSpeed, contentHolder->getHeight() - contentComp->getBottom()); | |||
| else | |||
| dy = jmin (dy, maximumSpeed, -contentComp->getY()); | |||
| if (dy < 0) | |||
| dy = jmax (dy, -maximumSpeed, contentHolder->getHeight() - contentComp->getBottom()); | |||
| else | |||
| dy = jmin (dy, maximumSpeed, -contentComp->getY()); | |||
| } | |||
| if (dx != 0 || dy != 0) | |||
| { | |||
| @@ -62923,10 +62938,10 @@ void Viewport::updateVisibleRegion() | |||
| { | |||
| if (contentComp != 0) | |||
| { | |||
| const int newVX = -contentComp->getX(); | |||
| const int newVY = -contentComp->getY(); | |||
| Rectangle<int> newViewPos; | |||
| newViewPos.setPosition (-contentComp->getPosition()); | |||
| if (newVX == 0 && newVY == 0 | |||
| if (newViewPos.getX() == 0 && newViewPos.getY() == 0 | |||
| && contentComp->getWidth() <= getWidth() | |||
| && contentComp->getHeight() <= getHeight()) | |||
| { | |||
| @@ -62935,14 +62950,14 @@ void Viewport::updateVisibleRegion() | |||
| } | |||
| horizontalScrollBar->setRangeLimits (0.0, contentComp->getWidth()); | |||
| horizontalScrollBar->setCurrentRange (newVX, getMaximumVisibleWidth()); | |||
| horizontalScrollBar->setCurrentRange (newViewPos.getX(), getMaximumVisibleWidth()); | |||
| horizontalScrollBar->setSingleStepSize (singleStepX); | |||
| if (! (contentComp->getWidth() > 0 && showHScrollbar && getHeight() > getScrollBarThickness())) | |||
| horizontalScrollBar->setVisible (! horizontalScrollBar->autoHides()); | |||
| verticalScrollBar->setRangeLimits (0.0, contentComp->getHeight()); | |||
| verticalScrollBar->setCurrentRange (newVY, getMaximumVisibleHeight()); | |||
| verticalScrollBar->setCurrentRange (newViewPos.getY(), getMaximumVisibleHeight()); | |||
| verticalScrollBar->setSingleStepSize (singleStepY); | |||
| if (! (contentComp->getHeight() > 0 && showVScrollbar && getWidth() > getScrollBarThickness())) | |||
| @@ -62950,8 +62965,8 @@ void Viewport::updateVisibleRegion() | |||
| if (verticalScrollBar->isVisible()) | |||
| { | |||
| horizontalScrollBar->setCurrentRange (newVX, getMaximumVisibleWidth()); | |||
| verticalScrollBar->setCurrentRange (newVY, getMaximumVisibleHeight()); | |||
| horizontalScrollBar->setCurrentRange (newViewPos.getX(), getMaximumVisibleWidth()); | |||
| verticalScrollBar->setCurrentRange (newViewPos.getY(), getMaximumVisibleHeight()); | |||
| verticalScrollBar | |||
| ->setBounds (getMaximumVisibleWidth(), 0, | |||
| @@ -62960,7 +62975,7 @@ void Viewport::updateVisibleRegion() | |||
| if (horizontalScrollBar->isVisible()) | |||
| { | |||
| horizontalScrollBar->setCurrentRange (newVX, getMaximumVisibleWidth()); | |||
| horizontalScrollBar->setCurrentRange (newViewPos.getX(), getMaximumVisibleWidth()); | |||
| horizontalScrollBar | |||
| ->setBounds (0, getMaximumVisibleHeight(), | |||
| @@ -62970,20 +62985,13 @@ void Viewport::updateVisibleRegion() | |||
| contentHolder->setSize (getMaximumVisibleWidth(), | |||
| getMaximumVisibleHeight()); | |||
| const int newVW = jmin (contentComp->getRight(), getMaximumVisibleWidth()); | |||
| const int newVH = jmin (contentComp->getBottom(), getMaximumVisibleHeight()); | |||
| newViewPos.setSize (jmin (contentComp->getRight(), getMaximumVisibleWidth()), | |||
| jmin (contentComp->getBottom(), getMaximumVisibleHeight())); | |||
| if (newVX != lastVX | |||
| || newVY != lastVY | |||
| || newVW != lastVW | |||
| || newVH != lastVH) | |||
| if (lastViewPos != newViewPos) | |||
| { | |||
| lastVX = newVX; | |||
| lastVY = newVY; | |||
| lastVW = newVW; | |||
| lastVH = newVH; | |||
| visibleAreaChanged (newVX, newVY, newVW, newVH); | |||
| lastViewPos = newViewPos; | |||
| visibleAreaChanged (newViewPos.getX(), newViewPos.getY(), newViewPos.getWidth(), newViewPos.getHeight()); | |||
| } | |||
| horizontalScrollBar->handleUpdateNowIfNeeded(); | |||
| @@ -62996,8 +63004,7 @@ void Viewport::updateVisibleRegion() | |||
| } | |||
| } | |||
| void Viewport::setSingleStepSizes (const int stepX, | |||
| const int stepY) | |||
| void Viewport::setSingleStepSizes (const int stepX, const int stepY) | |||
| { | |||
| singleStepX = stepX; | |||
| singleStepY = stepY; | |||
| @@ -247175,27 +247182,32 @@ public: | |||
| { | |||
| const KeyPress& kp = keyPresses.getReference(0); | |||
| juce_wchar key = kp.getTextCharacter(); | |||
| if (kp.getKeyCode() == KeyPress::backspaceKey) | |||
| key = NSBackspaceCharacter; | |||
| else if (kp.getKeyCode() == KeyPress::deleteKey) | |||
| key = NSDeleteCharacter; | |||
| else if (key == 0) | |||
| key = (juce_wchar) kp.getKeyCode(); | |||
| unsigned int mods = 0; | |||
| if (kp.getModifiers().isShiftDown()) | |||
| mods |= NSShiftKeyMask; | |||
| if (kp.getModifiers().isCtrlDown()) | |||
| mods |= NSControlKeyMask; | |||
| if (kp.getModifiers().isAltDown()) | |||
| mods |= NSAlternateKeyMask; | |||
| if (kp.getModifiers().isCommandDown()) | |||
| mods |= NSCommandKeyMask; | |||
| [item setKeyEquivalent: juceStringToNS (String::charToString (key))]; | |||
| [item setKeyEquivalentModifierMask: mods]; | |||
| if (kp.getKeyCode() != KeyPress::backspaceKey | |||
| && kp.getKeyCode() != KeyPress::deleteKey) // (adding these is annoying because it flashes the menu bar | |||
| // every time you press the key while editing text) | |||
| { | |||
| juce_wchar key = kp.getTextCharacter(); | |||
| if (kp.getKeyCode() == KeyPress::backspaceKey) | |||
| key = NSBackspaceCharacter; | |||
| else if (kp.getKeyCode() == KeyPress::deleteKey) | |||
| key = NSDeleteCharacter; | |||
| else if (key == 0) | |||
| key = (juce_wchar) kp.getKeyCode(); | |||
| unsigned int mods = 0; | |||
| if (kp.getModifiers().isShiftDown()) | |||
| mods |= NSShiftKeyMask; | |||
| if (kp.getModifiers().isCtrlDown()) | |||
| mods |= NSControlKeyMask; | |||
| if (kp.getModifiers().isAltDown()) | |||
| mods |= NSAlternateKeyMask; | |||
| if (kp.getModifiers().isCommandDown()) | |||
| mods |= NSCommandKeyMask; | |||
| [item setKeyEquivalent: juceStringToNS (String::charToString (key))]; | |||
| [item setKeyEquivalentModifierMask: mods]; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -5035,7 +5035,7 @@ public: | |||
| if (this != &other) | |||
| { | |||
| ReferenceCountedArray<ObjectClass, TypeOfCriticalSectionToUse> otherCopy (other); | |||
| swapWithArray (other); | |||
| swapWithArray (otherCopy); | |||
| } | |||
| return *this; | |||
| @@ -10363,11 +10363,23 @@ public: | |||
| return Rectangle (x + deltaPosition.getX(), y + deltaPosition.getY(), w, h); | |||
| } | |||
| Rectangle& operator+= (const Point<ValueType>& deltaPosition) throw() | |||
| { | |||
| x += deltaPosition.getX(); y += deltaPosition.getY(); | |||
| return *this; | |||
| } | |||
| const Rectangle operator- (const Point<ValueType>& deltaPosition) const throw() | |||
| { | |||
| return Rectangle (x - deltaPosition.getX(), y - deltaPosition.getY(), w, h); | |||
| } | |||
| Rectangle& operator-= (const Point<ValueType>& deltaPosition) throw() | |||
| { | |||
| x -= deltaPosition.getX(); y -= deltaPosition.getY(); | |||
| return *this; | |||
| } | |||
| void expand (const ValueType deltaX, | |||
| const ValueType deltaY) throw() | |||
| { | |||
| @@ -16449,13 +16461,15 @@ public: | |||
| bool autoScroll (int mouseX, int mouseY, int distanceFromEdge, int maximumSpeed); | |||
| int getViewPositionX() const throw() { return lastVX; } | |||
| const Point<int> getViewPosition() const throw() { return lastViewPos.getPosition(); } | |||
| int getViewPositionX() const throw() { return lastViewPos.getX(); } | |||
| int getViewPositionY() const throw() { return lastVY; } | |||
| int getViewPositionY() const throw() { return lastViewPos.getY(); } | |||
| int getViewWidth() const throw() { return lastVW; } | |||
| int getViewWidth() const throw() { return lastViewPos.getWidth(); } | |||
| int getViewHeight() const throw() { return lastVH; } | |||
| int getViewHeight() const throw() { return lastViewPos.getHeight(); } | |||
| int getMaximumVisibleWidth() const throw(); | |||
| @@ -16494,7 +16508,7 @@ public: | |||
| private: | |||
| Component::SafePointer<Component> contentComp; | |||
| int lastVX, lastVY, lastVW, lastVH; | |||
| Rectangle<int> lastViewPos; | |||
| int scrollBarThickness; | |||
| int singleStepX, singleStepY; | |||
| bool showHScrollbar, showVScrollbar; | |||
| @@ -16503,6 +16517,7 @@ private: | |||
| ScrollBar* horizontalScrollBar; | |||
| void updateVisibleRegion(); | |||
| Viewport (const Viewport&); | |||
| Viewport& operator= (const Viewport&); | |||
| }; | |||
| @@ -22620,6 +22635,8 @@ public: | |||
| virtual const File getSelectedFile (int index) const = 0; | |||
| virtual void deselectAllFiles() = 0; | |||
| virtual void scrollToTop() = 0; | |||
| void addListener (FileBrowserListener* listener); | |||
| @@ -22721,6 +22738,8 @@ public: | |||
| const File getSelectedFile (int index) const throw(); | |||
| void deselectAllFiles(); | |||
| bool currentFileIsValid() const; | |||
| const File getHighlightedFile() const throw(); | |||
| @@ -23530,6 +23549,8 @@ public: | |||
| const File getSelectedFile (int index = 0) const; | |||
| void deselectAllFiles(); | |||
| void scrollToTop(); | |||
| void changeListenerCallback (void*); | |||
| @@ -23740,6 +23761,8 @@ public: | |||
| const File getSelectedFile (int index = 0) const; | |||
| void deselectAllFiles(); | |||
| void scrollToTop(); | |||
| void setDragAndDropDescription (const String& description); | |||
| @@ -25890,7 +25913,7 @@ public: | |||
| virtual ~LassoSource() {} | |||
| virtual void findLassoItemsInArea (Array <SelectableItemType>& itemsFound, | |||
| int x, int y, int width, int height) = 0; | |||
| const Rectangle<int>& area) = 0; | |||
| virtual SelectedItemSet <SelectableItemType>& getLassoSelection() = 0; | |||
| }; | |||
| @@ -25923,17 +25946,18 @@ public: | |||
| originalSelection = lassoSource->getLassoSelection().getItemArray(); | |||
| setSize (0, 0); | |||
| dragStartPos = e.getMouseDownPosition(); | |||
| } | |||
| void dragLasso (const MouseEvent& e) | |||
| { | |||
| if (source != 0) | |||
| { | |||
| setBounds (Rectangle<int> (e.getMouseDownPosition(), e.getPosition())); | |||
| setBounds (Rectangle<int> (dragStartPos, e.getPosition())); | |||
| setVisible (true); | |||
| Array <SelectableItemType> itemsInLasso; | |||
| source->findLassoItemsInArea (itemsInLasso, getX(), getY(), getWidth(), getHeight()); | |||
| source->findLassoItemsInArea (itemsInLasso, getBounds()); | |||
| if (e.mods.isShiftDown()) | |||
| { | |||
| @@ -25987,6 +26011,7 @@ private: | |||
| Array <SelectableItemType> originalSelection; | |||
| LassoSource <SelectableItemType>* source; | |||
| int outlineThickness; | |||
| Point<int> dragStartPos; | |||
| }; | |||
| #endif // __JUCE_LASSOCOMPONENT_JUCEHEADER__ | |||
| @@ -277,7 +277,7 @@ XmlElement* AudioProcessor::getXmlFromBinary (const void* data, | |||
| const int sizeInBytes) | |||
| { | |||
| if (sizeInBytes > 8 | |||
| && ByteOrder::littleEndianInt ((const char*) data) == magicXmlNumber) | |||
| && ByteOrder::littleEndianInt (data) == magicXmlNumber) | |||
| { | |||
| const int stringLength = (int) ByteOrder::littleEndianInt (((const char*) data) + 4); | |||
| @@ -80,7 +80,7 @@ public: | |||
| if (this != &other) | |||
| { | |||
| ReferenceCountedArray<ObjectClass, TypeOfCriticalSectionToUse> otherCopy (other); | |||
| swapWithArray (other); | |||
| swapWithArray (otherCopy); | |||
| } | |||
| return *this; | |||
| @@ -40,7 +40,7 @@ class TreeViewContentComponent : public Component, | |||
| public TooltipClient | |||
| { | |||
| public: | |||
| TreeViewContentComponent (TreeView* const owner_) | |||
| TreeViewContentComponent (TreeView& owner_) | |||
| : owner (owner_), | |||
| buttonUnderMouse (0), | |||
| isDragging (false) | |||
| @@ -67,9 +67,9 @@ public: | |||
| // (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.openCloseButtonsVisible) | |||
| { | |||
| if (e.x >= pos.getX() - owner->getIndentSize()) | |||
| if (e.x >= pos.getX() - owner.getIndentSize()) | |||
| item->setOpen (! item->isOpen()); | |||
| // (clicks to the left of an open/close button are ignored) | |||
| @@ -77,7 +77,7 @@ public: | |||
| else | |||
| { | |||
| // mouse-down inside the body of the item.. | |||
| if (! owner->isMultiSelectEnabled()) | |||
| if (! owner.isMultiSelectEnabled()) | |||
| item->setSelected (true, true); | |||
| else if (item->isSelected()) | |||
| needSelectionOnMouseUp = ! e.mods.isPopupMenu(); | |||
| @@ -110,7 +110,7 @@ public: | |||
| Rectangle<int> pos; | |||
| TreeViewItem* const item = findItemAt (e.y, pos); | |||
| if (item != 0 && (e.x >= pos.getX() || ! owner->openCloseButtonsVisible)) | |||
| if (item != 0 && (e.x >= pos.getX() || ! owner.openCloseButtonsVisible)) | |||
| item->itemDoubleClicked (e.withNewPosition (e.getPosition() - pos.getPosition())); | |||
| } | |||
| } | |||
| @@ -143,7 +143,7 @@ public: | |||
| dragImage->multiplyAllAlphas (0.6f); | |||
| Point<int> imageOffset (pos.getX() - e.x, pos.getY() - e.y); | |||
| dragContainer->startDragging (dragDescription, owner, dragImage, true, &imageOffset); | |||
| dragContainer->startDragging (dragDescription, &owner, dragImage, true, &imageOffset); | |||
| } | |||
| else | |||
| { | |||
| @@ -166,25 +166,37 @@ public: | |||
| updateButtonUnderMouse (e); | |||
| } | |||
| void paint (Graphics& g); | |||
| TreeViewItem* findItemAt (int y, Rectangle<int>& itemPosition) const; | |||
| void paint (Graphics& g) | |||
| { | |||
| if (owner.rootItem != 0) | |||
| { | |||
| owner.handleAsyncUpdate(); | |||
| static bool isMouseDraggingInChildCompOf (Component* const comp) | |||
| if (! owner.rootItemVisible) | |||
| g.setOrigin (0, -owner.rootItem->itemHeight); | |||
| owner.rootItem->paintRecursively (g, getWidth()); | |||
| } | |||
| } | |||
| TreeViewItem* findItemAt (int y, Rectangle<int>& itemPosition) const | |||
| { | |||
| for (int i = Desktop::getInstance().getNumMouseSources(); --i >= 0;) | |||
| if (owner.rootItem != 0) | |||
| { | |||
| MouseInputSource* source = Desktop::getInstance().getMouseSource(i); | |||
| owner.handleAsyncUpdate(); | |||
| if (source->isDragging()) | |||
| { | |||
| Component* const underMouse = source->getComponentUnderMouse(); | |||
| if (! owner.rootItemVisible) | |||
| y += owner.rootItem->itemHeight; | |||
| if (underMouse != 0 && (comp == underMouse || comp->isParentOf (underMouse))) | |||
| return true; | |||
| } | |||
| TreeViewItem* const ti = owner.rootItem->findItemRecursively (y); | |||
| if (ti != 0) | |||
| itemPosition = ti->getItemPosition (false); | |||
| return ti; | |||
| } | |||
| return false; | |||
| return 0; | |||
| } | |||
| void updateComponents() | |||
| @@ -193,8 +205,8 @@ public: | |||
| const int visibleBottom = visibleTop + getParentHeight(); | |||
| BigInteger itemsToKeep; | |||
| TreeViewItem* item = owner->rootItem; | |||
| int y = (item != 0 && !owner->rootItemVisible) ? -item->itemHeight : 0; | |||
| TreeViewItem* item = owner.rootItem; | |||
| int y = (item != 0 && ! owner.rootItemVisible) ? -item->itemHeight : 0; | |||
| while (item != 0 && y < visibleBottom) | |||
| { | |||
| @@ -268,12 +280,12 @@ public: | |||
| { | |||
| TreeViewItem* newItem = 0; | |||
| if (owner->openCloseButtonsVisible) | |||
| if (owner.openCloseButtonsVisible) | |||
| { | |||
| Rectangle<int> pos; | |||
| TreeViewItem* item = findItemAt (e.y, pos); | |||
| if (item != 0 && e.x < pos.getX() && e.x >= pos.getX() - owner->getIndentSize()) | |||
| if (item != 0 && e.x < pos.getX() && e.x >= pos.getX() - owner.getIndentSize()) | |||
| { | |||
| newItem = item; | |||
| @@ -300,14 +312,14 @@ public: | |||
| } | |||
| } | |||
| bool isMouseOverButton (TreeViewItem* item) const throw() | |||
| bool isMouseOverButton (TreeViewItem* const item) const throw() | |||
| { | |||
| return item == buttonUnderMouse; | |||
| } | |||
| void resized() | |||
| { | |||
| owner->itemsChanged(); | |||
| owner.itemsChanged(); | |||
| } | |||
| const String getTooltip() | |||
| @@ -318,31 +330,27 @@ public: | |||
| if (item != 0) | |||
| return item->getTooltip(); | |||
| return owner->getTooltip(); | |||
| return owner.getTooltip(); | |||
| } | |||
| //============================================================================== | |||
| juce_UseDebuggingNewOperator | |||
| private: | |||
| TreeView* const owner; | |||
| TreeView& owner; | |||
| Array <TreeViewItem*> rowComponentItems; | |||
| Array <int> rowComponentIds; | |||
| Array <Component*> rowComponents; | |||
| TreeViewItem* buttonUnderMouse; | |||
| bool isDragging, needSelectionOnMouseUp; | |||
| TreeViewContentComponent (const TreeViewContentComponent&); | |||
| TreeViewContentComponent& operator= (const TreeViewContentComponent&); | |||
| void selectBasedOnModifiers (TreeViewItem* const item, const ModifierKeys& modifiers) | |||
| { | |||
| TreeViewItem* firstSelected = 0; | |||
| if (modifiers.isShiftDown() && ((firstSelected = owner->getSelectedItem (0)) != 0)) | |||
| if (modifiers.isShiftDown() && ((firstSelected = owner.getSelectedItem (0)) != 0)) | |||
| { | |||
| TreeViewItem* const lastSelected = owner->getSelectedItem (owner->getNumSelectedItems() - 1); | |||
| TreeViewItem* const lastSelected = owner.getSelectedItem (owner.getNumSelectedItems() - 1); | |||
| jassert (lastSelected != 0); | |||
| int rowStart = firstSelected->getRowNumberInTree(); | |||
| @@ -357,13 +365,12 @@ private: | |||
| swapVariables (ourRow, otherEnd); | |||
| for (int i = ourRow; i <= otherEnd; ++i) | |||
| owner->getItemOnRow (i)->setSelected (true, false); | |||
| owner.getItemOnRow (i)->setSelected (true, false); | |||
| } | |||
| else | |||
| { | |||
| const bool cmd = modifiers.isCommandDown(); | |||
| item->setSelected ((! cmd) || (! item->isSelected()), ! cmd); | |||
| const bool cmd = modifiers.isCommandDown(); | |||
| item->setSelected ((! cmd) || ! item->isSelected(), ! cmd); | |||
| } | |||
| } | |||
| @@ -375,33 +382,63 @@ private: | |||
| return false; | |||
| } | |||
| static bool isMouseDraggingInChildCompOf (Component* const comp) | |||
| { | |||
| for (int i = Desktop::getInstance().getNumMouseSources(); --i >= 0;) | |||
| { | |||
| MouseInputSource* const source = Desktop::getInstance().getMouseSource(i); | |||
| if (source->isDragging()) | |||
| { | |||
| Component* const underMouse = source->getComponentUnderMouse(); | |||
| if (underMouse != 0 && (comp == underMouse || comp->isParentOf (underMouse))) | |||
| return true; | |||
| } | |||
| } | |||
| return false; | |||
| } | |||
| TreeViewContentComponent (const TreeViewContentComponent&); | |||
| TreeViewContentComponent& operator= (const TreeViewContentComponent&); | |||
| }; | |||
| //============================================================================== | |||
| class TreeView::TreeViewport : public Viewport | |||
| { | |||
| public: | |||
| TreeViewport() throw() {} | |||
| ~TreeViewport() throw() {} | |||
| TreeViewport() throw() : lastX (-1) {} | |||
| ~TreeViewport() throw() {} | |||
| void updateComponents() | |||
| void updateComponents (const bool triggerResize = false) | |||
| { | |||
| TreeViewContentComponent* const tvc = static_cast <TreeViewContentComponent*> (getViewedComponent()); | |||
| if (tvc != 0) | |||
| tvc->updateComponents(); | |||
| { | |||
| if (triggerResize) | |||
| tvc->resized(); | |||
| else | |||
| tvc->updateComponents(); | |||
| } | |||
| repaint(); | |||
| } | |||
| void visibleAreaChanged (int, int, int, int) | |||
| void visibleAreaChanged (int x, int, int, int) | |||
| { | |||
| updateComponents(); | |||
| const bool hasScrolledSideways = (x != lastX); | |||
| lastX = x; | |||
| updateComponents (hasScrolledSideways); | |||
| } | |||
| //============================================================================== | |||
| juce_UseDebuggingNewOperator | |||
| private: | |||
| int lastX; | |||
| TreeViewport (const TreeViewport&); | |||
| TreeViewport& operator= (const TreeViewport&); | |||
| }; | |||
| @@ -421,7 +458,7 @@ TreeView::TreeView (const String& componentName) | |||
| openCloseButtonsVisible (true) | |||
| { | |||
| addAndMakeVisible (viewport = new TreeViewport()); | |||
| viewport->setViewedComponent (new TreeViewContentComponent (this)); | |||
| viewport->setViewedComponent (new TreeViewContentComponent (*this)); | |||
| viewport->setWantsKeyboardFocus (false); | |||
| setWantsKeyboardFocus (true); | |||
| } | |||
| @@ -1054,40 +1091,6 @@ void TreeView::itemDropped (const String& sourceDescription, Component* sourceCo | |||
| handleDrop (StringArray(), sourceDescription, sourceComponent, x, y); | |||
| } | |||
| //============================================================================== | |||
| void TreeViewContentComponent::paint (Graphics& g) | |||
| { | |||
| if (owner->rootItem != 0) | |||
| { | |||
| owner->handleAsyncUpdate(); | |||
| if (! owner->rootItemVisible) | |||
| g.setOrigin (0, -owner->rootItem->itemHeight); | |||
| owner->rootItem->paintRecursively (g, getWidth()); | |||
| } | |||
| } | |||
| TreeViewItem* TreeViewContentComponent::findItemAt (int y, Rectangle<int>& itemPosition) const | |||
| { | |||
| if (owner->rootItem != 0) | |||
| { | |||
| owner->handleAsyncUpdate(); | |||
| if (! owner->rootItemVisible) | |||
| y += owner->rootItem->itemHeight; | |||
| TreeViewItem* const ti = owner->rootItem->findItemRecursively (y); | |||
| if (ti != 0) | |||
| itemPosition = ti->getItemPosition (false); | |||
| return ti; | |||
| } | |||
| return 0; | |||
| } | |||
| //============================================================================== | |||
| enum TreeViewOpenness | |||
| { | |||
| @@ -1309,7 +1312,6 @@ void TreeViewItem::itemDropped (const String& /*sourceDescription*/, Component* | |||
| const Rectangle<int> TreeViewItem::getItemPosition (const bool relativeToTreeViewTopLeft) const throw() | |||
| { | |||
| const int indentX = getIndentX(); | |||
| int width = itemWidth; | |||
| if (ownerView != 0 && width < 0) | |||
| @@ -1318,8 +1320,7 @@ const Rectangle<int> TreeViewItem::getItemPosition (const bool relativeToTreeVie | |||
| Rectangle<int> r (indentX, y, jmax (0, width), totalHeight); | |||
| if (relativeToTreeViewTopLeft) | |||
| r.setPosition (r.getX() - ownerView->viewport->getViewPositionX(), | |||
| r.getY() - ownerView->viewport->getViewPositionY()); | |||
| r -= ownerView->viewport->getViewPosition(); | |||
| return r; | |||
| } | |||
| @@ -59,6 +59,9 @@ public: | |||
| */ | |||
| virtual const File getSelectedFile (int index) const = 0; | |||
| /** Deselects any selected files. */ | |||
| virtual void deselectAllFiles() = 0; | |||
| /** Scrolls this view to the top. */ | |||
| virtual void scrollToTop() = 0; | |||
| @@ -195,6 +195,11 @@ const File FileBrowserComponent::getHighlightedFile() const throw() | |||
| return fileListComponent->getSelectedFile (0); | |||
| } | |||
| void FileBrowserComponent::deselectAllFiles() | |||
| { | |||
| fileListComponent->deselectAllFiles(); | |||
| } | |||
| //============================================================================== | |||
| bool FileBrowserComponent::isFileSuitable (const File& file) const | |||
| { | |||
| @@ -114,6 +114,10 @@ public: | |||
| */ | |||
| const File getSelectedFile (int index) const throw(); | |||
| /** Deselects any files that are currently selected. | |||
| */ | |||
| void deselectAllFiles(); | |||
| /** Returns true if the currently selected file(s) are usable. | |||
| This can be used to decide whether the user can press "ok" for the | |||
| @@ -60,6 +60,11 @@ const File FileListComponent::getSelectedFile (int index) const | |||
| return fileList.getFile (getSelectedRow (index)); | |||
| } | |||
| void FileListComponent::deselectAllFiles() | |||
| { | |||
| deselectAllRows(); | |||
| } | |||
| void FileListComponent::scrollToTop() | |||
| { | |||
| getVerticalScrollBar()->setCurrentRangeStart (0); | |||
| @@ -70,6 +70,9 @@ public: | |||
| */ | |||
| const File getSelectedFile (int index = 0) const; | |||
| /** Deselects any files that are currently selected. */ | |||
| void deselectAllFiles(); | |||
| /** Scrolls to the top of the list. */ | |||
| void scrollToTop(); | |||
| @@ -250,10 +250,13 @@ const File FileTreeComponent::getSelectedFile (const int index) const | |||
| { | |||
| const FileListTreeItem* const item = dynamic_cast <const FileListTreeItem*> (getSelectedItem (index)); | |||
| if (item != 0) | |||
| return item->file; | |||
| return item != 0 ? item->file | |||
| : File::nonexistent; | |||
| } | |||
| return File::nonexistent; | |||
| void FileTreeComponent::deselectAllFiles() | |||
| { | |||
| clearSelectedItems(); | |||
| } | |||
| void FileTreeComponent::scrollToTop() | |||
| @@ -66,6 +66,9 @@ public: | |||
| */ | |||
| const File getSelectedFile (int index = 0) const; | |||
| /** Deselects any files that are currently selected. */ | |||
| void deselectAllFiles(); | |||
| /** Scrolls the list to the top. */ | |||
| void scrollToTop(); | |||
| @@ -35,10 +35,6 @@ BEGIN_JUCE_NAMESPACE | |||
| Viewport::Viewport (const String& componentName) | |||
| : Component (componentName), | |||
| contentComp (0), | |||
| lastVX (0), | |||
| lastVY (0), | |||
| lastVW (0), | |||
| lastVH (0), | |||
| scrollBarThickness (0), | |||
| singleStepX (16), | |||
| singleStepY (16), | |||
| @@ -106,16 +102,14 @@ int Viewport::getMaximumVisibleHeight() const throw() | |||
| return jmax (0, getHeight() - (horizontalScrollBar->isVisible() ? getScrollBarThickness() : 0)); | |||
| } | |||
| void Viewport::setViewPosition (const int xPixelsOffset, | |||
| const int yPixelsOffset) | |||
| void Viewport::setViewPosition (const int xPixelsOffset, const int yPixelsOffset) | |||
| { | |||
| if (contentComp != 0) | |||
| contentComp->setTopLeftPosition (-xPixelsOffset, | |||
| -yPixelsOffset); | |||
| } | |||
| void Viewport::setViewPositionProportionately (const double x, | |||
| const double y) | |||
| void Viewport::setViewPositionProportionately (const double x, const double y) | |||
| { | |||
| if (contentComp != 0) | |||
| setViewPosition (jmax (0, roundToInt (x * (contentComp->getWidth() - getWidth()))), | |||
| @@ -128,25 +122,31 @@ bool Viewport::autoScroll (int mouseX, int mouseY, int activeBorderThickness, in | |||
| { | |||
| int dx = 0, dy = 0; | |||
| if (mouseX < activeBorderThickness) | |||
| dx = activeBorderThickness - mouseX; | |||
| else if (mouseX >= contentHolder->getWidth() - activeBorderThickness) | |||
| dx = (contentHolder->getWidth() - activeBorderThickness) - mouseX; | |||
| if (dx < 0) | |||
| dx = jmax (dx, -maximumSpeed, contentHolder->getWidth() - contentComp->getRight()); | |||
| else | |||
| dx = jmin (dx, maximumSpeed, -contentComp->getX()); | |||
| if (mouseY < activeBorderThickness) | |||
| dy = activeBorderThickness - mouseY; | |||
| else if (mouseY >= contentHolder->getHeight() - activeBorderThickness) | |||
| dy = (contentHolder->getHeight() - activeBorderThickness) - mouseY; | |||
| if (horizontalScrollBar->isVisible()) | |||
| { | |||
| if (mouseX < activeBorderThickness) | |||
| dx = activeBorderThickness - mouseX; | |||
| else if (mouseX >= contentHolder->getWidth() - activeBorderThickness) | |||
| dx = (contentHolder->getWidth() - activeBorderThickness) - mouseX; | |||
| if (dx < 0) | |||
| dx = jmax (dx, -maximumSpeed, contentHolder->getWidth() - contentComp->getRight()); | |||
| else | |||
| dx = jmin (dx, maximumSpeed, -contentComp->getX()); | |||
| } | |||
| if (dy < 0) | |||
| dy = jmax (dy, -maximumSpeed, contentHolder->getHeight() - contentComp->getBottom()); | |||
| else | |||
| dy = jmin (dy, maximumSpeed, -contentComp->getY()); | |||
| if (verticalScrollBar->isVisible()) | |||
| { | |||
| if (mouseY < activeBorderThickness) | |||
| dy = activeBorderThickness - mouseY; | |||
| else if (mouseY >= contentHolder->getHeight() - activeBorderThickness) | |||
| dy = (contentHolder->getHeight() - activeBorderThickness) - mouseY; | |||
| if (dy < 0) | |||
| dy = jmax (dy, -maximumSpeed, contentHolder->getHeight() - contentComp->getBottom()); | |||
| else | |||
| dy = jmin (dy, maximumSpeed, -contentComp->getY()); | |||
| } | |||
| if (dx != 0 || dy != 0) | |||
| { | |||
| @@ -176,10 +176,10 @@ void Viewport::updateVisibleRegion() | |||
| { | |||
| if (contentComp != 0) | |||
| { | |||
| const int newVX = -contentComp->getX(); | |||
| const int newVY = -contentComp->getY(); | |||
| Rectangle<int> newViewPos; | |||
| newViewPos.setPosition (-contentComp->getPosition()); | |||
| if (newVX == 0 && newVY == 0 | |||
| if (newViewPos.getX() == 0 && newViewPos.getY() == 0 | |||
| && contentComp->getWidth() <= getWidth() | |||
| && contentComp->getHeight() <= getHeight()) | |||
| { | |||
| @@ -188,14 +188,14 @@ void Viewport::updateVisibleRegion() | |||
| } | |||
| horizontalScrollBar->setRangeLimits (0.0, contentComp->getWidth()); | |||
| horizontalScrollBar->setCurrentRange (newVX, getMaximumVisibleWidth()); | |||
| horizontalScrollBar->setCurrentRange (newViewPos.getX(), getMaximumVisibleWidth()); | |||
| horizontalScrollBar->setSingleStepSize (singleStepX); | |||
| if (! (contentComp->getWidth() > 0 && showHScrollbar && getHeight() > getScrollBarThickness())) | |||
| horizontalScrollBar->setVisible (! horizontalScrollBar->autoHides()); | |||
| verticalScrollBar->setRangeLimits (0.0, contentComp->getHeight()); | |||
| verticalScrollBar->setCurrentRange (newVY, getMaximumVisibleHeight()); | |||
| verticalScrollBar->setCurrentRange (newViewPos.getY(), getMaximumVisibleHeight()); | |||
| verticalScrollBar->setSingleStepSize (singleStepY); | |||
| if (! (contentComp->getHeight() > 0 && showVScrollbar && getWidth() > getScrollBarThickness())) | |||
| @@ -203,8 +203,8 @@ void Viewport::updateVisibleRegion() | |||
| if (verticalScrollBar->isVisible()) | |||
| { | |||
| horizontalScrollBar->setCurrentRange (newVX, getMaximumVisibleWidth()); | |||
| verticalScrollBar->setCurrentRange (newVY, getMaximumVisibleHeight()); | |||
| horizontalScrollBar->setCurrentRange (newViewPos.getX(), getMaximumVisibleWidth()); | |||
| verticalScrollBar->setCurrentRange (newViewPos.getY(), getMaximumVisibleHeight()); | |||
| verticalScrollBar | |||
| ->setBounds (getMaximumVisibleWidth(), 0, | |||
| @@ -213,7 +213,7 @@ void Viewport::updateVisibleRegion() | |||
| if (horizontalScrollBar->isVisible()) | |||
| { | |||
| horizontalScrollBar->setCurrentRange (newVX, getMaximumVisibleWidth()); | |||
| horizontalScrollBar->setCurrentRange (newViewPos.getX(), getMaximumVisibleWidth()); | |||
| horizontalScrollBar | |||
| ->setBounds (0, getMaximumVisibleHeight(), | |||
| @@ -223,20 +223,13 @@ void Viewport::updateVisibleRegion() | |||
| contentHolder->setSize (getMaximumVisibleWidth(), | |||
| getMaximumVisibleHeight()); | |||
| const int newVW = jmin (contentComp->getRight(), getMaximumVisibleWidth()); | |||
| const int newVH = jmin (contentComp->getBottom(), getMaximumVisibleHeight()); | |||
| newViewPos.setSize (jmin (contentComp->getRight(), getMaximumVisibleWidth()), | |||
| jmin (contentComp->getBottom(), getMaximumVisibleHeight())); | |||
| if (newVX != lastVX | |||
| || newVY != lastVY | |||
| || newVW != lastVW | |||
| || newVH != lastVH) | |||
| if (lastViewPos != newViewPos) | |||
| { | |||
| lastVX = newVX; | |||
| lastVY = newVY; | |||
| lastVW = newVW; | |||
| lastVH = newVH; | |||
| visibleAreaChanged (newVX, newVY, newVW, newVH); | |||
| lastViewPos = newViewPos; | |||
| visibleAreaChanged (newViewPos.getX(), newViewPos.getY(), newViewPos.getWidth(), newViewPos.getHeight()); | |||
| } | |||
| horizontalScrollBar->handleUpdateNowIfNeeded(); | |||
| @@ -250,8 +243,7 @@ void Viewport::updateVisibleRegion() | |||
| } | |||
| //============================================================================== | |||
| void Viewport::setSingleStepSizes (const int stepX, | |||
| const int stepY) | |||
| void Viewport::setSingleStepSizes (const int stepX, const int stepY) | |||
| { | |||
| singleStepX = stepX; | |||
| singleStepY = stepY; | |||
| @@ -119,29 +119,33 @@ public: | |||
| */ | |||
| bool autoScroll (int mouseX, int mouseY, int distanceFromEdge, int maximumSpeed); | |||
| /** Returns the position within the child component of the top-left of its visible area. | |||
| */ | |||
| const Point<int> getViewPosition() const throw() { return lastViewPos.getPosition(); } | |||
| /** Returns the position within the child component of the top-left of its visible area. | |||
| @see getViewWidth, setViewPosition | |||
| */ | |||
| int getViewPositionX() const throw() { return lastVX; } | |||
| int getViewPositionX() const throw() { return lastViewPos.getX(); } | |||
| /** Returns the position within the child component of the top-left of its visible area. | |||
| @see getViewHeight, setViewPosition | |||
| */ | |||
| int getViewPositionY() const throw() { return lastVY; } | |||
| int getViewPositionY() const throw() { return lastViewPos.getY(); } | |||
| /** Returns the width of the visible area of the child component. | |||
| This may be less than the width of this Viewport if there's a vertical scrollbar | |||
| or if the child component is itself smaller. | |||
| */ | |||
| int getViewWidth() const throw() { return lastVW; } | |||
| int getViewWidth() const throw() { return lastViewPos.getWidth(); } | |||
| /** Returns the height of the visible area of the child component. | |||
| This may be less than the height of this Viewport if there's a horizontal scrollbar | |||
| or if the child component is itself smaller. | |||
| */ | |||
| int getViewHeight() const throw() { return lastVH; } | |||
| int getViewHeight() const throw() { return lastViewPos.getHeight(); } | |||
| /** Returns the width available within this component for the contents. | |||
| @@ -241,7 +245,7 @@ public: | |||
| private: | |||
| Component::SafePointer<Component> contentComp; | |||
| int lastVX, lastVY, lastVW, lastVH; | |||
| Rectangle<int> lastViewPos; | |||
| int scrollBarThickness; | |||
| int singleStepX, singleStepY; | |||
| bool showHScrollbar, showVScrollbar; | |||
| @@ -250,6 +254,7 @@ private: | |||
| ScrollBar* horizontalScrollBar; | |||
| void updateVisibleRegion(); | |||
| Viewport (const Viewport&); | |||
| Viewport& operator= (const Viewport&); | |||
| }; | |||
| @@ -56,7 +56,7 @@ public: | |||
| component itself). | |||
| */ | |||
| virtual void findLassoItemsInArea (Array <SelectableItemType>& itemsFound, | |||
| int x, int y, int width, int height) = 0; | |||
| const Rectangle<int>& area) = 0; | |||
| /** Returns the SelectedItemSet that the lasso should update. | |||
| @@ -141,6 +141,7 @@ public: | |||
| originalSelection = lassoSource->getLassoSelection().getItemArray(); | |||
| setSize (0, 0); | |||
| dragStartPos = e.getMouseDownPosition(); | |||
| } | |||
| /** Call this in your mouseDrag event, to update the lasso's position. | |||
| @@ -159,11 +160,11 @@ public: | |||
| { | |||
| if (source != 0) | |||
| { | |||
| setBounds (Rectangle<int> (e.getMouseDownPosition(), e.getPosition())); | |||
| setBounds (Rectangle<int> (dragStartPos, e.getPosition())); | |||
| setVisible (true); | |||
| Array <SelectableItemType> itemsInLasso; | |||
| source->findLassoItemsInArea (itemsInLasso, getX(), getY(), getWidth(), getHeight()); | |||
| source->findLassoItemsInArea (itemsInLasso, getBounds()); | |||
| if (e.mods.isShiftDown()) | |||
| { | |||
| @@ -236,6 +237,7 @@ private: | |||
| Array <SelectableItemType> originalSelection; | |||
| LassoSource <SelectableItemType>* source; | |||
| int outlineThickness; | |||
| Point<int> dragStartPos; | |||
| }; | |||
| @@ -233,12 +233,26 @@ public: | |||
| return Rectangle (x + deltaPosition.getX(), y + deltaPosition.getY(), w, h); | |||
| } | |||
| /** Moves this rectangle by a given amount. */ | |||
| Rectangle& operator+= (const Point<ValueType>& deltaPosition) throw() | |||
| { | |||
| x += deltaPosition.getX(); y += deltaPosition.getY(); | |||
| return *this; | |||
| } | |||
| /** Returns a rectangle which is the same as this one moved by a given amount. */ | |||
| const Rectangle operator- (const Point<ValueType>& deltaPosition) const throw() | |||
| { | |||
| return Rectangle (x - deltaPosition.getX(), y - deltaPosition.getY(), w, h); | |||
| } | |||
| /** Moves this rectangle by a given amount. */ | |||
| Rectangle& operator-= (const Point<ValueType>& deltaPosition) throw() | |||
| { | |||
| x -= deltaPosition.getX(); y -= deltaPosition.getY(); | |||
| return *this; | |||
| } | |||
| /** Expands the rectangle by a given amount. | |||
| Effectively, its new size is (x - deltaX, y - deltaY, w + deltaX * 2, h + deltaY * 2). | |||
| @@ -302,27 +302,32 @@ public: | |||
| { | |||
| const KeyPress& kp = keyPresses.getReference(0); | |||
| juce_wchar key = kp.getTextCharacter(); | |||
| if (kp.getKeyCode() == KeyPress::backspaceKey) | |||
| key = NSBackspaceCharacter; | |||
| else if (kp.getKeyCode() == KeyPress::deleteKey) | |||
| key = NSDeleteCharacter; | |||
| else if (key == 0) | |||
| key = (juce_wchar) kp.getKeyCode(); | |||
| unsigned int mods = 0; | |||
| if (kp.getModifiers().isShiftDown()) | |||
| mods |= NSShiftKeyMask; | |||
| if (kp.getModifiers().isCtrlDown()) | |||
| mods |= NSControlKeyMask; | |||
| if (kp.getModifiers().isAltDown()) | |||
| mods |= NSAlternateKeyMask; | |||
| if (kp.getModifiers().isCommandDown()) | |||
| mods |= NSCommandKeyMask; | |||
| [item setKeyEquivalent: juceStringToNS (String::charToString (key))]; | |||
| [item setKeyEquivalentModifierMask: mods]; | |||
| if (kp.getKeyCode() != KeyPress::backspaceKey | |||
| && kp.getKeyCode() != KeyPress::deleteKey) // (adding these is annoying because it flashes the menu bar | |||
| // every time you press the key while editing text) | |||
| { | |||
| juce_wchar key = kp.getTextCharacter(); | |||
| if (kp.getKeyCode() == KeyPress::backspaceKey) | |||
| key = NSBackspaceCharacter; | |||
| else if (kp.getKeyCode() == KeyPress::deleteKey) | |||
| key = NSDeleteCharacter; | |||
| else if (key == 0) | |||
| key = (juce_wchar) kp.getKeyCode(); | |||
| unsigned int mods = 0; | |||
| if (kp.getModifiers().isShiftDown()) | |||
| mods |= NSShiftKeyMask; | |||
| if (kp.getModifiers().isCtrlDown()) | |||
| mods |= NSControlKeyMask; | |||
| if (kp.getModifiers().isAltDown()) | |||
| mods |= NSAlternateKeyMask; | |||
| if (kp.getModifiers().isCommandDown()) | |||
| mods |= NSCommandKeyMask; | |||
| [item setKeyEquivalent: juceStringToNS (String::charToString (key))]; | |||
| [item setKeyEquivalentModifierMask: mods]; | |||
| } | |||
| } | |||
| } | |||
| } | |||